mirror of
https://github.com/borgesdan/xn65
synced 2024-12-29 21:54:47 +01:00
commit
52ac1447c1
@ -9,6 +9,8 @@ if (POLICY CMP0141)
|
||||
set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "$<IF:$<AND:$<C_COMPILER_ID:MSVC>,$<CXX_COMPILER_ID:MSVC>>,$<$<CONFIG:Debug,RelWithDebInfo>:EditAndContinue>,$<$<CONFIG:Debug,RelWithDebInfo>:ProgramDatabase>>")
|
||||
endif()
|
||||
|
||||
set(ENV{VCPKG_ROOT} C:\\vcpkg)
|
||||
|
||||
project ("xna")
|
||||
|
||||
# Include sub-projects.
|
||||
|
@ -3,7 +3,43 @@
|
||||
#
|
||||
|
||||
# Add source to this project's executable.
|
||||
add_executable (xna WIN32 "xna.cpp" "xna.h" "platform/window-dx.cpp" "platform/device-dx.cpp" "platform/adapter-dx.cpp" "platform/swapchain-dx.cpp" "platform/rendertarget-dx.cpp" "platform/texture-dx.cpp" "platform/blendstate-dx.cpp" "platform/game-dx.cpp" "platform/clock-dx.cpp" "csharp/stream.cpp" "platform/gdevicemanager-dx.cpp" "platform/vertexinput-dx.cpp" "platform/shader-dx.cpp" "platform/rasterizerstate-dx.cpp" "platform/vertexbuffer-dx.cpp" "platform/indexbuffer-dx.cpp" "common/matrix.cpp" "platform/constbuffer-dx.cpp" "platform/databuffer-dx.cpp" "platform/samplerstate-dx.cpp" "platform/spritebatch-dx.cpp" "platform/spritefont-dx.cpp" "platform/depthstencilstate-dx.cpp" "platform/keyboard-dx.cpp" "platform/mouse-dx.cpp" "platform/gamepad-dx.cpp" "common/vectors.cpp" "platform/soundeffect-dx.cpp" "platform/displaymode-dx.cpp" "platform/presentparameters-dx.cpp" "game/component.cpp" "content/manager.cpp" "content/reader.cpp" "csharp/binary.cpp")
|
||||
add_executable (xna WIN32
|
||||
"xna.cpp"
|
||||
"platform/window-dx.cpp"
|
||||
"platform/device-dx.cpp"
|
||||
"platform/adapter-dx.cpp"
|
||||
"platform/swapchain-dx.cpp"
|
||||
"platform/rendertarget-dx.cpp"
|
||||
"platform/texture-dx.cpp"
|
||||
"platform/blendstate-dx.cpp"
|
||||
"platform/game-dx.cpp"
|
||||
"platform/clock-dx.cpp"
|
||||
"csharp/stream.cpp"
|
||||
"platform/gdevicemanager-dx.cpp"
|
||||
"platform/vertexinput-dx.cpp"
|
||||
"platform/shader-dx.cpp"
|
||||
"platform/rasterizerstate-dx.cpp"
|
||||
"platform/vertexbuffer-dx.cpp"
|
||||
"platform/indexbuffer-dx.cpp"
|
||||
"common/matrix.cpp"
|
||||
"platform/constbuffer-dx.cpp"
|
||||
"platform/databuffer-dx.cpp"
|
||||
"platform/samplerstate-dx.cpp"
|
||||
"platform/spritebatch-dx.cpp"
|
||||
"platform/spritefont-dx.cpp"
|
||||
"platform/depthstencilstate-dx.cpp"
|
||||
"platform/keyboard-dx.cpp"
|
||||
"platform/mouse-dx.cpp"
|
||||
"platform/gamepad-dx.cpp"
|
||||
"common/vectors.cpp"
|
||||
"platform/soundeffect-dx.cpp"
|
||||
"platform/displaymode-dx.cpp"
|
||||
"platform/presentparameters-dx.cpp"
|
||||
"game/component.cpp"
|
||||
"content/manager.cpp"
|
||||
"content/reader.cpp"
|
||||
"csharp/binary.cpp"
|
||||
"content/lzx/decoder.cpp" "content/lzx/decoderstream.cpp" "content/typereadermanager.cpp" "csharp/object.cpp" "csharp/type.cpp" "platform/init-dx.cpp" "game/servicecontainer.cpp" "common/color.cpp")
|
||||
|
||||
if (CMAKE_VERSION VERSION_GREATER 3.12)
|
||||
set_property(TARGET xna PROPERTY CXX_STANDARD 20)
|
||||
@ -12,7 +48,6 @@ endif()
|
||||
# TODO: Add tests and install targets if needed.
|
||||
|
||||
|
||||
|
||||
# -- Biblioteca DirectxTK --
|
||||
# Url: https://github.com/microsoft/DirectXTK/wiki/DirectXTK
|
||||
#
|
||||
@ -30,5 +65,14 @@ endif()
|
||||
# "CMAKE_TOOLCHAIN_FILE": "{VCPKG_DIR}\\scripts\\buildsystems\\vcpkg.cmake"
|
||||
# }
|
||||
#
|
||||
# Instalaçao do libmspack
|
||||
# $- vcpkg install libmspack
|
||||
#
|
||||
find_package(directxtk CONFIG REQUIRED)
|
||||
target_link_libraries(${PROJECT_NAME} D3d11.lib dxgi.lib dxguid.lib d3dcompiler.lib Microsoft::DirectXTK)
|
||||
|
||||
include_directories($ENV{VCPKG_ROOT}\\packages\\libmspack_x64-windows\\include)
|
||||
|
||||
target_link_libraries(${PROJECT_NAME}
|
||||
D3d11.lib dxgi.lib dxguid.lib d3dcompiler.lib Microsoft::DirectXTK
|
||||
$ENV{VCPKG_ROOT}\\packages\\libmspack_x64-windows\\lib\\libmspack.lib
|
||||
)
|
||||
|
5
framework/common/color.cpp
Normal file
5
framework/common/color.cpp
Normal file
@ -0,0 +1,5 @@
|
||||
#include "color.hpp"
|
||||
|
||||
namespace xna {
|
||||
|
||||
}
|
@ -189,6 +189,10 @@ namespace xna {
|
||||
return Color::Multiply(value, scale);
|
||||
}
|
||||
|
||||
constexpr operator Uint() const {
|
||||
return _packedValue;
|
||||
}
|
||||
|
||||
private:
|
||||
Uint _packedValue{ 0 };
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
#define XNA_COMMON_MATH_HPP
|
||||
|
||||
#include <limits>
|
||||
#include <cmath>
|
||||
|
||||
namespace xna {
|
||||
struct MathHelper {
|
||||
@ -9,9 +10,49 @@ namespace xna {
|
||||
static constexpr double PI = 3.1415926535897931;
|
||||
static constexpr double TAU = 6.2831853071795862;
|
||||
static constexpr double EPSILON = std::numeric_limits<double>::epsilon();
|
||||
};
|
||||
|
||||
using Math = MathHelper;
|
||||
static constexpr float ToRadians(float degrees) { return degrees * (static_cast<float>(PI) / 180.0f); }
|
||||
static constexpr float ToDegrees(float radians) { return radians * 57.2957764F; }
|
||||
static float Distance(float value1, float value2) { return std::abs(value1 - value2); }
|
||||
static float Min(float value1, float value2) { return (std::min)(value1, value2); }
|
||||
static float Max(float value1, float value2) { return (std::max)(value1, value2); }
|
||||
|
||||
static constexpr float Clamp(float value, float min, float max) {
|
||||
value = value > max ? max : value;
|
||||
value = value < min ? min : value;
|
||||
return value;
|
||||
}
|
||||
|
||||
static constexpr float Lerp(float value1, float value2, float amount) {
|
||||
return value1 + (value2 - value1) * amount;
|
||||
}
|
||||
|
||||
static constexpr float Barycentric(float value1, float value2, float value3, float amount1, float amount2) {
|
||||
return value1 + amount1 * (value2 - value1) + amount2 * (value3 - value1);
|
||||
}
|
||||
|
||||
static constexpr float SmoothStep(float value1, float value2, float amount) {
|
||||
const auto num = Clamp(amount, 0.0f, 1.0f);
|
||||
return Lerp(value1, value2, (num * num * (3.0F - 2.0F * num)));
|
||||
}
|
||||
|
||||
static float CatmullRom(float value1, float value2, float value3, float value4, float amount) {
|
||||
const auto num1 = amount * amount;
|
||||
const auto num2 = amount * num1;
|
||||
return (0.5F * (2.0F * value2 + (-value1 + value3) * amount + (2.0F * value1 - 5.0F * value2 + 4.0F * value3 - value4) * num1 + (-value1 + 3.0F * value2 - 3.0F * value3 + value4) * num2));
|
||||
}
|
||||
|
||||
static float Hermite(float value1, float tangent1, float value2, float tangent2, float amount) {
|
||||
const auto num1 = amount;
|
||||
const auto num2 = num1 * num1;
|
||||
const auto num3 = num1 * num2;
|
||||
const auto num4 = (2.0F * num3 - 3.0F * num2 + 1.0F);
|
||||
const auto num5 = (-2.0F * num3 + 3.0F * num2);
|
||||
const auto num6 = num3 - 2.0f * num2 + num1;
|
||||
const auto num7 = num3 - num2;
|
||||
return value1 * num4 + value2 * num5 + tangent1 * num6 + tangent2 * num7;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
@ -212,7 +212,7 @@ namespace xna {
|
||||
}
|
||||
|
||||
Matrix Matrix::CreatePerspectiveFieldOfView(float fieldOfView, float aspectRatio, float nearPlaneDistance, float farPlaneDistance) {
|
||||
if (fieldOfView <= 0.0 || fieldOfView >= Math::PI || nearPlaneDistance <= 0.0 || farPlaneDistance <= 0.0 || nearPlaneDistance >= farPlaneDistance) {
|
||||
if (fieldOfView <= 0.0 || fieldOfView >= MathHelper::PI || nearPlaneDistance <= 0.0 || farPlaneDistance <= 0.0 || nearPlaneDistance >= farPlaneDistance) {
|
||||
return Matrix();
|
||||
}
|
||||
|
||||
|
@ -623,6 +623,47 @@ namespace xna {
|
||||
vector3.Z = num3;
|
||||
return vector3;
|
||||
}
|
||||
|
||||
constexpr Vector4 Vector4::Transform(Vector2 const& position, Matrix const& matrix)
|
||||
{
|
||||
const auto num1 = (position.X * matrix.M11 + position.Y * matrix.M21) + matrix.M41;
|
||||
const auto num2 = (position.X * matrix.M12 + position.Y * matrix.M22) + matrix.M42;
|
||||
const auto num3 = (position.X * matrix.M13 + position.Y * matrix.M23) + matrix.M43;
|
||||
const auto num4 = (position.X * matrix.M14 + position.Y * matrix.M24) + matrix.M44;
|
||||
Vector4 vector4;
|
||||
vector4.X = num1;
|
||||
vector4.Y = num2;
|
||||
vector4.Z = num3;
|
||||
vector4.W = num4;
|
||||
return vector4;
|
||||
}
|
||||
|
||||
constexpr Vector4 Vector4::Transform(Vector3 const& position, Matrix const& matrix)
|
||||
{
|
||||
const auto num1 = (position.X * matrix.M11 + position.Y * matrix.M21 + position.Z * matrix.M31) + matrix.M41;
|
||||
const auto num2 = (position.X * matrix.M12 + position.Y * matrix.M22 + position.Z * matrix.M32) + matrix.M42;
|
||||
const auto num3 = (position.X * matrix.M13 + position.Y * matrix.M23 + position.Z * matrix.M33) + matrix.M43;
|
||||
const auto num4 = (position.X * matrix.M14 + position.Y * matrix.M24 + position.Z * matrix.M34) + matrix.M44;
|
||||
Vector4 vector4;
|
||||
vector4.X = num1;
|
||||
vector4.Y = num2;
|
||||
vector4.Z = num3;
|
||||
vector4.W = num4;
|
||||
return vector4;
|
||||
}
|
||||
|
||||
constexpr Vector4 Vector4::Transform(Vector4 const& vector, Matrix const& matrix) {
|
||||
const auto num1 = (vector.X * matrix.M11 + vector.Y * matrix.M21 + vector.Z * matrix.M31 + vector.W * matrix.M41);
|
||||
const auto num2 = (vector.X * matrix.M12 + vector.Y * matrix.M22 + vector.Z * matrix.M32 + vector.W * matrix.M42);
|
||||
const auto num3 = (vector.X * matrix.M13 + vector.Y * matrix.M23 + vector.Z * matrix.M33 + vector.W * matrix.M43);
|
||||
const auto num4 = (vector.X * matrix.M14 + vector.Y * matrix.M24 + vector.Z * matrix.M34 + vector.W * matrix.M44);
|
||||
Vector4 vector4;
|
||||
vector4.X = num1;
|
||||
vector4.Y = num2;
|
||||
vector4.Z = num3;
|
||||
vector4.W = num4;
|
||||
return vector4;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@ -57,6 +57,55 @@ namespace xna {
|
||||
vector3.Z = num15;
|
||||
return vector3;
|
||||
}
|
||||
|
||||
constexpr Vector4 Vector4::Transform(Vector2 const& value, Quaternion const& rotation)
|
||||
{
|
||||
const auto num1 = rotation.X + rotation.X;
|
||||
const auto num2 = rotation.Y + rotation.Y;
|
||||
const auto num3 = rotation.Z + rotation.Z;
|
||||
const auto num4 = rotation.W * num1;
|
||||
const auto num5 = rotation.W * num2;
|
||||
const auto num6 = rotation.W * num3;
|
||||
const auto num7 = rotation.X * num1;
|
||||
const auto num8 = rotation.X * num2;
|
||||
const auto num9 = rotation.X * num3;
|
||||
const auto num10 = rotation.Y * num2;
|
||||
const auto num11 = rotation.Y * num3;
|
||||
const auto num12 = rotation.Z * num3;
|
||||
const auto num13 = (value.X * (1.0F - num10 - num12) + value.Y * (num8 - num6));
|
||||
const auto num14 = (value.X * (num8 + num6) + value.Y * (1.0F - num7 - num12));
|
||||
const auto num15 = (value.X * (num9 - num5) + value.Y * (num11 + num4));
|
||||
Vector4 vector4;
|
||||
vector4.X = num13;
|
||||
vector4.Y = num14;
|
||||
vector4.Z = num15;
|
||||
vector4.W = 1.0f;
|
||||
return vector4;
|
||||
}
|
||||
|
||||
constexpr Vector4 Vector4::Transform(Vector3 const& value, Quaternion const& rotation) {
|
||||
const auto num1 = rotation.X + rotation.X;
|
||||
const auto num2 = rotation.Y + rotation.Y;
|
||||
const auto num3 = rotation.Z + rotation.Z;
|
||||
const auto num4 = rotation.W * num1;
|
||||
const auto num5 = rotation.W * num2;
|
||||
const auto num6 = rotation.W * num3;
|
||||
const auto num7 = rotation.X * num1;
|
||||
const auto num8 = rotation.X * num2;
|
||||
const auto num9 = rotation.X * num3;
|
||||
const auto num10 = rotation.Y * num2;
|
||||
const auto num11 = rotation.Y * num3;
|
||||
const auto num12 = rotation.Z * num3;
|
||||
const auto num13 = (value.X * (1.0F - num10 - num12) + value.Y * (num8 - num6) + value.Z * (num9 + num5));
|
||||
const auto num14 = (value.X * (num8 + num6) + value.Y * (1.0F - num7 - num12) + value.Z * (num11 - num4));
|
||||
const auto num15 = (value.X * (num9 - num5) + value.Y * (num11 + num4) + value.Z * (1.0F - num7 - num10));
|
||||
Vector4 vector4;
|
||||
vector4.X = num13;
|
||||
vector4.Y = num14;
|
||||
vector4.Z = num15;
|
||||
vector4.W = 1.0f;
|
||||
return vector4;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@ -2,18 +2,113 @@
|
||||
#define XNA_COMMON_RECTANGLE_HPP
|
||||
|
||||
#include "../types.hpp"
|
||||
#include "point.hpp"
|
||||
|
||||
namespace xna {
|
||||
struct Rectangle {
|
||||
Int Height{ 0 };
|
||||
Int Width{ 0 };
|
||||
Int X{ 0 };
|
||||
Int Y{ 0 };
|
||||
Int Width{ 0 };
|
||||
Int Height{ 0 };
|
||||
|
||||
constexpr Rectangle() = default;
|
||||
|
||||
constexpr Rectangle(const Int& X, const Int& Y, const Int& Width, const Int& Height):
|
||||
X(X), Y(Y), Width(Width), Height(Height) {}
|
||||
|
||||
constexpr bool operator==(const Rectangle& other) const {
|
||||
return Height == other.Height && Width == other.Width && X == other.X && Y == other.Y;
|
||||
}
|
||||
|
||||
constexpr Int Left() const { return X; }
|
||||
constexpr Int Right() const { return X + Width; }
|
||||
constexpr Int Top() const { return Y; }
|
||||
constexpr Int Bottom() const { return Y + Height; }
|
||||
|
||||
constexpr Point Location() const { return { X, Y }; }
|
||||
constexpr void Location(Point const& p) {
|
||||
X = p.X;
|
||||
Y = p.Y;
|
||||
}
|
||||
|
||||
constexpr Point Center() const { return { X + Width / 2, Y + Height / 2 }; }
|
||||
|
||||
constexpr static Rectangle Empty() { return {}; }
|
||||
|
||||
constexpr bool IsEmpty() const { return Width == 0 && Height == 0 && X == 0 && Y == 0; }
|
||||
|
||||
constexpr void Offset(Point const& amount) {
|
||||
X += amount.X;
|
||||
Y += amount.Y;
|
||||
}
|
||||
|
||||
constexpr void Offset(Int x, Int y) {
|
||||
X += x;
|
||||
Y += y;
|
||||
}
|
||||
|
||||
constexpr void Inflate(Int horizontalAmount, Int verticalAmount) {
|
||||
X -= horizontalAmount;
|
||||
Y -= verticalAmount;
|
||||
Width += horizontalAmount * 2;
|
||||
Height += verticalAmount * 2;
|
||||
}
|
||||
|
||||
constexpr bool Contains(Int x, Int y) const {
|
||||
return X <= x && x < X + Width && Y <= y && y < Y + Height;
|
||||
}
|
||||
|
||||
constexpr bool Contains(Point const& value) const {
|
||||
return X <= value.X && value.X < X + Width && Y <= value.Y && value.Y < Y + Height;
|
||||
}
|
||||
|
||||
constexpr bool Contains(Rectangle const& value) const {
|
||||
return X <= value.X && value.X + value.Width <= X + Width && Y <= value.Y && value.Y + value.Height <= Y + Height;
|
||||
}
|
||||
|
||||
constexpr bool Intersects(Rectangle const& value) const {
|
||||
return value.X < X + Width && X < value.X + value.Width && value.Y < Y + Height && Y < value.Y + value.Height;
|
||||
}
|
||||
|
||||
constexpr static Rectangle Intersect(Rectangle const& value1, Rectangle const& value2) {
|
||||
const auto left1 = value1.Left();
|
||||
const auto left2 = value2.Left();
|
||||
const auto bottom1 = value1.Bottom();
|
||||
const auto bottom2 = value2.Bottom();
|
||||
const auto maxX = value1.X > value2.X ? value1.X : value2.X;
|
||||
const auto maxY = value1.Y > value2.Y ? value1.Y : value2.Y;
|
||||
const auto maxl = left1 < left2 ? left1 : left2;
|
||||
const auto maxb = bottom1 < bottom2 ? bottom1 : bottom2;
|
||||
|
||||
Rectangle rectangle{};
|
||||
|
||||
if (maxl > maxX && maxb > maxY) {
|
||||
rectangle.X = maxX;
|
||||
rectangle.Y = maxY;
|
||||
rectangle.Width = maxl - maxX;
|
||||
rectangle.Height = maxb - maxY;
|
||||
}
|
||||
|
||||
return rectangle;
|
||||
}
|
||||
|
||||
constexpr static Rectangle Union(Rectangle const& value1, Rectangle const& value2) {
|
||||
const auto left1 = value1.Left();
|
||||
const auto left2 = value2.Left();
|
||||
const auto bottom1 = value1.Bottom();
|
||||
const auto bottom2 = value2.Bottom();
|
||||
const auto minX = value1.X < value2.X ? value1.X : value2.X;
|
||||
const auto miny = value1.Y < value2.Y ? value1.Y : value2.Y;
|
||||
const auto maxl = left1 > left2 ? left1 : left2;
|
||||
const auto maxb = bottom1 > bottom2 ? bottom1 : bottom2;
|
||||
|
||||
Rectangle rectangle;
|
||||
rectangle.X = minX;
|
||||
rectangle.Y = miny;
|
||||
rectangle.Width = maxl - minX;
|
||||
rectangle.Height = maxb - miny;
|
||||
return rectangle;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -17,6 +17,14 @@ namespace xna {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Vector2::Transform(std::vector<Vector2> sourceArray, Matrix const& matrix, std::vector<Vector2>& destinationArray)
|
||||
{
|
||||
if (destinationArray.empty())
|
||||
destinationArray.resize(sourceArray.size());
|
||||
|
||||
return Transform(sourceArray.data(), sourceArray.size(), matrix, destinationArray.data(), destinationArray.size());
|
||||
}
|
||||
|
||||
bool Vector2::Transform(Vector2 const* sourceArray, size_t sourceArrayLength, size_t sourceIndex, Matrix const& matrix,
|
||||
Vector2* destinationArray, size_t destinationArrayLength, size_t destinationIndex, size_t length) {
|
||||
if (!sourceArray || !destinationArray || destinationArrayLength < sourceArrayLength
|
||||
@ -32,6 +40,14 @@ namespace xna {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Vector2::Transform(std::vector<Vector2> const& sourceArray, size_t sourceIndex, Matrix const& matrix, std::vector<Vector2>& destinationArray, size_t destinationIndex, size_t length)
|
||||
{
|
||||
if (destinationArray.empty())
|
||||
destinationArray.resize(sourceArray.size());
|
||||
|
||||
return Transform(sourceArray.data(), sourceArray.size(), sourceIndex, matrix, destinationArray.data(), destinationArray.size(), destinationIndex, length);
|
||||
}
|
||||
|
||||
bool Vector2::TransformNormal(Vector2 const* sourceArray, size_t sourceArrayLength, Matrix const& matrix, Vector2* destinationArray, size_t destinationArrayLength) {
|
||||
if (!sourceArray || !destinationArray || destinationArrayLength < sourceArrayLength)
|
||||
return false;
|
||||
@ -44,6 +60,14 @@ namespace xna {
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Vector2::TransformNormal(std::vector<Vector2> const& sourceArray, Matrix const& matrix, std::vector<Vector2>& destinationArray)
|
||||
{
|
||||
if (destinationArray.empty())
|
||||
destinationArray.resize(sourceArray.size());
|
||||
|
||||
return TransformNormal(sourceArray.data(), sourceArray.size(), matrix, destinationArray.data(), destinationArray.size());
|
||||
}
|
||||
|
||||
bool Vector2::TransformNormal(Vector2 const* sourceArray, size_t sourceArrayLength, size_t sourceIndex, Matrix const& matrix, Vector2* destinationArray, size_t destinationArrayLength, size_t destinationIndex, size_t length) {
|
||||
if (!sourceArray || !destinationArray || destinationArrayLength < sourceArrayLength
|
||||
@ -60,6 +84,14 @@ namespace xna {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Vector2::TransformNormal(std::vector<Vector2> const& sourceArray, size_t sourceIndex, Matrix const& matrix, std::vector<Vector2>& destinationArray, size_t destinationIndex, size_t length)
|
||||
{
|
||||
if (destinationArray.empty())
|
||||
destinationArray.resize(sourceArray.size());
|
||||
|
||||
return TransformNormal(sourceArray.data(), sourceArray.size(), sourceIndex, matrix, destinationArray.data(), destinationArray.size(), destinationIndex, length);
|
||||
}
|
||||
|
||||
bool Vector2::Transform(Vector2 const* sourceArray, size_t sourceArrayLength, Quaternion const& rotation, Vector2* destinationArray, size_t destinationArrayLength) {
|
||||
if (!sourceArray || !destinationArray || destinationArrayLength < sourceArrayLength)
|
||||
return false;
|
||||
@ -86,6 +118,14 @@ namespace xna {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Vector2::Transform(std::vector<Vector2> const& sourceArray, Quaternion const& rotation, std::vector<Vector2>& destinationArray)
|
||||
{
|
||||
if (destinationArray.empty())
|
||||
destinationArray.resize(sourceArray.size());
|
||||
|
||||
return Transform(sourceArray.data(), sourceArray.size(), rotation, destinationArray.data(), destinationArray.size());
|
||||
}
|
||||
|
||||
bool Vector2::Transform(Vector2 const* sourceArray, size_t sourceArrayLength, size_t sourceIndex, Quaternion const& rotation,
|
||||
Vector2* destinationArray, size_t destinationArrayLength, size_t destinationIndex, size_t length) {
|
||||
if (!sourceArray || !destinationArray || destinationArrayLength < sourceArrayLength
|
||||
@ -117,30 +157,20 @@ namespace xna {
|
||||
return true;
|
||||
}
|
||||
|
||||
void Vector3::Normalize() {
|
||||
const auto num = 1.0f / std::sqrt(X * X + Y * Y + Z * Z);
|
||||
X *= num;
|
||||
Y *= num;
|
||||
Z *= num;
|
||||
}
|
||||
|
||||
Vector3 Vector3::Normalize(Vector3 const& value) {
|
||||
const auto num = 1.0f / std::sqrt(value.X * value.X + value.Y * value.Y + value.Z * value.Z);
|
||||
|
||||
Vector3 vector3;
|
||||
vector3.X = value.X * num;
|
||||
vector3.Y = value.Y * num;
|
||||
vector3.Z = value.Z * num;
|
||||
|
||||
return vector3;
|
||||
}
|
||||
|
||||
bool xna::Vector3::Transform(std::vector<Vector3> const& sourceArray, Matrix const& matrix, std::vector<Vector3>& destinationArray)
|
||||
bool Vector2::Transform(std::vector<Vector2> const& sourceArray, size_t sourceIndex, Quaternion const& rotation, std::vector<Vector2>& destinationArray, size_t destinationIndex, size_t length)
|
||||
{
|
||||
if (destinationArray.size() < sourceArray.size())
|
||||
if (destinationArray.empty())
|
||||
destinationArray.resize(sourceArray.size());
|
||||
|
||||
return Transform(sourceArray.data(), sourceArray.size(), sourceIndex, rotation, destinationArray.data(), destinationArray.size(), destinationIndex, length);
|
||||
}
|
||||
|
||||
bool Vector3::Transform(Vector3 const* sourceArray, size_t sourceArrayLength, Matrix const& matrix, Vector3* destinationArray, size_t destinationLength)
|
||||
{
|
||||
if (!sourceArray || !destinationArray || destinationLength < sourceArrayLength)
|
||||
return false;
|
||||
|
||||
for (size_t index = 0; index < sourceArray.size(); ++index)
|
||||
for (size_t index = 0; index < sourceArrayLength; ++index)
|
||||
{
|
||||
const auto& source = sourceArray[index];
|
||||
destinationArray[index].X = (source.X * matrix.M11 + source.Y * matrix.M21 + source.Z * matrix.M31) + matrix.M41;
|
||||
@ -151,9 +181,17 @@ namespace xna {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Vector3::Transform(std::vector<Vector3> const& sourceArray, size_t sourceIndex, Matrix const& matrix, std::vector<Vector3>& destinationArray, size_t destinationIndex, size_t length)
|
||||
bool Vector3::Transform(std::vector<Vector3> const& sourceArray, Matrix const& matrix, std::vector<Vector3>& destinationArray)
|
||||
{
|
||||
if (sourceArray.size() < sourceIndex + length || destinationArray.size() < destinationIndex + length)
|
||||
if (destinationArray.empty())
|
||||
destinationArray.resize(sourceArray.size());
|
||||
|
||||
return Transform(sourceArray.data(), sourceArray.size(), matrix, destinationArray.data(), destinationArray.size());
|
||||
}
|
||||
|
||||
bool Vector3::Transform(Vector3 const* sourceArray, size_t sourceArrayLength, size_t sourceIndex, Matrix const& matrix, Vector3* destinationArray, size_t destinationLength, size_t destinationIndex, size_t length)
|
||||
{
|
||||
if (!sourceArray || !destinationArray || sourceArrayLength < sourceIndex + length || destinationLength < destinationIndex + length)
|
||||
return false;
|
||||
|
||||
for (size_t index = 0; index < length; ++index)
|
||||
@ -161,18 +199,26 @@ namespace xna {
|
||||
const auto& source = sourceArray[sourceIndex + index];
|
||||
destinationArray[destinationIndex + index].X = (source.X * matrix.M11 + source.Y * matrix.M21 + source.Z * matrix.M31) + matrix.M41;
|
||||
destinationArray[destinationIndex + index].Y = (source.X * matrix.M12 + source.Y * matrix.M22 + source.Z * matrix.M32) + matrix.M42;
|
||||
destinationArray[destinationIndex + index].Z = (source.X * matrix.M13 + source.Y * matrix.M23 + source.Z * matrix.M33) + matrix.M43;
|
||||
destinationArray[destinationIndex + index].Z = (source.X * matrix.M13 + source.Y * matrix.M23 + source.Z * matrix.M33) + matrix.M43;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Vector3::TransformNormal(std::vector<Vector3> const& sourceArray, Matrix const& matrix, std::vector<Vector3>& destinationArray)
|
||||
bool Vector3::Transform(std::vector<Vector3> const& sourceArray, size_t sourceIndex, Matrix const& matrix, std::vector<Vector3>& destinationArray, size_t destinationIndex, size_t length)
|
||||
{
|
||||
if (destinationArray.size() < sourceArray.size())
|
||||
if (destinationArray.empty())
|
||||
destinationArray.resize(sourceArray.size());
|
||||
|
||||
return Transform(sourceArray.data(), sourceArray.size(), sourceIndex, matrix, destinationArray.data(), destinationArray.size(), destinationIndex, length);
|
||||
}
|
||||
|
||||
bool Vector3::TransformNormal(Vector3 const* sourceArray, size_t sourceArrayLength, Matrix const& matrix, Vector3* destinationArray, size_t destionationArrayLength)
|
||||
{
|
||||
if (!sourceArray || !destinationArray || sourceArrayLength < destionationArrayLength)
|
||||
return false;
|
||||
|
||||
for (size_t index = 0; index < sourceArray.size(); ++index)
|
||||
for (size_t index = 0; index < sourceArrayLength; ++index)
|
||||
{
|
||||
const auto& source = sourceArray[index];
|
||||
destinationArray[index].X = source.X * matrix.M11 + source.Y * matrix.M21 + source.Z * matrix.M31;
|
||||
@ -183,9 +229,17 @@ namespace xna {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Vector3::TransformNormal(std::vector<Vector3> const& sourceArray, size_t sourceIndex, Matrix const& matrix, std::vector<Vector3>& destinationArray, size_t destinationIndex, size_t length)
|
||||
bool Vector3::TransformNormal(std::vector<Vector3> const& sourceArray, Matrix const& matrix, std::vector<Vector3>& destinationArray)
|
||||
{
|
||||
if (sourceArray.size() < sourceIndex + length || destinationArray.size() < destinationIndex + length)
|
||||
if (destinationArray.empty())
|
||||
destinationArray.resize(sourceArray.size());
|
||||
|
||||
return TransformNormal(sourceArray.data(), sourceArray.size(), matrix, destinationArray.data(), destinationArray.size());
|
||||
}
|
||||
|
||||
bool Vector3::TransformNormal(Vector3 const* sourceArray, size_t sourceArrayLength, size_t sourceIndex, Matrix const& matrix, Vector3* destinationArray, size_t destinationLength, size_t destinationIndex, size_t length)
|
||||
{
|
||||
if (!sourceArray || !destinationArray || sourceArrayLength < sourceIndex + length || destinationLength < destinationIndex + length)
|
||||
return false;
|
||||
|
||||
for (size_t index = 0; index < length; ++index) {
|
||||
@ -198,9 +252,17 @@ namespace xna {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Vector3::TransformNormal(std::vector<Vector3> const& sourceArray, Quaternion const& rotation, std::vector<Vector3>& destinationArray)
|
||||
bool Vector3::TransformNormal(std::vector<Vector3> const& sourceArray, size_t sourceIndex, Matrix const& matrix, std::vector<Vector3>& destinationArray, size_t destinationIndex, size_t length)
|
||||
{
|
||||
if (destinationArray.size() < sourceArray.size())
|
||||
if (destinationArray.empty())
|
||||
destinationArray.resize(sourceArray.size());
|
||||
|
||||
return TransformNormal(sourceArray.data(), sourceArray.size(), sourceIndex, matrix, destinationArray.data(), destinationArray.size(), destinationIndex, length);
|
||||
}
|
||||
|
||||
bool Vector3::TransformNormal(Vector3 const* sourceArray, size_t sourceArrayLength, Quaternion const& rotation, Vector3* destinationArray, size_t destinationLength)
|
||||
{
|
||||
if (!sourceArray || !destinationArray || destinationLength < sourceArrayLength)
|
||||
return false;
|
||||
|
||||
const auto num1 = rotation.X + rotation.X;
|
||||
@ -225,7 +287,7 @@ namespace xna {
|
||||
const auto num20 = num11 + num4;
|
||||
const auto num21 = 1.0f - num7 - num10;
|
||||
|
||||
for (size_t index = 0; index < sourceArray.size(); ++index)
|
||||
for (size_t index = 0; index < sourceArrayLength; ++index)
|
||||
{
|
||||
const auto& source = sourceArray[index];
|
||||
destinationArray[index].X = source.X * num13 + source.Y * num14 + source.Z * num15;
|
||||
@ -236,11 +298,19 @@ namespace xna {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Vector3::TransformNormal(std::vector<Vector3> const& sourceArray, size_t sourceIndex, Quaternion const& rotation, std::vector<Vector3>& destinationArray, size_t destinationIndex, size_t length)
|
||||
bool Vector3::TransformNormal(std::vector<Vector3> const& sourceArray, Quaternion const& rotation, std::vector<Vector3>& destinationArray)
|
||||
{
|
||||
if (sourceArray.size() < sourceIndex + length || destinationArray.size() < destinationIndex + length)
|
||||
if (destinationArray.empty())
|
||||
destinationArray.resize(sourceArray.size());
|
||||
|
||||
return TransformNormal(sourceArray.data(), sourceArray.size(), rotation, destinationArray.data(), destinationArray.size());
|
||||
}
|
||||
|
||||
bool Vector3::TransformNormal(Vector3 const* sourceArray, size_t sourceArrayLength, size_t sourceIndex, Quaternion const& rotation, Vector3* destinationArray, size_t destinationLength, size_t destinationIndex, size_t length)
|
||||
{
|
||||
if (!sourceArray || !destinationArray || sourceArrayLength < sourceIndex + length || destinationLength < destinationIndex + length)
|
||||
return false;
|
||||
|
||||
|
||||
const auto num1 = rotation.X + rotation.X;
|
||||
const auto num2 = rotation.Y + rotation.Y;
|
||||
const auto num3 = rotation.Z + rotation.Z;
|
||||
@ -273,4 +343,155 @@ namespace xna {
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Vector3::TransformNormal(std::vector<Vector3> const& sourceArray, size_t sourceIndex, Quaternion const& rotation, std::vector<Vector3>& destinationArray, size_t destinationIndex, size_t length)
|
||||
{
|
||||
if (destinationArray.empty())
|
||||
destinationArray.resize(sourceArray.size());
|
||||
|
||||
return TransformNormal(sourceArray.data(), sourceArray.size(), sourceIndex, rotation, destinationArray.data(), destinationArray.size(), destinationIndex, length);
|
||||
}
|
||||
|
||||
bool Vector4::Transform(Vector4 const* sourceArray, size_t sourceLength, Matrix const& matrix, Vector4* destinationArray, size_t destinationLength)
|
||||
{
|
||||
if (!sourceArray || !destinationArray || destinationLength < sourceLength)
|
||||
return false;
|
||||
|
||||
for (size_t index = 0; index < sourceLength; ++index)
|
||||
{
|
||||
const auto& source = sourceArray[index];
|
||||
destinationArray[index].X = source.X * matrix.M11 + source.Y * matrix.M21 + source.Z * matrix.M31 + source.W * matrix.M41;
|
||||
destinationArray[index].Y = source.X * matrix.M12 + source.Y * matrix.M22 + source.Z * matrix.M32 + source.W * matrix.M42;
|
||||
destinationArray[index].Z = source.X * matrix.M13 + source.Y * matrix.M23 + source.Z * matrix.M33 + source.W * matrix.M43;
|
||||
destinationArray[index].W = source.X * matrix.M14 + source.Y * matrix.M24 + source.Z * matrix.M34 + source.W * matrix.M44;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Vector4::Transform(std::vector<Vector4> const& sourceArray, size_t sourceLength, Matrix const& matrix, std::vector<Vector4>& destinationArray)
|
||||
{
|
||||
if (destinationArray.empty())
|
||||
destinationArray.resize(sourceArray.size());
|
||||
|
||||
return Transform(sourceArray.data(), sourceArray.size(), matrix, destinationArray.data(), destinationArray.size());
|
||||
}
|
||||
|
||||
bool Vector4::Transform(Vector4 const* sourceArray, size_t sourceLength, size_t sourceIndex, Matrix const& matrix, Vector4* destinationArray, size_t destinationLength, size_t destinationIndex, size_t length)
|
||||
{
|
||||
if (!sourceArray || !destinationArray || sourceLength < sourceIndex + length || destinationLength < destinationIndex + length)
|
||||
return false;
|
||||
|
||||
for (size_t i = 0; i < length; ++i)
|
||||
{
|
||||
const auto& source = sourceArray[sourceIndex + i];
|
||||
destinationArray[destinationIndex].X = source.X * matrix.M11 + source.Y * matrix.M21 + source.Z * matrix.M31 + source.W * matrix.M41;
|
||||
destinationArray[destinationIndex].Y = source.X * matrix.M12 + source.Y * matrix.M22 + source.Z * matrix.M32 + source.W * matrix.M42;
|
||||
destinationArray[destinationIndex].Z = source.X * matrix.M13 + source.Y * matrix.M23 + source.Z * matrix.M33 + source.W * matrix.M43;
|
||||
destinationArray[destinationIndex].W = source.X * matrix.M14 + source.Y * matrix.M24 + source.Z * matrix.M34 + source.W * matrix.M44;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Vector4::Transform(std::vector<Vector4> const& sourceArray, size_t sourceIndex, Matrix const& matrix, std::vector<Vector4>& destinationArray, size_t destinationIndex, size_t length)
|
||||
{
|
||||
if (destinationArray.empty())
|
||||
destinationArray.resize(sourceArray.size());
|
||||
|
||||
return Transform(sourceArray.data(), sourceArray.size(), sourceIndex, matrix, destinationArray.data(), destinationArray.size(), destinationIndex, length);
|
||||
}
|
||||
|
||||
bool Vector4::Transform(Vector4 const* sourceArray, size_t sourceLength, Quaternion const& rotation, Vector4* destinationArray, size_t destinationLength)
|
||||
{
|
||||
if (!sourceArray || !destinationArray || destinationLength < sourceLength)
|
||||
return false;
|
||||
|
||||
const auto num1 = rotation.X + rotation.X;
|
||||
const auto num2 = rotation.Y + rotation.Y;
|
||||
const auto num3 = rotation.Z + rotation.Z;
|
||||
const auto num4 = rotation.W * num1;
|
||||
const auto num5 = rotation.W * num2;
|
||||
const auto num6 = rotation.W * num3;
|
||||
const auto num7 = rotation.X * num1;
|
||||
const auto num8 = rotation.X * num2;
|
||||
const auto num9 = rotation.X * num3;
|
||||
const auto num10 = rotation.Y * num2;
|
||||
const auto num11 = rotation.Y * num3;
|
||||
const auto num12 = rotation.Z * num3;
|
||||
const auto num13 = 1.0f - num10 - num12;
|
||||
const auto num14 = num8 - num6;
|
||||
const auto num15 = num9 + num5;
|
||||
const auto num16 = num8 + num6;
|
||||
const auto num17 = 1.0f - num7 - num12;
|
||||
const auto num18 = num11 - num4;
|
||||
const auto num19 = num9 - num5;
|
||||
const auto num20 = num11 + num4;
|
||||
const auto num21 = 1.0f - num7 - num10;
|
||||
|
||||
for (size_t index = 0; index < sourceLength; ++index)
|
||||
{
|
||||
const auto& source = sourceArray[index];
|
||||
destinationArray[index].X = source.Z * num13 + source.Y * num14 + source.Z * num15;
|
||||
destinationArray[index].Y = source.Z * num16 + source.Y * num17 + source.Z * num18;
|
||||
destinationArray[index].Z = source.Z * num19 + source.Y * num20 + source.Z * num21;
|
||||
destinationArray[index].W = sourceArray[index].W;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Vector4::Transform(std::vector<Vector4> const& sourceArray, Quaternion const& rotation, std::vector<Vector4>& destinationArray)
|
||||
{
|
||||
if (destinationArray.empty())
|
||||
destinationArray.resize(sourceArray.size());
|
||||
|
||||
return Transform(sourceArray.data(), sourceArray.size(), rotation, destinationArray.data(), destinationArray.size());
|
||||
}
|
||||
|
||||
bool Vector4::Transform(Vector4 const* sourceArray, size_t sourceLength, size_t sourceIndex, Quaternion const& rotation, Vector4* destinationArray, size_t destinationLength, size_t destinationIndex, size_t length)
|
||||
{
|
||||
if (!sourceArray || !destinationArray || sourceLength < sourceIndex + length || destinationLength < destinationIndex + length)
|
||||
return false;
|
||||
|
||||
const auto num1 = rotation.X + rotation.X;
|
||||
const auto num2 = rotation.Y + rotation.Y;
|
||||
const auto num3 = rotation.Z + rotation.Z;
|
||||
const auto num4 = rotation.W * num1;
|
||||
const auto num5 = rotation.W * num2;
|
||||
const auto num6 = rotation.W * num3;
|
||||
const auto num7 = rotation.X * num1;
|
||||
const auto num8 = rotation.X * num2;
|
||||
const auto num9 = rotation.X * num3;
|
||||
const auto num10 = rotation.Y * num2;
|
||||
const auto num11 = rotation.Y * num3;
|
||||
const auto num12 = rotation.Z * num3;
|
||||
const auto num13 = 1.0f - num10 - num12;
|
||||
const auto num14 = num8 - num6;
|
||||
const auto num15 = num9 + num5;
|
||||
const auto num16 = num8 + num6;
|
||||
const auto num17 = 1.0f - num7 - num12;
|
||||
const auto num18 = num11 - num4;
|
||||
const auto num19 = num9 - num5;
|
||||
const auto num20 = num11 + num4;
|
||||
const auto num21 = 1.0f - num7 - num10;
|
||||
|
||||
for (size_t i = 0; i < length; ++i)
|
||||
{
|
||||
const auto& source = sourceArray[sourceIndex + i];
|
||||
destinationArray[destinationIndex].X = source.X * num13 + source.Y * num14 + source.Z * num15;
|
||||
destinationArray[destinationIndex].Y = source.X * num16 + source.Y * num17 + source.Z * num18;
|
||||
destinationArray[destinationIndex].Z = source.X * num19 + source.Y * num20 + source.Z * num21;
|
||||
destinationArray[destinationIndex].W = source.W;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
bool Vector4::Transform(std::vector<Vector4> const& sourceArray, size_t sourceIndex, Quaternion const& rotation, std::vector<Vector4>& destinationArray, size_t destinationIndex, size_t length)
|
||||
{
|
||||
if (destinationArray.empty())
|
||||
destinationArray.resize(sourceArray.size());
|
||||
|
||||
return Transform(sourceArray.data(), sourceArray.size(), sourceIndex, rotation, destinationArray.data(), destinationArray.size(), destinationIndex, length);
|
||||
}
|
||||
}
|
@ -53,8 +53,9 @@ namespace xna {
|
||||
}
|
||||
|
||||
static inline Vector2 Normalize(Vector2 const& value) {
|
||||
const auto normal = 1.0F / value.Length();
|
||||
return { value.X * normal, value.Y * normal };
|
||||
auto v = value;
|
||||
v.Normalize();
|
||||
return v;
|
||||
}
|
||||
|
||||
static constexpr Vector2 Reflect(Vector2 const& vector, Vector2 const& normal) {
|
||||
@ -136,14 +137,20 @@ namespace xna {
|
||||
static constexpr Vector2 TransformNormal(Vector2 const& normal, Matrix const& matrix);
|
||||
static constexpr Vector2 Transform(Vector2 const& value, Quaternion const& rotation);
|
||||
static bool Transform(Vector2 const* sourceArray, size_t sourceArrayLength, Matrix const& matrix, Vector2* destinationArray, size_t destinationArrayLength);
|
||||
static bool Transform(std::vector<Vector2> sourceArray, Matrix const& matrix, std::vector<Vector2>& destinationArray);
|
||||
static bool Transform(Vector2 const* sourceArray, size_t sourceArrayLength, size_t sourceIndex, Matrix const& matrix,
|
||||
Vector2* destinationArray, size_t destinationArrayLength, size_t destinationIndex, size_t length);
|
||||
static bool Transform(std::vector<Vector2> const& sourceArray, size_t sourceIndex, Matrix const& matrix, std::vector<Vector2>& destinationArray, size_t destinationIndex, size_t length);
|
||||
static bool TransformNormal(Vector2 const* sourceArray, size_t sourceArrayLength, Matrix const& matrix, Vector2* destinationArray, size_t destinationArrayLength);
|
||||
static bool TransformNormal(std::vector<Vector2> const& sourceArray, Matrix const& matrix, std::vector<Vector2>& destinationArray);
|
||||
static bool TransformNormal(Vector2 const* sourceArray, size_t sourceArrayLength, size_t sourceIndex, Matrix const& matrix,
|
||||
Vector2* destinationArray, size_t destinationArrayLength, size_t destinationIndex, size_t length);
|
||||
static bool TransformNormal(std::vector<Vector2> const& sourceArray, size_t sourceIndex, Matrix const& matrix, std::vector<Vector2>& destinationArray, size_t destinationIndex, size_t length);
|
||||
static bool Transform(Vector2 const* sourceArray, size_t sourceArrayLength, Quaternion const& rotation, Vector2* destinationArray, size_t destinationArrayLength);
|
||||
static bool Transform(std::vector<Vector2> const& sourceArray, Quaternion const& rotation, std::vector<Vector2>& destinationArray);
|
||||
static bool Transform(Vector2 const* sourceArray, size_t sourceArrayLength, size_t sourceIndex, Quaternion const& rotation,
|
||||
Vector2* destinationArray, size_t destinationArrayLength, size_t destinationIndex, size_t length);
|
||||
static bool Transform(std::vector<Vector2> const& sourceArray, size_t sourceIndex, Quaternion const& rotation, std::vector<Vector2>& destinationArray, size_t destinationIndex, size_t length);
|
||||
|
||||
static constexpr Vector2 Negate(Vector2 const& value) {
|
||||
return { -value.X, -value.Y };
|
||||
@ -260,8 +267,18 @@ namespace xna {
|
||||
return vector1.X * vector2.X + vector1.Y * vector2.Y + vector1.Z * vector2.Z;
|
||||
}
|
||||
|
||||
void Normalize();
|
||||
static Vector3 Normalize(Vector3 const& value);
|
||||
inline void Normalize() {
|
||||
const auto num = 1.0f / Length();
|
||||
X *= num;
|
||||
Y *= num;
|
||||
Z *= num;
|
||||
}
|
||||
|
||||
static Vector3 Normalize(Vector3 const& value) {
|
||||
auto v = value;
|
||||
v.Normalize();
|
||||
return v;
|
||||
}
|
||||
|
||||
static constexpr Vector3 Cross(Vector3 const& vector1, Vector3 const& vector2) {
|
||||
Vector3 vector3;
|
||||
@ -364,11 +381,17 @@ namespace xna {
|
||||
static constexpr Vector3 Transform(Vector3 const& position, Matrix const& matrix);
|
||||
static constexpr Vector3 TransformNormal(Vector3 const& normal, Matrix const& matrix);
|
||||
static constexpr Vector3 Transform(Vector3 const& value, Quaternion const& rotation);
|
||||
static bool Transform(Vector3 const* sourceArray, size_t sourceArrayLength, Matrix const& matrix, Vector3* destinationArray, size_t destinationLength);
|
||||
static bool Transform(std::vector<Vector3> const& sourceArray, Matrix const& matrix, std::vector<Vector3>& destinationArray);
|
||||
static bool Transform(Vector3 const* sourceArray, size_t sourceArrayLength, size_t sourceIndex, Matrix const& matrix, Vector3* destinationArray, size_t destinationLength, size_t destinationIndex, size_t length);
|
||||
static bool Transform(std::vector<Vector3> const& sourceArray, size_t sourceIndex, Matrix const& matrix, std::vector<Vector3>& destinationArray, size_t destinationIndex, size_t length);
|
||||
static bool TransformNormal(Vector3 const* sourceArray, size_t sourceArrayLength, Matrix const& matrix, Vector3* destinationArray, size_t destionationArrayLength);
|
||||
static bool TransformNormal(std::vector<Vector3> const& sourceArray, Matrix const& matrix, std::vector<Vector3>& destinationArray);
|
||||
static bool TransformNormal(Vector3 const* sourceArray, size_t sourceArrayLength, size_t sourceIndex, Matrix const& matrix, Vector3* destinationArray, size_t destinationLength, size_t destinationIndex, size_t length);
|
||||
static bool TransformNormal(std::vector<Vector3> const& sourceArray, size_t sourceIndex, Matrix const& matrix, std::vector<Vector3>& destinationArray, size_t destinationIndex, size_t length);
|
||||
static bool TransformNormal(Vector3 const* sourceArray, size_t sourceArrayLength, Quaternion const& rotation,Vector3* destinationArray, size_t destinationLength);
|
||||
static bool TransformNormal(std::vector<Vector3> const& sourceArray, Quaternion const& rotation, std::vector<Vector3>& destinationArray);
|
||||
static bool TransformNormal(Vector3 const* sourceArray, size_t sourceArrayLength, size_t sourceIndex, Quaternion const& rotation, Vector3* destinationArray, size_t destinationLength, size_t destinationIndex, size_t length);
|
||||
static bool TransformNormal(std::vector<Vector3> const& sourceArray, size_t sourceIndex, Quaternion const& rotation, std::vector<Vector3>& destinationArray, size_t destinationIndex, size_t length);
|
||||
|
||||
static constexpr Vector3 Negate(Vector3 const& value)
|
||||
@ -474,12 +497,279 @@ namespace xna {
|
||||
|
||||
constexpr Vector4() = default;
|
||||
|
||||
constexpr Vector4(float value):
|
||||
X(value), Y(value), Z(value), W(value){}
|
||||
|
||||
constexpr Vector4(float X, float Y, float Z, float W)
|
||||
: X(X), Y(Y), Z(Z), W(W) { }
|
||||
|
||||
constexpr Vector4(Vector2 value, float Z, float W)
|
||||
: X(value.X), Y(value.Y), Z(Z), W(W) { }
|
||||
|
||||
constexpr Vector4(Vector3 value, float W)
|
||||
: X(value.X), Y(value.Y), Z(value.Z), W(W) { }
|
||||
|
||||
constexpr bool operator==(const Vector4& other) const {
|
||||
return X == other.X && Y == other.Y && Z == other.Z && W == other.W;
|
||||
}
|
||||
|
||||
static Vector4 Zero() { return {}; }
|
||||
static Vector4 One() { return { 1 }; }
|
||||
static Vector4 UnitX() { return { 1,0,0,0 }; }
|
||||
static Vector4 UnitY() { return { 0,1,0,0 }; }
|
||||
static Vector4 UnitZ() { return { 0,0,1,0 }; }
|
||||
static Vector4 UnitW() { return { 0,0,0,1 }; }
|
||||
|
||||
float Length() const {
|
||||
return sqrt(LengthSquared());
|
||||
}
|
||||
|
||||
constexpr float LengthSquared() const {
|
||||
return (X * X + Y * Y + Z * Z + W * W);
|
||||
}
|
||||
|
||||
inline static float Distance(Vector4 const& value1, Vector4 const& value2) {
|
||||
return sqrt(DistanceSquared(value1, value2));
|
||||
}
|
||||
|
||||
static constexpr float DistanceSquared(Vector4 const& value1, Vector4 const& value2) {
|
||||
const auto num1 = value1.X - value2.X;
|
||||
const auto num2 = value1.Y - value2.Y;
|
||||
const auto num3 = value1.Z - value2.Z;
|
||||
const auto num4 = value1.W - value2.W;
|
||||
return num1 * num1 + num2 * num2 + num3 * num3 + num4 * num4;
|
||||
}
|
||||
|
||||
static constexpr float Dot(Vector4 const& vector1, Vector4 const& vector2) {
|
||||
return vector1.X * vector2.X + vector1.Y * vector2.Y + vector1.Z * vector2.Z + vector1.W * vector2.W;
|
||||
}
|
||||
|
||||
void Normalize() {
|
||||
const auto num = 1.0f / Length();
|
||||
X *= num;
|
||||
Y *= num;
|
||||
Z *= num;
|
||||
W *= num;
|
||||
}
|
||||
|
||||
inline static Vector4 Normalize(Vector4 const& vector) {
|
||||
auto v = vector;
|
||||
v.Normalize();
|
||||
return v;
|
||||
}
|
||||
|
||||
static constexpr Vector4 Min(Vector4 const& value1, Vector4 const& value2) {
|
||||
Vector4 vector4;
|
||||
vector4.X = value1.X < value2.X ? value1.X : value2.X;
|
||||
vector4.Y = value1.Y < value2.Y ? value1.Y : value2.Y;
|
||||
vector4.Z = value1.Z < value2.Z ? value1.Z : value2.Z;
|
||||
vector4.W = value1.W < value2.W ? value1.W : value2.W;
|
||||
return vector4;
|
||||
}
|
||||
|
||||
static constexpr Vector4 Max(Vector4 const& value1, Vector4 const& value2) {
|
||||
Vector4 vector4;
|
||||
vector4.X = value1.X > value2.X ? value1.X : value2.X;
|
||||
vector4.Y = value1.Y > value2.Y ? value1.Y : value2.Y;
|
||||
vector4.Z = value1.Z > value2.Z ? value1.Z : value2.Z;
|
||||
vector4.W = value1.W > value2.W ? value1.W : value2.W;
|
||||
return vector4;
|
||||
}
|
||||
|
||||
static Vector4 Clamp(Vector4 const& value1, Vector4 const& min, Vector4 const& max) {
|
||||
const auto x = value1.X;
|
||||
const auto num1 = x > max.X ? max.X : x;
|
||||
const auto num2 = num1 < min.X ? min.X : num1;
|
||||
const auto y = value1.Y;
|
||||
const auto num3 = y > max.Y ? max.Y : y;
|
||||
const auto num4 = num3 < min.Y ? min.Y : num3;
|
||||
const auto z = value1.Z;
|
||||
const auto num5 = z > max.Z ? max.Z : z;
|
||||
const auto num6 = num5 < min.Z ? min.Z : num5;
|
||||
const auto w = value1.W;
|
||||
const auto num7 = w > max.W ? max.W : w;
|
||||
const auto num8 = num7 < min.W ? min.W : num7;
|
||||
Vector4 vector4;
|
||||
vector4.X = num2;
|
||||
vector4.Y = num4;
|
||||
vector4.Z = num6;
|
||||
vector4.W = num8;
|
||||
return vector4;
|
||||
}
|
||||
|
||||
static Vector4 Lerp(Vector4 const& value1, Vector4 const& value2, float amount) {
|
||||
Vector4 vector4;
|
||||
vector4.X = value1.X + (value2.X - value1.X) * amount;
|
||||
vector4.Y = value1.Y + (value2.Y - value1.Y) * amount;
|
||||
vector4.Z = value1.Z + (value2.Z - value1.Z) * amount;
|
||||
vector4.W = value1.W + (value2.W - value1.W) * amount;
|
||||
return vector4;
|
||||
}
|
||||
|
||||
static Vector4 Barycentric(Vector4 const& value1, Vector4 const& value2, Vector4 const& value3, float amount1, float amount2) {
|
||||
Vector4 vector4;
|
||||
vector4.X = value1.X + amount1 * (value2.X - value1.X) + amount2 * (value3.X - value1.X);
|
||||
vector4.Y = value1.Y + amount1 * (value2.Y - value1.Y) + amount2 * (value3.Y - value1.Y);
|
||||
vector4.Z = value1.Z + amount1 * (value2.Z - value1.Z) + amount2 * (value3.Z - value1.Z);
|
||||
vector4.W = value1.W + amount1 * (value2.W - value1.W) + amount2 * (value3.W - value1.W);
|
||||
return vector4;
|
||||
}
|
||||
|
||||
static Vector4 SmoothStep(Vector4 const& value1, Vector4 const& value2, float amount) {
|
||||
amount = amount > 1.0F ? 1.0f : (amount < 0.0F ? 0.0f : amount);
|
||||
amount = (amount * amount * (3.0F - 2.0F * amount));
|
||||
Vector4 vector4;
|
||||
vector4.X = value1.X + (value2.X - value1.X) * amount;
|
||||
vector4.Y = value1.Y + (value2.Y - value1.Y) * amount;
|
||||
vector4.Z = value1.Z + (value2.Z - value1.Z) * amount;
|
||||
vector4.W = value1.W + (value2.W - value1.W) * amount;
|
||||
return vector4;
|
||||
}
|
||||
|
||||
static Vector4 CatmullRom(Vector4 const& value1, Vector4 const& value2, Vector4 const& value3, Vector4 const& value4, float amount) {
|
||||
const auto num1 = amount * amount;
|
||||
const auto num2 = amount * num1;
|
||||
Vector4 vector4;
|
||||
vector4.X = 0.5F * (2.0f * value2.X + (-value1.X + value3.X) * amount + (2.0F * value1.X - 5.0f * value2.X + 4.0f * value3.X - value4.X) * num1 + (-value1.X + 3.0f * value2.X - 3.0f * value3.X + value4.X) * num2);
|
||||
vector4.Y = 0.5F * (2.0f * value2.Y + (-value1.Y + value3.Y) * amount + (2.0F * value1.Y - 5.0f * value2.Y + 4.0f * value3.Y - value4.Y) * num1 + (-value1.Y + 3.0f * value2.Y - 3.0f * value3.Y + value4.Y) * num2);
|
||||
vector4.Z = 0.5F * (2.0f * value2.Z + (-value1.Z + value3.Z) * amount + (2.0F * value1.Z - 5.0f * value2.Z + 4.0f * value3.Z - value4.Z) * num1 + (-value1.Z + 3.0f * value2.Z - 3.0f * value3.Z + value4.Z) * num2);
|
||||
vector4.W = 0.5F * (2.0f * value2.W + (-value1.W + value3.W) * amount + (2.0F * value1.W - 5.0f * value2.W + 4.0f * value3.W - value4.W) * num1 + (-value1.W + 3.0f * value2.W - 3.0f * value3.W + value4.W) * num2);
|
||||
return vector4;
|
||||
}
|
||||
|
||||
static Vector4 Hermite(Vector4 const& value1, Vector4 const& tangent1, Vector4 const& value2, Vector4 const& tangent2, float amount) {
|
||||
const auto num1 = amount * amount;
|
||||
const auto num2 = amount * num1;
|
||||
const auto num3 = (2.0F * num2 - 3.0F * num1 + 1.0F);
|
||||
const auto num4 = (-2.0F * num2 + 3.0F * num1);
|
||||
const auto num5 = num2 - 2.0f * num1 + amount;
|
||||
const auto num6 = num2 - num1;
|
||||
Vector4 vector4;
|
||||
vector4.X = (value1.X * num3 + value2.X * num4 + tangent1.X * num5 + tangent2.X * num6);
|
||||
vector4.Y = (value1.Y * num3 + value2.Y * num4 + tangent1.Y * num5 + tangent2.Y * num6);
|
||||
vector4.Z = (value1.Z * num3 + value2.Z * num4 + tangent1.Z * num5 + tangent2.Z * num6);
|
||||
vector4.W = (value1.W * num3 + value2.W * num4 + tangent1.W * num5 + tangent2.W * num6);
|
||||
return vector4;
|
||||
}
|
||||
|
||||
static constexpr Vector4 Transform(Vector2 const& position, Matrix const& matrix);
|
||||
static constexpr Vector4 Transform(Vector3 const& position, Matrix const& matrix);
|
||||
static constexpr Vector4 Transform(Vector4 const& vector, Matrix const& matrix);
|
||||
static constexpr Vector4 Transform(Vector2 const& value, Quaternion const& rotation);
|
||||
static constexpr Vector4 Transform(Vector3 const& value, Quaternion const& rotation);
|
||||
static bool Transform(Vector4 const* sourceArray, size_t sourceLength, Matrix const& matrix, Vector4* destinationArray, size_t destinationLength);
|
||||
static bool Transform(std::vector<Vector4> const& sourceArray, size_t sourceLength, Matrix const& matrix, std::vector<Vector4>& destinationArray);
|
||||
static bool Transform(Vector4 const* sourceArray, size_t sourceLength, size_t sourceIndex, Matrix const& matrix, Vector4* destinationArray, size_t destinationLength, size_t destinationIndex, size_t length);
|
||||
static bool Transform(std::vector<Vector4> const& sourceArray, size_t sourceIndex, Matrix const& matrix, std::vector<Vector4>& destinationArray, size_t destinationIndex, size_t length);
|
||||
static bool Transform(Vector4 const* sourceArray, size_t sourceLength, Quaternion const& rotation, Vector4* destinationArray, size_t destinationLength);
|
||||
static bool Transform(std::vector<Vector4> const& sourceArray, Quaternion const& rotation, std::vector<Vector4>& destinationArray);
|
||||
static bool Transform(Vector4 const* sourceArray, size_t sourceLength, size_t sourceIndex, Quaternion const& rotation, Vector4* destinationArray, size_t destinationLength, size_t destinationIndex, size_t length);
|
||||
static bool Transform(std::vector<Vector4> const& sourceArray, size_t sourceIndex, Quaternion const& rotation, std::vector<Vector4>& destinationArray, size_t destinationIndex, size_t length);
|
||||
|
||||
static constexpr Vector4 Negate(Vector4 const& value) {
|
||||
Vector4 vector4;
|
||||
vector4.X = -value.X;
|
||||
vector4.Y = -value.Y;
|
||||
vector4.Z = -value.Z;
|
||||
vector4.W = -value.W;
|
||||
return vector4;
|
||||
}
|
||||
|
||||
static constexpr Vector4 Add(Vector4 const& value1, Vector4 const& value2) {
|
||||
Vector4 vector4;
|
||||
vector4.X = value1.X + value2.X;
|
||||
vector4.Y = value1.Y + value2.Y;
|
||||
vector4.Z = value1.Z + value2.Z;
|
||||
vector4.W = value1.W + value2.W;
|
||||
return vector4;
|
||||
}
|
||||
|
||||
static constexpr Vector4 Subtract(Vector4 const& value1, Vector4 const& value2) {
|
||||
Vector4 vector4;
|
||||
vector4.X = value1.X - value2.X;
|
||||
vector4.Y = value1.Y - value2.Y;
|
||||
vector4.Z = value1.Z - value2.Z;
|
||||
vector4.W = value1.W - value2.W;
|
||||
return vector4;
|
||||
}
|
||||
|
||||
static constexpr Vector4 Multiply(Vector4 const& value1, Vector4 const& value2)
|
||||
{
|
||||
Vector4 vector4;
|
||||
vector4.X = value1.X * value2.X;
|
||||
vector4.Y = value1.Y * value2.Y;
|
||||
vector4.Z = value1.Z * value2.Z;
|
||||
vector4.W = value1.W * value2.W;
|
||||
return vector4;
|
||||
}
|
||||
|
||||
|
||||
static constexpr Vector4 Multiply(Vector4 const& value1, float scaleFactor)
|
||||
{
|
||||
Vector4 vector4;
|
||||
vector4.X = value1.X * scaleFactor;
|
||||
vector4.Y = value1.Y * scaleFactor;
|
||||
vector4.Z = value1.Z * scaleFactor;
|
||||
vector4.W = value1.W * scaleFactor;
|
||||
return vector4;
|
||||
}
|
||||
|
||||
static constexpr Vector4 Divide(Vector4 const& value1, Vector4 const& value2)
|
||||
{
|
||||
Vector4 vector4;
|
||||
vector4.X = value1.X / value2.X;
|
||||
vector4.Y = value1.Y / value2.Y;
|
||||
vector4.Z = value1.Z / value2.Z;
|
||||
vector4.W = value1.W / value2.W;
|
||||
return vector4;
|
||||
}
|
||||
|
||||
static constexpr Vector4 Divide(Vector4 const& value1, float divider)
|
||||
{
|
||||
float num = 1.0f / divider;
|
||||
Vector4 vector4;
|
||||
vector4.X = value1.X * num;
|
||||
vector4.Y = value1.Y * num;
|
||||
vector4.Z = value1.Z * num;
|
||||
vector4.W = value1.W * num;
|
||||
return vector4;
|
||||
}
|
||||
|
||||
constexpr Vector4 operator-() const {
|
||||
return Vector4::Negate(*this);
|
||||
}
|
||||
|
||||
friend constexpr Vector4 operator+(Vector4 const& value1, Vector4 const& value2) {
|
||||
return Vector4::Add(value1, value2);
|
||||
}
|
||||
|
||||
friend constexpr Vector4 operator-(Vector4 const& value1, Vector4 const& value2) {
|
||||
return Vector4::Subtract(value1, value2);
|
||||
}
|
||||
|
||||
friend constexpr Vector4 operator*(Vector4 const& value1, Vector4 const& value2) {
|
||||
return Vector4::Multiply(value1, value2);
|
||||
}
|
||||
|
||||
friend constexpr Vector4 operator*(Vector4 const& value, float factor) {
|
||||
return Vector4::Multiply(value, factor);
|
||||
}
|
||||
|
||||
friend constexpr Vector4 operator*(float factor, Vector4 const& value) {
|
||||
return Vector4::Multiply(value, factor);
|
||||
}
|
||||
|
||||
friend constexpr Vector4 operator/(Vector4 const& value1, Vector4 const& value2) {
|
||||
return Vector4::Divide(value1, value2);
|
||||
}
|
||||
|
||||
friend constexpr Vector4 operator/(Vector4 const& value, float divider) {
|
||||
return Vector4::Divide(value, divider);
|
||||
}
|
||||
|
||||
friend constexpr Vector4 operator/(float divider, Vector4 const& value) {
|
||||
return Vector4::Divide(value, divider);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
223
framework/content/defaultreaders.hpp
Normal file
223
framework/content/defaultreaders.hpp
Normal file
@ -0,0 +1,223 @@
|
||||
#ifndef XNA_CONTENT_DEFAULTREADERS_ARRAY_HPP
|
||||
#define XNA_CONTENT_DEFAULTREADERS_ARRAY_HPP
|
||||
|
||||
#include "reader.hpp"
|
||||
#include "../default.hpp"
|
||||
#include "../common/color.hpp"
|
||||
#include "../common/matrix.hpp"
|
||||
#include "../common/point.hpp"
|
||||
#include "../common/rectangle.hpp"
|
||||
#include "../csharp/timespan.hpp"
|
||||
|
||||
namespace xna {
|
||||
class ObjectReader : public ContentTypeReaderT<Object> {
|
||||
public:
|
||||
ObjectReader() : ContentTypeReaderT(typeof<Object>()) {}
|
||||
|
||||
virtual Object Read(ContentReader& input, Object& existingInstance) override {
|
||||
return Object();
|
||||
}
|
||||
};
|
||||
|
||||
class BooleanReader : public ContentTypeReaderT<bool> {
|
||||
public:
|
||||
BooleanReader() : ContentTypeReaderT(typeof<bool>()) {}
|
||||
|
||||
bool Read(ContentReader& input, bool& existingInstance) override {
|
||||
return input.ReadBoolean();
|
||||
}
|
||||
};
|
||||
|
||||
class ByteReader : public ContentTypeReaderT<Byte> {
|
||||
public:
|
||||
ByteReader() : ContentTypeReaderT(typeof<Byte>()) {}
|
||||
|
||||
Byte Read(ContentReader& input, Byte& existingInstance) override {
|
||||
const auto b = input.ReadByte();
|
||||
return b;
|
||||
}
|
||||
};
|
||||
|
||||
class CharReader : public ContentTypeReaderT<Char> {
|
||||
public:
|
||||
CharReader() : ContentTypeReaderT(typeof<Char>()) {}
|
||||
|
||||
Char Read(ContentReader& input, Char& existingInstance) override {
|
||||
const auto b = input.ReadChar();
|
||||
return b;
|
||||
}
|
||||
};
|
||||
|
||||
class ColorReader : public ContentTypeReaderT<Color> {
|
||||
public:
|
||||
ColorReader() : ContentTypeReaderT(typeof<Color>()) {}
|
||||
|
||||
Color Read(ContentReader& input, Color& existingInstance) override {
|
||||
const auto i = input.ReadUInt32();
|
||||
return { i };
|
||||
}
|
||||
};
|
||||
|
||||
class DoubleReader : public ContentTypeReaderT<double> {
|
||||
public:
|
||||
DoubleReader() : ContentTypeReaderT(typeof<double>()) {}
|
||||
|
||||
double Read(ContentReader& input, double& existingInstance) override {
|
||||
return input.ReadDouble();
|
||||
}
|
||||
};
|
||||
|
||||
class Int16Reader : public ContentTypeReaderT<Short> {
|
||||
public:
|
||||
Int16Reader() : ContentTypeReaderT(typeof<Short>()) {}
|
||||
|
||||
Short Read(ContentReader& input, Short& existingInstance) override {
|
||||
return input.ReadInt16();
|
||||
}
|
||||
};
|
||||
|
||||
class Int32Reader : public ContentTypeReaderT<Int> {
|
||||
public:
|
||||
Int32Reader() : ContentTypeReaderT(typeof<Int>()) {}
|
||||
|
||||
Int Read(ContentReader& input, Int& existingInstance) override {
|
||||
return input.ReadInt32();
|
||||
}
|
||||
};
|
||||
|
||||
class Int64Reader : public ContentTypeReaderT<Long> {
|
||||
public:
|
||||
Int64Reader() : ContentTypeReaderT(typeof<Long>()) {}
|
||||
|
||||
Long Read(ContentReader& input, Long& existingInstance) override {
|
||||
return input.ReadInt64();
|
||||
}
|
||||
};
|
||||
|
||||
class MatrixReader : public ContentTypeReaderT<Matrix> {
|
||||
public:
|
||||
MatrixReader() : ContentTypeReaderT(typeof<Matrix>()) {}
|
||||
|
||||
Matrix Read(ContentReader& input, Matrix& existingInstance) override {
|
||||
return input.ReadMatrix();
|
||||
}
|
||||
};
|
||||
|
||||
class PointReader : public ContentTypeReaderT<Point> {
|
||||
public:
|
||||
PointReader() : ContentTypeReaderT(typeof<Point>()) {}
|
||||
|
||||
Point Read(ContentReader& input, Point& existingInstance) override {
|
||||
Point point;
|
||||
point.X = input.ReadInt32();
|
||||
point.Y = input.ReadInt32();
|
||||
return point;
|
||||
}
|
||||
};
|
||||
|
||||
class QuaternionReader : public ContentTypeReaderT<Quaternion> {
|
||||
public:
|
||||
QuaternionReader() : ContentTypeReaderT(typeof<Quaternion>()) {}
|
||||
|
||||
Quaternion Read(ContentReader& input, Quaternion& existingInstance) override {
|
||||
return input.ReadQuaternion();
|
||||
}
|
||||
};
|
||||
|
||||
class RectangleReader : public ContentTypeReaderT<Rectangle> {
|
||||
public:
|
||||
RectangleReader() : ContentTypeReaderT(typeof<Rectangle>()) {}
|
||||
|
||||
Rectangle Read(ContentReader& input, Rectangle& existingInstance) override {
|
||||
Rectangle rectangle;
|
||||
rectangle.X = input.ReadInt32();
|
||||
rectangle.Y = input.ReadInt32();
|
||||
rectangle.Width = input.ReadInt32();
|
||||
rectangle.Height = input.ReadInt32();
|
||||
return rectangle;
|
||||
}
|
||||
};
|
||||
|
||||
class SByteReader : public ContentTypeReaderT<Sbyte> {
|
||||
public:
|
||||
SByteReader() : ContentTypeReaderT(typeof<Sbyte>()) {}
|
||||
|
||||
Sbyte Read(ContentReader& input, Sbyte& existingInstance) override {
|
||||
return input.ReadSByte();
|
||||
}
|
||||
};
|
||||
|
||||
class SingleReader : public ContentTypeReaderT<float> {
|
||||
public:
|
||||
SingleReader() : ContentTypeReaderT(typeof<float>()) {}
|
||||
|
||||
float Read(ContentReader& input, float& existingInstance) override {
|
||||
return input.ReadSingle();
|
||||
}
|
||||
};
|
||||
|
||||
class TimeSpanReader : public ContentTypeReaderT<TimeSpan> {
|
||||
public:
|
||||
TimeSpanReader() : ContentTypeReaderT(typeof<TimeSpan>()) {}
|
||||
|
||||
TimeSpan Read(ContentReader& input, TimeSpan& existingInstance) override {
|
||||
return TimeSpan::FromTicks(input.ReadInt64());
|
||||
}
|
||||
};
|
||||
|
||||
class UInt16Reader : public ContentTypeReaderT<Ushort> {
|
||||
public:
|
||||
UInt16Reader() : ContentTypeReaderT(typeof<Ushort>()) {}
|
||||
|
||||
Ushort Read(ContentReader& input, Ushort& existingInstance) override {
|
||||
return input.ReadUInt16();
|
||||
}
|
||||
};
|
||||
|
||||
class UInt32Reader : public ContentTypeReaderT<Uint> {
|
||||
public:
|
||||
UInt32Reader() : ContentTypeReaderT(typeof<Uint>()) {}
|
||||
|
||||
Uint Read(ContentReader& input, Uint& existingInstance) override {
|
||||
return input.ReadUInt32();
|
||||
}
|
||||
};
|
||||
|
||||
class UInt64Reader : public ContentTypeReaderT<Ulong> {
|
||||
public:
|
||||
UInt64Reader() : ContentTypeReaderT(typeof<Ulong>()) {}
|
||||
|
||||
Ulong Read(ContentReader& input, Ulong& existingInstance) override {
|
||||
return input.ReadUInt64();
|
||||
}
|
||||
};
|
||||
|
||||
class Vector2Reader : public ContentTypeReaderT<Vector2> {
|
||||
public:
|
||||
Vector2Reader() : ContentTypeReaderT(typeof<Vector2>()) {}
|
||||
|
||||
Vector2 Read(ContentReader& input, Vector2& existingInstance) override {
|
||||
return input.ReadVector2();
|
||||
}
|
||||
};
|
||||
|
||||
class Vector3Reader : public ContentTypeReaderT<Vector3> {
|
||||
public:
|
||||
Vector3Reader() : ContentTypeReaderT(typeof<Vector3>()) {}
|
||||
|
||||
Vector3 Read(ContentReader& input, Vector3& existingInstance) override {
|
||||
return input.ReadVector3();
|
||||
}
|
||||
};
|
||||
|
||||
class Vector4Reader : public ContentTypeReaderT<Vector4> {
|
||||
public:
|
||||
Vector4Reader() : ContentTypeReaderT(typeof<Vector4>()) {}
|
||||
|
||||
Vector4 Read(ContentReader& input, Vector4& existingInstance) override {
|
||||
return input.ReadVector4();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
5
framework/content/lzx/decoder.cpp
Normal file
5
framework/content/lzx/decoder.cpp
Normal file
@ -0,0 +1,5 @@
|
||||
#include "decoder.hpp"
|
||||
|
||||
namespace xna {
|
||||
|
||||
}
|
787
framework/content/lzx/decoder.hpp
Normal file
787
framework/content/lzx/decoder.hpp
Normal file
@ -0,0 +1,787 @@
|
||||
#ifndef XNA_CONTENT_LZX_LZXDECODE_HPP
|
||||
#define XNA_CONTENT_LZX_LZXDECODE_HPP
|
||||
|
||||
#include "../../default.hpp"
|
||||
#include "../../csharp/stream.hpp"
|
||||
#include <algorithm>
|
||||
|
||||
namespace xna {
|
||||
struct LzxConstants {
|
||||
static constexpr Ushort MIN_MATCH = 2;
|
||||
static constexpr Ushort MAX_MATCH = 257;
|
||||
static constexpr Ushort NUM_CHARS = 256;
|
||||
|
||||
enum class BLOCKTYPE {
|
||||
INVALID = 0,
|
||||
VERBATIM = 1,
|
||||
ALIGNED = 2,
|
||||
UNCOMPRESSED = 3
|
||||
};
|
||||
|
||||
static constexpr Ushort PRETREE_NUM_ELEMENTS = 20;
|
||||
static constexpr Ushort ALIGNED_NUM_ELEMENTS = 8;
|
||||
static constexpr Ushort NUM_PRIMARY_LENGTHS = 7;
|
||||
static constexpr Ushort NUM_SECONDARY_LENGTHS = 249;
|
||||
|
||||
static constexpr Ushort PRETREE_MAXSYMBOLS = PRETREE_NUM_ELEMENTS;
|
||||
static constexpr Ushort PRETREE_TABLEBITS = 6;
|
||||
static constexpr Ushort MAINTREE_MAXSYMBOLS = NUM_CHARS + 50 * 8;
|
||||
static constexpr Ushort MAINTREE_TABLEBITS = 12;
|
||||
static constexpr Ushort LENGTH_MAXSYMBOLS = NUM_SECONDARY_LENGTHS + 1;
|
||||
static constexpr Ushort LENGTH_TABLEBITS = 12;
|
||||
static constexpr Ushort ALIGNED_MAXSYMBOLS = ALIGNED_NUM_ELEMENTS;
|
||||
static constexpr Ushort ALIGNED_TABLEBITS = 7;
|
||||
|
||||
static constexpr Ushort LENTABLE_SAFETY = 64;
|
||||
};
|
||||
|
||||
struct LzxState {
|
||||
Uint R0{ 1 }, R1{ 1 }, R2{ 1 }; /* for the LRU offset system */
|
||||
Ushort main_elements{ 0 }; /* number of main tree elements */
|
||||
Int header_read{ 0 }; /* have we started decoding at all yet? */
|
||||
LzxConstants::BLOCKTYPE block_type{ LzxConstants::BLOCKTYPE::INVALID }; /* type of this block */
|
||||
Uint block_length{ 0 }; /* uncompressed length of this block */
|
||||
Uint block_remaining{ 0 }; /* uncompressed bytes still left to decode */
|
||||
Uint frames_read{ 0 }; /* the number of CFDATA blocks processed */
|
||||
Int intel_filesize{ 0 }; /* magic header value used for transform */
|
||||
Int intel_curpos{ 0 }; /* current offset in transform space */
|
||||
Int intel_started{ 0 }; /* have we seen any translateable data yet? */
|
||||
|
||||
std::vector<Ushort> PRETREE_table;
|
||||
std::vector<Byte> PRETREE_len;
|
||||
std::vector<Ushort> MAINTREE_table;
|
||||
std::vector<Byte> MAINTREE_len;
|
||||
std::vector<Ushort> LENGTH_table;
|
||||
std::vector<Byte> LENGTH_len;
|
||||
std::vector<Ushort> ALIGNED_table;
|
||||
std::vector<Byte> ALIGNED_len;
|
||||
|
||||
// NEEDED MEMBERS
|
||||
// CAB actualsize
|
||||
// CAB window
|
||||
// CAB window_size
|
||||
// CAB window_posn
|
||||
Uint actual_size{ 0 };
|
||||
std::vector<Byte> window;
|
||||
Uint window_size{ 0 };
|
||||
Uint window_posn{ 0 };
|
||||
};
|
||||
|
||||
class BitBuffer {
|
||||
public:
|
||||
BitBuffer(sptr<Stream> const& stream) : byteStream(stream) {
|
||||
InitBitStream();
|
||||
}
|
||||
|
||||
constexpr void InitBitStream() {
|
||||
buffer = 0;
|
||||
bitsleft = 0;
|
||||
}
|
||||
|
||||
void EnsureBits(Byte bits) {
|
||||
while (bitsleft < bits) {
|
||||
const auto lo = static_cast<Byte>(byteStream->ReadByte());
|
||||
const auto hi = static_cast<Byte>(byteStream->ReadByte());
|
||||
//int amount2shift = sizeofstatic_cast<Uint>(*8 - 16 - bitsleft;
|
||||
buffer |= static_cast<Uint>(((hi << 8) | lo) << (sizeof(Uint) * 8 - 16 - bitsleft));
|
||||
bitsleft += 16;
|
||||
}
|
||||
}
|
||||
|
||||
constexpr Uint PeekBits(Byte bits) const
|
||||
{
|
||||
return (buffer >> ((sizeof(Uint) * 8) - bits));
|
||||
}
|
||||
|
||||
constexpr void RemoveBits(Byte bits) {
|
||||
buffer <<= bits;
|
||||
bitsleft -= bits;
|
||||
}
|
||||
|
||||
Uint ReadBits(Byte bits)
|
||||
{
|
||||
Uint ret = 0;
|
||||
|
||||
if (bits > 0)
|
||||
{
|
||||
EnsureBits(bits);
|
||||
ret = PeekBits(bits);
|
||||
RemoveBits(bits);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
constexpr Uint GetBuffer() const {
|
||||
return buffer;
|
||||
}
|
||||
|
||||
constexpr Byte GetBitsLeft() const {
|
||||
return bitsleft;
|
||||
}
|
||||
|
||||
private:
|
||||
Uint buffer{ 0 };
|
||||
Byte bitsleft{ 0 };
|
||||
sptr<Stream> byteStream = nullptr;
|
||||
};
|
||||
|
||||
class LzxDecoder {
|
||||
public:
|
||||
LzxDecoder(Int window) {
|
||||
Uint wndsize = (Uint)(1 << window);
|
||||
Int posn_slots = 0;
|
||||
|
||||
// setup proper exception
|
||||
if (window < 15 || window > 21)
|
||||
return;
|
||||
|
||||
// let's initialise our state
|
||||
m_state.window = std::vector<Byte>(wndsize, 0xDC);
|
||||
|
||||
m_state.actual_size = wndsize;
|
||||
m_state.window_size = wndsize;
|
||||
|
||||
/* initialize static tables */
|
||||
|
||||
if (extra_bits.empty()) {
|
||||
extra_bits.resize(52);
|
||||
|
||||
for (size_t i = 0, j = 0; i <= 50; i += 2) {
|
||||
extra_bits[i] = extra_bits[i + 1] = static_cast<Byte>(j);
|
||||
|
||||
if ((i != 0) && (j < 17))
|
||||
j++;
|
||||
}
|
||||
}
|
||||
|
||||
if (position_base.empty()) {
|
||||
position_base.resize(51);
|
||||
|
||||
for (size_t i = 0, j = 0; i <= 50; i++) {
|
||||
position_base[i] = static_cast<Uint>(j);
|
||||
j += static_cast<size_t>(1) << extra_bits[i];
|
||||
}
|
||||
}
|
||||
|
||||
/* calculate required position slots */
|
||||
if (window == 20)
|
||||
posn_slots = 42;
|
||||
else if (window == 21)
|
||||
posn_slots = 50;
|
||||
else
|
||||
posn_slots = window << 1;
|
||||
|
||||
m_state.main_elements = static_cast<Ushort>(LzxConstants::NUM_CHARS + (posn_slots << 3));
|
||||
|
||||
// yo dawg i herd u liek arrays so we put arrays in ur arrays so u can array while u array
|
||||
m_state.PRETREE_table = std::vector<Ushort>((1 << LzxConstants::PRETREE_TABLEBITS) + (LzxConstants::PRETREE_MAXSYMBOLS << 1));
|
||||
m_state.PRETREE_len = std::vector<Byte>(LzxConstants::PRETREE_MAXSYMBOLS + LzxConstants::LENTABLE_SAFETY);
|
||||
m_state.MAINTREE_table = std::vector<Ushort>((1 << LzxConstants::MAINTREE_TABLEBITS) + (LzxConstants::MAINTREE_MAXSYMBOLS << 1));
|
||||
m_state.MAINTREE_len = std::vector<Byte>(LzxConstants::MAINTREE_MAXSYMBOLS + LzxConstants::LENTABLE_SAFETY);
|
||||
m_state.LENGTH_table = std::vector<Ushort>((1 << LzxConstants::LENGTH_TABLEBITS) + (LzxConstants::LENGTH_MAXSYMBOLS << 1));
|
||||
m_state.LENGTH_len = std::vector<Byte>(LzxConstants::LENGTH_MAXSYMBOLS + LzxConstants::LENTABLE_SAFETY);
|
||||
m_state.ALIGNED_table = std::vector<Ushort>((1 << LzxConstants::ALIGNED_TABLEBITS) + (LzxConstants::ALIGNED_MAXSYMBOLS << 1));
|
||||
m_state.ALIGNED_len = std::vector<Byte>(LzxConstants::ALIGNED_MAXSYMBOLS + LzxConstants::LENTABLE_SAFETY);
|
||||
|
||||
/* initialise tables to 0 (because deltas will be applied to them) */
|
||||
for (size_t i = 0; i < LzxConstants::MAINTREE_MAXSYMBOLS; i++)
|
||||
m_state.MAINTREE_len[i] = 0;
|
||||
|
||||
for (size_t i = 0; i < LzxConstants::LENGTH_MAXSYMBOLS; i++)
|
||||
m_state.LENGTH_len[i] = 0;
|
||||
}
|
||||
|
||||
Int Decompress(sptr<Stream>& inData, Int inLen, sptr<Stream>& outData, Int outLen) {
|
||||
BitBuffer bitbuf(inData);
|
||||
|
||||
auto startpos = inData->Position();
|
||||
auto endpos = inData->Position() + inLen;
|
||||
|
||||
auto& window = m_state.window;
|
||||
|
||||
Uint window_posn = m_state.window_posn;
|
||||
Uint window_size = m_state.window_size;
|
||||
Uint R0 = m_state.R0;
|
||||
Uint R1 = m_state.R1;
|
||||
Uint R2 = m_state.R2;
|
||||
Uint i = 0;
|
||||
Uint j = 0;
|
||||
|
||||
Int togo = outLen;
|
||||
Int this_run = 0;
|
||||
Int main_element = 0;
|
||||
Int match_length = 0;
|
||||
Int match_offset = 0;
|
||||
Int length_footer = 0;
|
||||
Int extra = 0;
|
||||
Int verbatim_bits = 0;
|
||||
Int rundest = 0;
|
||||
Int runsrc = 0;
|
||||
Int copy_length = 0;
|
||||
Int aligned_bits = 0;
|
||||
|
||||
bitbuf.InitBitStream();
|
||||
|
||||
/* read header if necessary */
|
||||
if (m_state.header_read == 0)
|
||||
{
|
||||
const auto intel = bitbuf.ReadBits(1);
|
||||
if (intel != 0)
|
||||
{
|
||||
// read the filesize
|
||||
i = bitbuf.ReadBits(16);
|
||||
j = bitbuf.ReadBits(16);
|
||||
m_state.intel_filesize = static_cast<Int>((i << 16) | j);
|
||||
}
|
||||
m_state.header_read = 1;
|
||||
}
|
||||
|
||||
while (togo > 0)
|
||||
{
|
||||
/* last block finished, new block expected */
|
||||
if (m_state.block_remaining == 0)
|
||||
{
|
||||
// TODO may screw something up here
|
||||
if (m_state.block_type == LzxConstants::BLOCKTYPE::UNCOMPRESSED) {
|
||||
if ((m_state.block_length & 1) == 1)
|
||||
inData->ReadByte(); /* realign bitstream to word */
|
||||
|
||||
bitbuf.InitBitStream();
|
||||
}
|
||||
|
||||
m_state.block_type = static_cast<LzxConstants::BLOCKTYPE>(bitbuf.ReadBits(3));
|
||||
i = bitbuf.ReadBits(16);
|
||||
j = bitbuf.ReadBits(8);
|
||||
m_state.block_remaining = m_state.block_length = static_cast<Uint>((i << 8) | j);
|
||||
|
||||
switch (m_state.block_type) {
|
||||
case LzxConstants::BLOCKTYPE::ALIGNED: {
|
||||
for (i = 0, j = 0; i < 8; i++) {
|
||||
j = bitbuf.ReadBits(3);
|
||||
m_state.ALIGNED_len[i] = static_cast<Byte>(j);
|
||||
}
|
||||
|
||||
MakeDecodeTable(LzxConstants::ALIGNED_MAXSYMBOLS, LzxConstants::ALIGNED_TABLEBITS,
|
||||
m_state.ALIGNED_len, m_state.ALIGNED_table);
|
||||
|
||||
//O mesmo que verbatim
|
||||
ReadLengths(m_state.MAINTREE_len, 0, 256, bitbuf);
|
||||
ReadLengths(m_state.MAINTREE_len, 256, m_state.main_elements, bitbuf);
|
||||
MakeDecodeTable(LzxConstants::MAINTREE_MAXSYMBOLS, LzxConstants::MAINTREE_TABLEBITS,
|
||||
m_state.MAINTREE_len, m_state.MAINTREE_table);
|
||||
|
||||
if (m_state.MAINTREE_len[0xE8] != 0)
|
||||
m_state.intel_started = 1;
|
||||
|
||||
ReadLengths(m_state.LENGTH_len, 0, LzxConstants::NUM_SECONDARY_LENGTHS, bitbuf);
|
||||
MakeDecodeTable(LzxConstants::LENGTH_MAXSYMBOLS, LzxConstants::LENGTH_TABLEBITS,
|
||||
m_state.LENGTH_len, m_state.LENGTH_table);
|
||||
break;
|
||||
}
|
||||
case LzxConstants::BLOCKTYPE::VERBATIM: {
|
||||
ReadLengths(m_state.MAINTREE_len, 0, 256, bitbuf);
|
||||
ReadLengths(m_state.MAINTREE_len, 256, m_state.main_elements, bitbuf);
|
||||
MakeDecodeTable(LzxConstants::MAINTREE_MAXSYMBOLS, LzxConstants::MAINTREE_TABLEBITS,
|
||||
m_state.MAINTREE_len, m_state.MAINTREE_table);
|
||||
|
||||
if (m_state.MAINTREE_len[0xE8] != 0)
|
||||
m_state.intel_started = 1;
|
||||
|
||||
ReadLengths(m_state.LENGTH_len, 0, LzxConstants::NUM_SECONDARY_LENGTHS, bitbuf);
|
||||
MakeDecodeTable(LzxConstants::LENGTH_MAXSYMBOLS, LzxConstants::LENGTH_TABLEBITS,
|
||||
m_state.LENGTH_len, m_state.LENGTH_table);
|
||||
break;
|
||||
}
|
||||
case LzxConstants::BLOCKTYPE::UNCOMPRESSED: {
|
||||
m_state.intel_started = 1; /* because we can't assume otherwise */
|
||||
bitbuf.EnsureBits(16); /* get up to 16 pad bits into the buffer */
|
||||
|
||||
if (bitbuf.GetBitsLeft() > 16)
|
||||
inData->Seek(-2, SeekOrigin::Current); /* and align the bitstream! */
|
||||
|
||||
Byte hi = 0;
|
||||
Byte mh = 0;
|
||||
Byte ml = 0;
|
||||
Byte lo = 0;
|
||||
|
||||
lo = static_cast<Byte>(inData->ReadByte());
|
||||
ml = static_cast<Byte>(inData->ReadByte());
|
||||
mh = static_cast<Byte>(inData->ReadByte());
|
||||
hi = static_cast<Byte>(inData->ReadByte());
|
||||
R0 = static_cast<Uint>(lo | ml << 8 | mh << 16 | hi << 24);
|
||||
lo = static_cast<Byte>(inData->ReadByte());
|
||||
ml = static_cast<Byte>(inData->ReadByte());
|
||||
mh = static_cast<Byte>(inData->ReadByte());
|
||||
hi = static_cast<Byte>(inData->ReadByte());
|
||||
R1 = static_cast<Uint>(lo | ml << 8 | mh << 16 | hi << 24);
|
||||
lo = static_cast<Byte>(inData->ReadByte());
|
||||
ml = static_cast<Byte>(inData->ReadByte());
|
||||
mh = static_cast<Byte>(inData->ReadByte());
|
||||
hi = static_cast<Byte>(inData->ReadByte());
|
||||
R2 = static_cast<Uint>(lo | ml << 8 | mh << 16 | hi << 24);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return -1; // TODO throw proper exception
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
/* buffer exhaustion check */
|
||||
if (inData->Position() > (startpos + inLen))
|
||||
{
|
||||
/* it's possible to have a file where the next run is less than
|
||||
* 16 bits in size. In this case, the READ_HUFFSYM() macro used
|
||||
* in building the tables will exhaust the buffer, so we should
|
||||
* allow for this, but not allow those accidentally read bits to
|
||||
* be used (so we check that there are at least 16 bits
|
||||
* remaining - in this boundary case they aren't really part of
|
||||
* the compressed data)
|
||||
*/
|
||||
//Debug.WriteLine("WTF");
|
||||
|
||||
if (inData->Position() > (startpos + inLen + 2) || bitbuf.GetBitsLeft() < 16)
|
||||
return -1; //TODO throw proper exception
|
||||
}
|
||||
|
||||
while ((this_run = static_cast<Int>(m_state.block_remaining)) > 0 && togo > 0)
|
||||
{
|
||||
if (this_run > togo)
|
||||
this_run = togo;
|
||||
|
||||
togo -= this_run;
|
||||
m_state.block_remaining -= static_cast<Uint>(this_run);
|
||||
|
||||
/* apply 2^x-1 mask */
|
||||
window_posn &= window_size - 1;
|
||||
/* runs can't straddle the window wraparound */
|
||||
if ((window_posn + this_run) > window_size)
|
||||
return -1; //TODO throw proper exception
|
||||
|
||||
switch (m_state.block_type)
|
||||
{
|
||||
case LzxConstants::BLOCKTYPE::VERBATIM: {
|
||||
while (this_run > 0)
|
||||
{
|
||||
main_element = static_cast<Int>(ReadHuffSym(m_state.MAINTREE_table, m_state.MAINTREE_len,
|
||||
LzxConstants::MAINTREE_MAXSYMBOLS, LzxConstants::MAINTREE_TABLEBITS,
|
||||
bitbuf));
|
||||
|
||||
if (main_element < LzxConstants::NUM_CHARS)
|
||||
{
|
||||
/* literal: 0 to NUM_CHARS-1 */
|
||||
window[window_posn++] = static_cast<Byte>(main_element);
|
||||
this_run--;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* match: NUM_CHARS + ((slot<<3) | length_header (3 bits)) */
|
||||
main_element -= LzxConstants::NUM_CHARS;
|
||||
|
||||
match_length = main_element & LzxConstants::NUM_PRIMARY_LENGTHS;
|
||||
if (match_length == LzxConstants::NUM_PRIMARY_LENGTHS)
|
||||
{
|
||||
length_footer = static_cast<Int>(ReadHuffSym(m_state.LENGTH_table, m_state.LENGTH_len,
|
||||
LzxConstants::LENGTH_MAXSYMBOLS, LzxConstants::LENGTH_TABLEBITS,
|
||||
bitbuf));
|
||||
match_length += length_footer;
|
||||
}
|
||||
match_length += LzxConstants::MIN_MATCH;
|
||||
|
||||
match_offset = main_element >> 3;
|
||||
|
||||
if (match_offset > 2)
|
||||
{
|
||||
/* not repeated offset */
|
||||
if (match_offset != 3)
|
||||
{
|
||||
extra = extra_bits[match_offset];
|
||||
verbatim_bits = static_cast<Int>(bitbuf.ReadBits(static_cast<Int>(extra)));
|
||||
match_offset = static_cast<Int>(position_base[match_offset]) - 2 + verbatim_bits;
|
||||
}
|
||||
else
|
||||
{
|
||||
match_offset = 1;
|
||||
}
|
||||
|
||||
/* update repeated offset LRU queue */
|
||||
R2 = R1; R1 = R0; R0 = static_cast<Uint>(match_offset);
|
||||
}
|
||||
else if (match_offset == 0)
|
||||
{
|
||||
match_offset = (int)R0;
|
||||
}
|
||||
else if (match_offset == 1)
|
||||
{
|
||||
match_offset = (int)R1;
|
||||
R1 = R0; R0 = static_cast<Uint>(match_offset);
|
||||
}
|
||||
else /* match_offset == 2 */
|
||||
{
|
||||
match_offset = (int)R2;
|
||||
R2 = R0; R0 = static_cast<Uint>(match_offset);
|
||||
}
|
||||
|
||||
rundest = (int)window_posn;
|
||||
this_run -= match_length;
|
||||
|
||||
/* copy any wrapped around source data */
|
||||
if (static_cast<Int>(window_posn) >= match_offset)
|
||||
{
|
||||
/* no wrap */
|
||||
runsrc = rundest - match_offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
runsrc = rundest + ((int)window_size - match_offset);
|
||||
copy_length = match_offset - (int)window_posn;
|
||||
if (copy_length < match_length)
|
||||
{
|
||||
match_length -= copy_length;
|
||||
window_posn += static_cast<Uint>(copy_length);
|
||||
while (copy_length-- > 0) window[rundest++] = window[runsrc++];
|
||||
runsrc = 0;
|
||||
}
|
||||
}
|
||||
window_posn += static_cast<Uint>(match_length);
|
||||
|
||||
/* copy match data - no worries about destination wraps */
|
||||
while (match_length-- > 0) window[rundest++] = window[runsrc++];
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case LzxConstants::BLOCKTYPE::ALIGNED: {
|
||||
while (this_run > 0)
|
||||
{
|
||||
main_element = static_cast<Int>(ReadHuffSym(m_state.MAINTREE_table, m_state.MAINTREE_len,
|
||||
LzxConstants::MAINTREE_MAXSYMBOLS, LzxConstants::MAINTREE_TABLEBITS,
|
||||
bitbuf));
|
||||
|
||||
if (main_element < LzxConstants::NUM_CHARS)
|
||||
{
|
||||
/* literal 0 to NUM_CHARS-1 */
|
||||
window[window_posn++] = static_cast<Byte>(main_element);
|
||||
this_run--;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* match: NUM_CHARS + ((slot<<3) | length_header (3 bits)) */
|
||||
main_element -= LzxConstants::NUM_CHARS;
|
||||
|
||||
match_length = main_element & LzxConstants::NUM_PRIMARY_LENGTHS;
|
||||
if (match_length == LzxConstants::NUM_PRIMARY_LENGTHS)
|
||||
{
|
||||
length_footer = static_cast<Int>(ReadHuffSym(m_state.LENGTH_table, m_state.LENGTH_len,
|
||||
LzxConstants::LENGTH_MAXSYMBOLS, LzxConstants::LENGTH_TABLEBITS,
|
||||
bitbuf));
|
||||
match_length += length_footer;
|
||||
}
|
||||
match_length += LzxConstants::MIN_MATCH;
|
||||
|
||||
match_offset = main_element >> 3;
|
||||
|
||||
if (match_offset > 2)
|
||||
{
|
||||
/* not repeated offset */
|
||||
extra = extra_bits[match_offset];
|
||||
match_offset = static_cast<Int>(position_base[match_offset]) - 2;
|
||||
if (extra > 3)
|
||||
{
|
||||
/* verbatim and aligned bits */
|
||||
extra -= 3;
|
||||
verbatim_bits = static_cast<Int>(bitbuf.ReadBits(static_cast<Byte>(extra)));
|
||||
match_offset += (verbatim_bits << 3);
|
||||
aligned_bits = static_cast<Int>(ReadHuffSym(m_state.ALIGNED_table, m_state.ALIGNED_len,
|
||||
LzxConstants::ALIGNED_MAXSYMBOLS, LzxConstants::ALIGNED_TABLEBITS,
|
||||
bitbuf));
|
||||
match_offset += aligned_bits;
|
||||
}
|
||||
else if (extra == 3)
|
||||
{
|
||||
/* aligned bits only */
|
||||
aligned_bits = static_cast<Int>(ReadHuffSym(m_state.ALIGNED_table, m_state.ALIGNED_len,
|
||||
LzxConstants::ALIGNED_MAXSYMBOLS, LzxConstants::ALIGNED_TABLEBITS,
|
||||
bitbuf));
|
||||
match_offset += aligned_bits;
|
||||
}
|
||||
else if (extra > 0) /* extra==1, extra==2 */
|
||||
{
|
||||
/* verbatim bits only */
|
||||
verbatim_bits = static_cast<Int>(bitbuf.ReadBits(static_cast<Byte>(extra)));
|
||||
match_offset += verbatim_bits;
|
||||
}
|
||||
else /* extra == 0 */
|
||||
{
|
||||
/* ??? */
|
||||
match_offset = 1;
|
||||
}
|
||||
|
||||
/* update repeated offset LRU queue */
|
||||
R2 = R1; R1 = R0; R0 = static_cast<Uint>(match_offset);
|
||||
}
|
||||
else if (match_offset == 0)
|
||||
{
|
||||
match_offset = (int)R0;
|
||||
}
|
||||
else if (match_offset == 1)
|
||||
{
|
||||
match_offset = (int)R1;
|
||||
R1 = R0; R0 = static_cast<Uint>(match_offset);
|
||||
}
|
||||
else /* match_offset == 2 */
|
||||
{
|
||||
match_offset = (int)R2;
|
||||
R2 = R0; R0 = static_cast<Uint>(match_offset);
|
||||
}
|
||||
|
||||
rundest = (int)window_posn;
|
||||
this_run -= match_length;
|
||||
|
||||
/* copy any wrapped around source data */
|
||||
if (static_cast<Int>(window_posn) >= match_offset)
|
||||
{
|
||||
/* no wrap */
|
||||
runsrc = rundest - match_offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
runsrc = rundest + ((int)window_size - match_offset);
|
||||
copy_length = match_offset - (int)window_posn;
|
||||
if (copy_length < match_length)
|
||||
{
|
||||
match_length -= copy_length;
|
||||
window_posn += static_cast<Uint>(copy_length);
|
||||
while (copy_length-- > 0) window[rundest++] = window[runsrc++];
|
||||
runsrc = 0;
|
||||
}
|
||||
}
|
||||
window_posn += static_cast<Uint>(match_length);
|
||||
|
||||
/* copy match data - no worries about destination wraps */
|
||||
while (match_length-- > 0) window[rundest++] = window[runsrc++];
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case LzxConstants::BLOCKTYPE::UNCOMPRESSED: {
|
||||
if ((inData->Position() + this_run) > endpos) return -1; //TODO throw proper exception
|
||||
std::vector<Byte> temp_buffer(this_run);
|
||||
inData->Read(temp_buffer, 0, this_run);
|
||||
|
||||
for (size_t offset = 0; offset < temp_buffer.size(); ++offset)
|
||||
window[window_posn + offset] = temp_buffer[offset];
|
||||
|
||||
window_posn += static_cast<Uint>(this_run);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return -1; //TODO throw proper exception
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (togo != 0)
|
||||
return -1; //TODO throw proper exception
|
||||
|
||||
Int start_window_pos = static_cast<Int>(window_posn);
|
||||
|
||||
if (start_window_pos == 0)
|
||||
start_window_pos = static_cast<Int>(window_size);
|
||||
|
||||
start_window_pos -= outLen;
|
||||
outData->Write(window, start_window_pos, outLen);
|
||||
|
||||
m_state.window_posn = window_posn;
|
||||
m_state.R0 = R0;
|
||||
m_state.R1 = R1;
|
||||
m_state.R2 = R2;
|
||||
|
||||
// TODO finish intel E8 decoding
|
||||
/* intel E8 decoding */
|
||||
if ((m_state.frames_read++ < 32768) && m_state.intel_filesize != 0)
|
||||
{
|
||||
if (outLen <= 6 || m_state.intel_started == 0)
|
||||
{
|
||||
m_state.intel_curpos += outLen;
|
||||
}
|
||||
else
|
||||
{
|
||||
Int dataend = outLen - 10;
|
||||
auto curpos = static_cast<Uint>(m_state.intel_curpos);
|
||||
|
||||
m_state.intel_curpos = static_cast<Int>(curpos) + outLen;
|
||||
|
||||
while (outData->Position() < dataend)
|
||||
{
|
||||
if (outData->ReadByte() != 0xE8) {
|
||||
curpos++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public:
|
||||
inline static std::vector<Uint> position_base;
|
||||
inline static std::vector<Byte> extra_bits;
|
||||
|
||||
private:
|
||||
LzxState m_state;
|
||||
|
||||
Int MakeDecodeTable(Uint nsyms, Uint nbits, std::vector<Byte>& length, std::vector<Ushort>& table) {
|
||||
Ushort sym = 0;
|
||||
Uint leaf = 0;
|
||||
Byte bit_num = 1;
|
||||
Uint fill;
|
||||
Uint pos = 0; /* the current position in the decode table */
|
||||
Uint table_mask = static_cast<Uint>(1 << static_cast<Int>(nbits));
|
||||
Uint bit_mask = table_mask >> 1; /* don't do 0 length codes */
|
||||
Uint next_symbol = bit_mask; /* base of allocation for long codes */
|
||||
|
||||
/* fill entries for codes short enough for a direct mapping */
|
||||
while (bit_num <= nbits)
|
||||
{
|
||||
for (sym = 0; sym < nsyms; sym++)
|
||||
{
|
||||
if (length[sym] == bit_num)
|
||||
{
|
||||
leaf = pos;
|
||||
|
||||
if ((pos += bit_mask) > table_mask) return 1; /* table overrun */
|
||||
|
||||
/* fill all possible lookups of this symbol with the symbol itself */
|
||||
fill = bit_mask;
|
||||
while (fill-- > 0) table[leaf++] = sym;
|
||||
}
|
||||
}
|
||||
bit_mask >>= 1;
|
||||
bit_num++;
|
||||
}
|
||||
|
||||
/* if there are any codes longer than nbits */
|
||||
if (pos != table_mask)
|
||||
{
|
||||
/* clear the remainder of the table */
|
||||
for (sym = static_cast<Ushort>(pos);
|
||||
sym < table_mask; sym++) table[sym] = 0;
|
||||
|
||||
/* give ourselves room for codes to grow by up to 16 more bits */
|
||||
pos <<= 16;
|
||||
table_mask <<= 16;
|
||||
bit_mask = 1 << 15;
|
||||
|
||||
while (bit_num <= 16)
|
||||
{
|
||||
for (sym = 0; sym < nsyms; sym++)
|
||||
{
|
||||
if (length[sym] == bit_num)
|
||||
{
|
||||
leaf = pos >> 16;
|
||||
for (fill = 0; fill < bit_num - nbits; fill++)
|
||||
{
|
||||
/* if this path hasn't been taken yet, 'allocate' two entries */
|
||||
if (table[leaf] == 0)
|
||||
{
|
||||
table[(next_symbol << 1)] = 0;
|
||||
table[(next_symbol << 1) + 1] = 0;
|
||||
table[leaf] = static_cast<Ushort>(next_symbol++);
|
||||
}
|
||||
/* follow the path and select either left or right for next bit */
|
||||
leaf = static_cast<Uint>(table[leaf] << 1);
|
||||
if (((pos >> static_cast<Int>(15 - fill)) & 1) == 1) leaf++;
|
||||
}
|
||||
table[leaf] = sym;
|
||||
|
||||
if ((pos += bit_mask) > table_mask) return 1;
|
||||
}
|
||||
}
|
||||
bit_mask >>= 1;
|
||||
bit_num++;
|
||||
}
|
||||
}
|
||||
|
||||
/* full talbe? */
|
||||
if (pos == table_mask) return 0;
|
||||
|
||||
/* either erroneous table, or all elements are 0 - let's find out. */
|
||||
for (sym = 0; sym < nsyms; sym++) if (length[sym] != 0) return 1;
|
||||
return 0;
|
||||
}
|
||||
void ReadLengths(std::vector<Byte>& lens, Uint first, Uint last, BitBuffer& bitbuf) {
|
||||
Uint x = 0;
|
||||
Uint y = 0;
|
||||
Int z = 0;
|
||||
|
||||
// hufftbl pointer here?
|
||||
|
||||
for (x = 0; x < 20; x++)
|
||||
{
|
||||
y = bitbuf.ReadBits(4);
|
||||
m_state.PRETREE_len[x] = static_cast<Byte>(y);
|
||||
}
|
||||
|
||||
MakeDecodeTable(LzxConstants::PRETREE_MAXSYMBOLS, LzxConstants::PRETREE_TABLEBITS,
|
||||
m_state.PRETREE_len, m_state.PRETREE_table);
|
||||
|
||||
for (x = first; x < last;)
|
||||
{
|
||||
z = (int)ReadHuffSym(m_state.PRETREE_table, m_state.PRETREE_len,
|
||||
LzxConstants::PRETREE_MAXSYMBOLS, LzxConstants::PRETREE_TABLEBITS, bitbuf);
|
||||
if (z == 17)
|
||||
{
|
||||
y = bitbuf.ReadBits(4); y += 4;
|
||||
while (y-- != 0) lens[x++] = 0;
|
||||
}
|
||||
else if (z == 18)
|
||||
{
|
||||
y = bitbuf.ReadBits(5); y += 20;
|
||||
while (y-- != 0) lens[x++] = 0;
|
||||
}
|
||||
else if (z == 19)
|
||||
{
|
||||
y = bitbuf.ReadBits(1); y += 4;
|
||||
z = static_cast<Int>(ReadHuffSym(m_state.PRETREE_table, m_state.PRETREE_len,
|
||||
LzxConstants::PRETREE_MAXSYMBOLS, LzxConstants::PRETREE_TABLEBITS, bitbuf));
|
||||
z = lens[x] - z; if (z < 0) z += 17;
|
||||
while (y-- != 0) lens[x++] = static_cast<Byte>(z);
|
||||
}
|
||||
else
|
||||
{
|
||||
z = lens[x] - z; if (z < 0) z += 17;
|
||||
lens[x++] = static_cast<Byte>(z);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Uint ReadHuffSym(std::vector<Ushort>& table, std::vector<Byte>& lengths, Uint nsyms, Uint nbits, BitBuffer& bitbuf) {
|
||||
Uint i = 0;
|
||||
Uint j = 0;
|
||||
|
||||
bitbuf.EnsureBits(16);
|
||||
|
||||
if ((i = table[bitbuf.PeekBits(static_cast<Byte>(nbits))]) >= nsyms)
|
||||
{
|
||||
j = static_cast<Uint>(1 << static_cast<Int>((sizeof(Uint) * 8) - nbits));
|
||||
do
|
||||
{
|
||||
j >>= 1; i <<= 1; i |= (bitbuf.GetBuffer() & j) != 0 ? static_cast<Uint>(1) : 0;
|
||||
if (j == 0) return 0; // TODO throw proper exception
|
||||
} while ((i = table[i]) >= nsyms);
|
||||
}
|
||||
j = lengths[i];
|
||||
bitbuf.RemoveBits(static_cast<Byte>(j));
|
||||
|
||||
return i;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
40
framework/content/lzx/decoderstream.cpp
Normal file
40
framework/content/lzx/decoderstream.cpp
Normal file
@ -0,0 +1,40 @@
|
||||
#include "decoderstream.hpp"
|
||||
|
||||
namespace xna {
|
||||
Int LzxDecoderStream::Length()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
Long LzxDecoderStream::Position()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
void LzxDecoderStream::Close()
|
||||
{
|
||||
}
|
||||
Long LzxDecoderStream::Seek(Long offset, SeekOrigin const& origin, xna_error_ptr_arg)
|
||||
{
|
||||
return Long();
|
||||
}
|
||||
Int LzxDecoderStream::Read(Byte* buffer, Int bufferLength, Int offset, Int count, xna_error_ptr_arg)
|
||||
{
|
||||
return decompressedStream->Read(buffer, bufferLength, offset, count, err);
|
||||
}
|
||||
Int LzxDecoderStream::Read(std::vector<Byte>& buffer, Int offset, Int count, xna_error_ptr_arg)
|
||||
{
|
||||
return decompressedStream->Read(buffer, offset, count, err);
|
||||
}
|
||||
Int LzxDecoderStream::ReadByte(xna_error_ptr_arg)
|
||||
{
|
||||
return Int();
|
||||
}
|
||||
void LzxDecoderStream::Write(Byte const* buffer, Int bufferLength, Int offset, Int count, xna_error_ptr_arg)
|
||||
{
|
||||
}
|
||||
void LzxDecoderStream::Write(std::vector<Byte> const& buffer, Int offset, Int count, xna_error_ptr_arg)
|
||||
{
|
||||
}
|
||||
void LzxDecoderStream::WriteByte(Byte value, xna_error_ptr_arg)
|
||||
{
|
||||
}
|
||||
}
|
89
framework/content/lzx/decoderstream.hpp
Normal file
89
framework/content/lzx/decoderstream.hpp
Normal file
@ -0,0 +1,89 @@
|
||||
#ifndef XNA_CONTENT_LZX_DECODERSTREAM_HPP
|
||||
#define XNA_CONTENT_LZX_DECODERSTREAM_HPP
|
||||
|
||||
#include "decoder.hpp"
|
||||
|
||||
namespace xna {
|
||||
class LzxDecoderStream : public Stream {
|
||||
public:
|
||||
LzxDecoderStream(sptr<Stream>& input, Int decompressedSize, Int compressedSize) {
|
||||
dec = New<LzxDecoder>(16);
|
||||
Decompress(input, decompressedSize, compressedSize);
|
||||
}
|
||||
|
||||
private:
|
||||
void Decompress(sptr<Stream>& stream, Int decompressedSize, Int compressedSize) {
|
||||
//thanks to ShinAli (https://bitbucket.org/alisci01/xnbdecompressor)
|
||||
// default window size for XNB encoded files is 64Kb (need 16 bits to represent it)
|
||||
decompressedStream = New<MemoryStream>(decompressedSize);
|
||||
auto startPos = stream->Position();
|
||||
auto pos = startPos;
|
||||
|
||||
while (pos - startPos < compressedSize)
|
||||
{
|
||||
// the compressed stream is seperated into blocks that will decompress
|
||||
// into 32Kb or some other size if specified.
|
||||
// normal, 32Kb output blocks will have a short indicating the size
|
||||
// of the block before the block starts
|
||||
// blocks that have a defined output will be preceded by a byte of value
|
||||
// 0xFF (255), then a short indicating the output size and another
|
||||
// for the block size
|
||||
// all shorts for these cases are encoded in big endian order
|
||||
Int hi = stream->ReadByte();
|
||||
Int lo = stream->ReadByte();
|
||||
Int block_size = (hi << 8) | lo;
|
||||
Int frame_size = 0x8000; // frame size is 32Kb by default
|
||||
// does this block define a frame size?
|
||||
|
||||
if (hi == 0xFF) {
|
||||
hi = lo;
|
||||
lo = static_cast<Byte>(stream->ReadByte());
|
||||
frame_size = (hi << 8) | lo;
|
||||
hi = static_cast<Byte>(stream->ReadByte());
|
||||
lo = static_cast<Byte>(stream->ReadByte());
|
||||
block_size = (hi << 8) | lo;
|
||||
pos += 5;
|
||||
}
|
||||
else
|
||||
pos += 2;
|
||||
|
||||
// either says there is nothing to decode
|
||||
if (block_size == 0 || frame_size == 0)
|
||||
break;
|
||||
|
||||
auto decompressed = reinterpret_pointer_cast<Stream>(decompressedStream);
|
||||
dec->Decompress(stream, block_size, decompressed, frame_size);
|
||||
pos += block_size;
|
||||
|
||||
// reset the position of the input just incase the bit buffer
|
||||
// read in some unused bytes
|
||||
stream->Seek(pos, SeekOrigin::Begin);
|
||||
}
|
||||
|
||||
if (decompressedStream->Position() != decompressedSize)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
decompressedStream->Seek(0, SeekOrigin::Begin);
|
||||
}
|
||||
private:
|
||||
sptr<LzxDecoder> dec = nullptr;
|
||||
sptr<MemoryStream>decompressedStream = nullptr;
|
||||
|
||||
// Inherited via Stream
|
||||
Int Length() override;
|
||||
Long Position() override;
|
||||
void Close() override;
|
||||
Long Seek(Long offset, SeekOrigin const& origin, xna_error_nullarg) override;
|
||||
Int Read(Byte* buffer, Int bufferLength, Int offset, Int count, xna_error_nullarg) override;
|
||||
Int Read(std::vector<Byte>& buffer, Int offset, Int count, xna_error_nullarg) override;
|
||||
Int ReadByte(xna_error_nullarg) override;
|
||||
void Write(Byte const* buffer, Int bufferLength, Int offset, Int count, xna_error_nullarg) override;
|
||||
void Write(std::vector<Byte> const& buffer, Int offset, Int count, xna_error_nullarg) override;
|
||||
void WriteByte(Byte value, xna_error_nullarg) override;
|
||||
virtual constexpr bool IsClosed() override { return false; }
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
@ -1,21 +1,26 @@
|
||||
#ifndef XNA_CONTENT_MANAGER_HPP
|
||||
#define XNA_CONTENT_MANAGER_HPP
|
||||
|
||||
#include "../csharp/stream.hpp"
|
||||
#include "../default.hpp"
|
||||
#include "../game/servicecontainer.hpp"
|
||||
#include "reader.hpp"
|
||||
#include <algorithm>
|
||||
#include <filesystem>
|
||||
#include <map>
|
||||
#include <algorithm>
|
||||
#include "../csharp/stream.hpp"
|
||||
|
||||
namespace xna {
|
||||
class ContentManager {
|
||||
public:
|
||||
ContentManager(String const& rootDirectory) :
|
||||
_rootDirectory(rootDirectory),
|
||||
_path(rootDirectory){};
|
||||
friend class ContentReader;
|
||||
|
||||
virtual ~ContentManager(){
|
||||
Unload();
|
||||
ContentManager(String const& rootDirectory, sptr<GameServiceContainer> const& services) :
|
||||
_rootDirectory(rootDirectory){
|
||||
_services = services;
|
||||
};
|
||||
|
||||
static sptr<GameServiceContainer> Services() {
|
||||
return _services;
|
||||
}
|
||||
|
||||
constexpr String RootDirectory() const {
|
||||
@ -24,48 +29,43 @@ namespace xna {
|
||||
|
||||
void RootDirectory(String const& value) {
|
||||
_rootDirectory = value;
|
||||
_path = value;
|
||||
}
|
||||
|
||||
virtual void Unload() {
|
||||
if (_loadedAssets.empty())
|
||||
return;
|
||||
|
||||
_loadedAssets.clear();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
sptr<T> Load(String const& assetName) {
|
||||
if (assetName.empty()) return nullptr;
|
||||
T Load(String const& assetName) {
|
||||
if (assetName.empty()) return T();
|
||||
|
||||
if (_loadedAssets.contains(assetName)) {
|
||||
const auto& ptr = _loadedAssets[assetName];
|
||||
const auto obj1 = reinterpret_pointer_cast<T>(ptr);
|
||||
auto obj2 = ReadAsset<T>(assetName);
|
||||
|
||||
return obj1;
|
||||
}
|
||||
|
||||
const auto obj2 = ReadAsset<T>(assetName);
|
||||
return obj2;
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
protected:
|
||||
template <typename T>
|
||||
sptr<T> ReadAsset(String const& assetName) {
|
||||
T ReadAsset(String const& assetName) {
|
||||
auto input = OpenStream(assetName);
|
||||
|
||||
if (input->IsClosed())
|
||||
return T();
|
||||
|
||||
auto contentReader = ContentReader::Create(this, input, assetName);
|
||||
|
||||
return contentReader->ReadAsset<T>();
|
||||
}
|
||||
|
||||
sptr<Stream> OpenStream(String const& assetName) {
|
||||
String filePath = _rootDirectory + "\\" + assetName + contentExtension;
|
||||
const auto stream = New<FileStream>(filePath);
|
||||
const auto stream = New<FileStream>(filePath, FileMode::Open);
|
||||
//const auto stream = New<FileStream>(filePath);
|
||||
return reinterpret_pointer_cast<Stream>(stream);
|
||||
}
|
||||
|
||||
private:
|
||||
String _rootDirectory;
|
||||
std::filesystem::path _path;
|
||||
std::map<String, sptr<void>> _loadedAssets;
|
||||
String _rootDirectory;
|
||||
std::vector<Byte> byteBuffer;
|
||||
|
||||
inline const static String contentExtension = ".xnb";
|
||||
inline static sptr<GameServiceContainer> _services = nullptr;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -1,9 +1,173 @@
|
||||
#include "reader.hpp"
|
||||
#include "manager.hpp"
|
||||
#include "lzx/decoderstream.hpp"
|
||||
#include "typereadermanager.hpp"
|
||||
#include "manager.hpp"
|
||||
|
||||
namespace xna {
|
||||
sptr<ContentReader> ContentReader::Create(ContentManager* contentManager, Stream& input, String const& assetName)
|
||||
sptr<ContentReader> ContentReader::Create(ContentManager* contentManager, sptr<Stream>& input, String const& assetName)
|
||||
{
|
||||
return sptr<ContentReader>();
|
||||
Int graphicsProfile = 0;
|
||||
input = ContentReader::PrepareStream(input, assetName, graphicsProfile);
|
||||
return std::shared_ptr<ContentReader>(new ContentReader(contentManager, input, assetName, graphicsProfile));
|
||||
}
|
||||
|
||||
Vector2 ContentReader::ReadVector2()
|
||||
{
|
||||
Vector2 vector2;
|
||||
vector2.X = ReadSingle();
|
||||
vector2.Y = ReadSingle();
|
||||
return vector2;
|
||||
}
|
||||
|
||||
Vector3 ContentReader::ReadVector3()
|
||||
{
|
||||
Vector3 vector3;
|
||||
vector3.X = ReadSingle();
|
||||
vector3.Y = ReadSingle();
|
||||
vector3.Z = ReadSingle();
|
||||
return vector3;
|
||||
}
|
||||
|
||||
Vector4 ContentReader::ReadVector4()
|
||||
{
|
||||
Vector4 vector4;
|
||||
vector4.X = ReadSingle();
|
||||
vector4.Y = ReadSingle();
|
||||
vector4.Z = ReadSingle();
|
||||
vector4.W = ReadSingle();
|
||||
return vector4;
|
||||
}
|
||||
|
||||
Matrix ContentReader::ReadMatrix()
|
||||
{
|
||||
Matrix matrix;
|
||||
matrix.M11 = ReadSingle();
|
||||
matrix.M12 = ReadSingle();
|
||||
matrix.M13 = ReadSingle();
|
||||
matrix.M14 = ReadSingle();
|
||||
matrix.M21 = ReadSingle();
|
||||
matrix.M22 = ReadSingle();
|
||||
matrix.M23 = ReadSingle();
|
||||
matrix.M24 = ReadSingle();
|
||||
matrix.M31 = ReadSingle();
|
||||
matrix.M32 = ReadSingle();
|
||||
matrix.M33 = ReadSingle();
|
||||
matrix.M34 = ReadSingle();
|
||||
matrix.M41 = ReadSingle();
|
||||
matrix.M42 = ReadSingle();
|
||||
matrix.M43 = ReadSingle();
|
||||
matrix.M44 = ReadSingle();
|
||||
return matrix;
|
||||
}
|
||||
|
||||
Quaternion ContentReader::ReadQuaternion()
|
||||
{
|
||||
Quaternion quaternion;
|
||||
quaternion.X = ReadSingle();
|
||||
quaternion.Y = ReadSingle();
|
||||
quaternion.Z = ReadSingle();
|
||||
quaternion.W = ReadSingle();
|
||||
return quaternion;
|
||||
}
|
||||
|
||||
Color ContentReader::ReadColor()
|
||||
{
|
||||
const auto packedValue = ReadUInt32();
|
||||
return Color(packedValue);
|
||||
}
|
||||
|
||||
float ContentReader::ReadSingle()
|
||||
{
|
||||
const auto int32 = ReadUInt32();
|
||||
return *(float*)&int32;
|
||||
}
|
||||
|
||||
double ContentReader::ReadDouble()
|
||||
{
|
||||
const auto int64 = ReadUInt64();
|
||||
return *(double*)&int64;
|
||||
}
|
||||
|
||||
std::vector<Byte> ContentReader::ReadByteBuffer(size_t size, xna_error_ptr_arg)
|
||||
{
|
||||
std::vector<Byte>& buffer = _contentManager->byteBuffer;
|
||||
|
||||
if (buffer.empty() || buffer.size() < size)
|
||||
{
|
||||
buffer = std::vector<Byte>(size);
|
||||
//_contentManager->byteBuffer = buffer;
|
||||
}
|
||||
|
||||
Int num = 0;
|
||||
for (size_t index = 0; index < size; index += num)
|
||||
{
|
||||
num = Read(buffer, index, size - index);
|
||||
if (num == 0) {
|
||||
xna_error_apply(err, XnaErrorCode::FAILED_OPERATION);
|
||||
return std::vector<Byte>();
|
||||
}
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
sptr<Stream> ContentReader::PrepareStream(sptr<Stream>& input, String const& assetName, Int& graphicsProfile)
|
||||
{
|
||||
BinaryReader binaryReader = BinaryReader(input);
|
||||
|
||||
if (binaryReader.ReadByte() != 'X' || binaryReader.ReadByte() != 'N' || binaryReader.ReadByte() != 'B')
|
||||
return nullptr;
|
||||
|
||||
Int num1 = 0;
|
||||
auto _byte = binaryReader.ReadByte(); //desfazer
|
||||
if (_byte == 'w')
|
||||
num1 = binaryReader.ReadUInt16();
|
||||
else
|
||||
return nullptr;
|
||||
|
||||
graphicsProfile = (num1 & XnbVersionProfileMask) >> XnbVersionProfileShift;
|
||||
bool flag = false;
|
||||
|
||||
switch (num1 & -32513)
|
||||
{
|
||||
case XnbVersion:
|
||||
flag = false;
|
||||
break;
|
||||
case XnbCompressedVersion:
|
||||
flag = true;
|
||||
break;
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const auto num2 = binaryReader.ReadInt32();
|
||||
|
||||
if ((num2 - 10) > input->Length() - input->Position())
|
||||
return nullptr;
|
||||
|
||||
if (!flag)
|
||||
return input;
|
||||
|
||||
const Int compressedTodo = num2 - 14;
|
||||
const auto decompressedTodo = binaryReader.ReadInt32();
|
||||
|
||||
auto lzxStream = New<LzxDecoderStream>(input, compressedTodo, decompressedTodo);
|
||||
|
||||
return reinterpret_pointer_cast<Stream>(lzxStream);
|
||||
}
|
||||
|
||||
Int ContentReader::ReadHeader() {
|
||||
auto _this = shared_from_this();
|
||||
typeReaders = ContentTypeReaderManager::ReadTypeManifest(this->Read7BitEncodedInt(), _this);
|
||||
auto length = this->Read7BitEncodedInt();
|
||||
|
||||
if (length > 0)
|
||||
{
|
||||
//TODO: length > 0
|
||||
}
|
||||
|
||||
return length;
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -1,16 +1,153 @@
|
||||
#ifndef XNA_CONTENT_READER_HPP
|
||||
#define XNA_CONTENT_READER_HPP
|
||||
|
||||
#include "../common/color.hpp"
|
||||
#include "../common/matrix.hpp"
|
||||
#include "../common/quaternion.hpp"
|
||||
#include "../common/vectors.hpp"
|
||||
#include "../csharp/binary.hpp"
|
||||
#include "../csharp/type.hpp"
|
||||
#include "../default.hpp"
|
||||
#include "typereadermanager.hpp"
|
||||
#include <any>
|
||||
|
||||
namespace xna {
|
||||
class ContentReader {
|
||||
class ContentReader : public BinaryReader, public std::enable_shared_from_this<ContentReader> {
|
||||
public:
|
||||
static sptr<ContentReader> Create(ContentManager* contentManager, Stream& input, String const& assetName);
|
||||
static sptr<ContentReader> Create(ContentManager* contentManager, sptr<Stream>& input, String const& assetName);
|
||||
|
||||
template <typename T>
|
||||
T ReadAsset();
|
||||
|
||||
template <typename T>
|
||||
T ReadObject();
|
||||
|
||||
template <typename T>
|
||||
T ReadObject(T existingInstance);
|
||||
|
||||
template <typename T>
|
||||
T ReadObject(ContentTypeReader& typeReader);
|
||||
|
||||
template <typename T>
|
||||
T ReadObject(ContentTypeReader& typeReader, T existingInstance);
|
||||
|
||||
Vector2 ReadVector2();
|
||||
Vector3 ReadVector3();
|
||||
Vector4 ReadVector4();
|
||||
Matrix ReadMatrix();
|
||||
Quaternion ReadQuaternion();
|
||||
Color ReadColor();
|
||||
float ReadSingle();
|
||||
double ReadDouble();
|
||||
|
||||
std::vector<Byte> ReadByteBuffer(size_t size, xna_error_nullarg);
|
||||
|
||||
private:
|
||||
//ContentReader(ContentManager* contentManager, Stream& inut)
|
||||
ContentReader(ContentManager* contentManager, sptr<Stream>& input, String const& assetName, Int graphicsProfile)
|
||||
: BinaryReader(input), _contentManager(contentManager), _assetName(assetName) {}
|
||||
|
||||
static sptr<Stream> PrepareStream(sptr<Stream>& input, String const& assetName, Int& graphicsProfile);
|
||||
|
||||
Int ReadHeader();
|
||||
|
||||
template <typename T>
|
||||
T ReadObjectInternal(std::any& existingInstance, xna_error_nullarg);
|
||||
|
||||
template <typename T>
|
||||
T ReadObjectInternal(ContentTypeReader& typeReader, std::any& existingInstance, xna_error_nullarg);
|
||||
|
||||
template <typename T>
|
||||
T InvokeReader(ContentTypeReader& reader, std::any& existingInstance, xna_error_nullarg);
|
||||
|
||||
private:
|
||||
ContentManager* _contentManager = nullptr;
|
||||
String _assetName;
|
||||
std::vector<sptr<ContentTypeReader>> typeReaders;
|
||||
Int graphicsProfile{ 0 };
|
||||
|
||||
static constexpr Ushort XnbVersionProfileMask = 32512;
|
||||
static constexpr Ushort XnbCompressedVersion = 32773;
|
||||
static constexpr Ushort XnbVersion = 5;
|
||||
static constexpr Int XnbVersionProfileShift = 8;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
inline T ContentReader::ReadObjectInternal(std::any& existingInstance, xna_error_ptr_arg)
|
||||
{
|
||||
const auto num = Read7BitEncodedInt();
|
||||
|
||||
if (num == 0) {
|
||||
return T();
|
||||
}
|
||||
|
||||
const auto index = num - 1;
|
||||
|
||||
if (index >= typeReaders.size()) {
|
||||
xna_error_apply(err, XnaErrorCode::ARGUMENT_OUT_OF_RANGE);
|
||||
|
||||
return T();
|
||||
}
|
||||
|
||||
auto reader = typeReaders[index];
|
||||
return InvokeReader<T>(*reader, existingInstance, err);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline T ContentReader::InvokeReader(ContentTypeReader& reader, std::any& existingInstance, xna_error_ptr_arg)
|
||||
{
|
||||
auto contentTypeReader = reinterpret_cast<ContentTypeReaderT<T>*>(&reader);
|
||||
T objB;
|
||||
|
||||
if (contentTypeReader) {
|
||||
auto existingInstance1 = existingInstance.has_value() ? std::any_cast<T>(existingInstance) : T();
|
||||
objB = contentTypeReader->Read(*this, existingInstance1);
|
||||
return objB;
|
||||
}
|
||||
|
||||
return T();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline T ContentReader::ReadAsset()
|
||||
{
|
||||
const auto sharedResourceCount = ReadHeader();
|
||||
auto obj = ReadObject<T>();
|
||||
return obj;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline T ContentReader::ReadObject()
|
||||
{
|
||||
auto a = std::any();
|
||||
return ReadObjectInternal<T>(a);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline T ContentReader::ReadObject(T existingInstance)
|
||||
{
|
||||
return ReadObjectInternal<T>(std::any(existingInstance));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline T ContentReader::ReadObject(ContentTypeReader& typeReader)
|
||||
{
|
||||
auto obj = std::any();
|
||||
return ReadObjectInternal<T>(typeReader, obj);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline T ContentReader::ReadObject(ContentTypeReader& typeReader, T existingInstance)
|
||||
{
|
||||
return ReadObjectInternal<T>(typeReader, std::any(existingInstance));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline T ContentReader::ReadObjectInternal(ContentTypeReader& typeReader, std::any& existingInstance, xna_error_ptr_arg)
|
||||
{
|
||||
return typeReader.TargetIsValueType
|
||||
? InvokeReader<T>(typeReader, existingInstance, err)
|
||||
: ReadObjectInternal<T>(existingInstance, err);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
148
framework/content/typereadermanager.cpp
Normal file
148
framework/content/typereadermanager.cpp
Normal file
@ -0,0 +1,148 @@
|
||||
#include "typereadermanager.hpp"
|
||||
#include "reader.hpp"
|
||||
#include "defaultreaders.hpp"
|
||||
|
||||
namespace xna {
|
||||
std::vector<PContentTypeReader> ContentTypeReaderManager::ReadTypeManifest(Int typeCount, sptr<ContentReader>& contentReader, xna_error_ptr_arg)
|
||||
{
|
||||
initMaps();
|
||||
|
||||
auto contentTypeReaderArray = std::vector<PContentTypeReader>(typeCount);
|
||||
std::vector<PContentTypeReader> newTypeReaders;
|
||||
|
||||
for (size_t index = 0; index < typeCount; ++index)
|
||||
{
|
||||
const auto readerTypeName = contentReader->ReadString();
|
||||
const auto xnaType = readerTypeName.substr(0, readerTypeName.find(","));
|
||||
|
||||
|
||||
auto typeReader = ContentTypeReaderManager::GetTypeReader(xnaType.empty() ? readerTypeName : xnaType, contentReader, newTypeReaders);
|
||||
|
||||
if (contentReader->ReadInt32() != typeReader->TypeVersion()) {
|
||||
xna_error_apply(err, XnaErrorCode::BAD_TYPE);
|
||||
ContentTypeReaderManager::RollbackAddReaders(newTypeReaders);
|
||||
return std::vector<PContentTypeReader>();
|
||||
}
|
||||
|
||||
contentTypeReaderArray[index] = typeReader;
|
||||
|
||||
if (!newTypeReaders.empty()) {
|
||||
auto manager = std::shared_ptr<ContentTypeReaderManager>(new ContentTypeReaderManager(contentReader));
|
||||
|
||||
for (size_t i = 0; i < newTypeReaders.size(); ++i) {
|
||||
auto& contentTypeReader = newTypeReaders[i];
|
||||
contentTypeReader->Initialize(manager);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return contentTypeReaderArray;
|
||||
}
|
||||
|
||||
sptr<ContentTypeReader> ContentTypeReaderManager::GetTypeReader(sptr<Type> const& targetType, sptr<ContentReader>& contentReader, xna_error_ptr_arg)
|
||||
{
|
||||
if (!targetType) {
|
||||
xna_error_apply(err, XnaErrorCode::ARGUMENT_IS_NULL);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
sptr<ContentTypeReader> typeReader = nullptr;
|
||||
|
||||
if (!ContentTypeReaderManager::targetTypeToReader.contains(targetType)) {
|
||||
xna_error_apply(err, XnaErrorCode::ARGUMENT_OUT_OF_RANGE);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return ContentTypeReaderManager::targetTypeToReader[targetType];
|
||||
}
|
||||
|
||||
ContentTypeReaderManager::ContentTypeReaderManager(sptr<ContentReader>& contentReader) {
|
||||
initMaps();
|
||||
}
|
||||
|
||||
sptr<ContentTypeReader> ContentTypeReaderManager::GetTypeReader(String const& readerTypeName, sptr<ContentReader>& contentReader, std::vector<PContentTypeReader>& newTypeReaders, xna_error_ptr_arg)
|
||||
{
|
||||
sptr<ContentTypeReader> reader = nullptr;
|
||||
|
||||
if (ContentTypeReaderManager::nameToReader.contains(readerTypeName)) {
|
||||
return ContentTypeReaderManager::nameToReader[readerTypeName];
|
||||
}
|
||||
else if (!ContentTypeReaderManager::InstantiateTypeReader(readerTypeName, contentReader, reader, err)) {
|
||||
return reader;
|
||||
}
|
||||
|
||||
if (xna_error_haserros(err))
|
||||
return nullptr;
|
||||
|
||||
ContentTypeReaderManager::AddTypeReader(readerTypeName, contentReader, reader, err);
|
||||
|
||||
if (xna_error_haserros(err)) return nullptr;
|
||||
|
||||
newTypeReaders.push_back(reader);
|
||||
|
||||
return reader;
|
||||
}
|
||||
|
||||
bool ContentTypeReaderManager::InstantiateTypeReader(String const& readerTypeName, sptr<ContentReader>& contentReader, sptr<ContentTypeReader>& reader, xna_error_ptr_arg)
|
||||
{
|
||||
sptr<Type> type = nullptr;
|
||||
|
||||
if (Type::NameOfRegisteredTypes.contains(readerTypeName))
|
||||
type = Type::NameOfRegisteredTypes[readerTypeName];
|
||||
|
||||
if (!type) {
|
||||
xna_error_apply(err, XnaErrorCode::INVALID_OPERATION);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ContentTypeReaderManager::readerTypeToReader.contains(type)) {
|
||||
reader = ContentTypeReaderManager::readerTypeToReader[type];
|
||||
ContentTypeReaderManager::nameToReader.insert({ readerTypeName, reader });
|
||||
return false;
|
||||
}
|
||||
|
||||
reader = ContentTypeReaderActivador::CreateInstance(type, err);
|
||||
return true;
|
||||
}
|
||||
|
||||
void ContentTypeReaderManager::AddTypeReader(String const& readerTypeName, sptr<ContentReader>& contentReader, sptr<ContentTypeReader>& reader, xna_error_ptr_arg)
|
||||
{
|
||||
auto targetType = reader->TargetType();
|
||||
|
||||
if (ContentTypeReaderManager::targetTypeToReader.contains(targetType)) {
|
||||
xna_error_apply(err, XnaErrorCode::INVALID_OPERATION);
|
||||
return;
|
||||
}
|
||||
|
||||
ContentTypeReaderManager::targetTypeToReader.insert({ targetType, reader });
|
||||
//ContentTypeReaderManager::readerTypeToReader.insert({ reader->GetType(), reader });
|
||||
ContentTypeReaderManager::readerTypeToReader.insert({ typeof(*reader), reader});
|
||||
ContentTypeReaderManager::nameToReader.insert({ readerTypeName, reader });
|
||||
}
|
||||
|
||||
void ContentTypeReaderManager::RollbackAddReaders(std::vector<sptr<ContentTypeReader>>& newTypeReaders)
|
||||
{
|
||||
if (newTypeReaders.empty())
|
||||
return;
|
||||
|
||||
for (size_t i = 0; i < newTypeReaders.size(); ++i) {
|
||||
auto newTypeReader = newTypeReaders[i];
|
||||
ContentTypeReaderManager::RollbackAddReader(ContentTypeReaderManager::nameToReader, newTypeReader);
|
||||
ContentTypeReaderManager::RollbackAddReader(ContentTypeReaderManager::targetTypeToReader, newTypeReader);
|
||||
ContentTypeReaderManager::RollbackAddReader(ContentTypeReaderManager::readerTypeToReader, newTypeReader);
|
||||
}
|
||||
}
|
||||
|
||||
void ContentTypeReaderManager::initMaps()
|
||||
{
|
||||
if (targetTypeToReader.empty() && readerTypeToReader.empty()) {
|
||||
auto typeReader = New<ObjectReader>();
|
||||
auto contentTypeReader = reinterpret_pointer_cast<ContentTypeReader>(typeReader);
|
||||
|
||||
//targetTypeToReader.insert({ typeReader->TargetType(), contentTypeReader});
|
||||
//readerTypeToReader.insert({ typeReader->GetType(), contentTypeReader});
|
||||
targetTypeToReader.insert({ typeof<Object>(), contentTypeReader});
|
||||
readerTypeToReader.insert({ typeof<ObjectReader>(), contentTypeReader});
|
||||
}
|
||||
}
|
||||
}
|
153
framework/content/typereadermanager.hpp
Normal file
153
framework/content/typereadermanager.hpp
Normal file
@ -0,0 +1,153 @@
|
||||
#ifndef XNA_CONTENT_TYPEREADER_HPP
|
||||
#define XNA_CONTENT_TYPEREADER_HPP
|
||||
|
||||
#include "../csharp/type.hpp"
|
||||
#include "../default.hpp"
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
#include <any>
|
||||
|
||||
namespace xna {
|
||||
//-------------------------------------------------------//
|
||||
// ContentTypeReader //
|
||||
//-------------------------------------------------------//
|
||||
class ContentTypeReader {
|
||||
public:
|
||||
virtual Int TypeVersion() { return 0; }
|
||||
virtual bool CanDeserializeIntoExistingObject() { return false; }
|
||||
virtual void Initialize(sptr<ContentTypeReaderManager> const& manager) {}
|
||||
|
||||
sptr<Type> TargetType() { return _targetType; }
|
||||
virtual std::any Read(ContentReader& input, std::any& existingInstance) = 0;
|
||||
|
||||
protected:
|
||||
ContentTypeReader(sptr<Type> const& targetType) : _targetType(targetType)
|
||||
{}
|
||||
|
||||
public:
|
||||
bool TargetIsValueType{ false };
|
||||
|
||||
private:
|
||||
sptr<Type> _targetType = nullptr;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class ContentTypeReaderT : public ContentTypeReader {
|
||||
protected:
|
||||
ContentTypeReaderT(sptr<Type> const& targetType) : ContentTypeReader(targetType){}
|
||||
|
||||
public:
|
||||
virtual std::any Read(ContentReader& input, std::any& existingInstance) override{
|
||||
return std::any();
|
||||
}
|
||||
|
||||
virtual T Read(ContentReader& input, T& existingInstance) = 0;
|
||||
};
|
||||
|
||||
//-------------------------------------------------------//
|
||||
// ContentTypeReaderActivador //
|
||||
//-------------------------------------------------------//
|
||||
class ContentTypeReaderActivador {
|
||||
public:
|
||||
using Activador = sptr<ContentTypeReader>(*)();
|
||||
|
||||
static sptr<ContentTypeReader> CreateInstance(sptr<Type> const& type, xna_error_nullarg) {
|
||||
if (!type)
|
||||
{
|
||||
xna_error_apply(err, XnaErrorCode::ARGUMENT_IS_NULL);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const auto hash = type->GetHashCode();
|
||||
|
||||
if (!activators.contains(hash))
|
||||
return nullptr;
|
||||
|
||||
auto activador = activators[hash];
|
||||
|
||||
if (!activador) return nullptr;
|
||||
|
||||
return activador();
|
||||
}
|
||||
|
||||
static void SetActivador(sptr<Type> const& type, Activador activador, xna_error_nullarg) {
|
||||
if (!type) {
|
||||
xna_error_apply(err, XnaErrorCode::ARGUMENT_IS_NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
const auto hash = type->GetHashCode();
|
||||
|
||||
if (!activators.contains(hash))
|
||||
activators.insert({ hash, activador });
|
||||
}
|
||||
|
||||
private:
|
||||
inline static auto activators = std::map<size_t, Activador>();
|
||||
|
||||
ContentTypeReaderActivador();
|
||||
ContentTypeReaderActivador(ContentTypeReaderActivador&&);
|
||||
ContentTypeReaderActivador(ContentTypeReaderActivador&);
|
||||
};
|
||||
|
||||
using PContentTypeReader = sptr<ContentTypeReader>;
|
||||
using PType = sptr<Type>;
|
||||
|
||||
//-------------------------------------------------------//
|
||||
// ContentTypeReaderManager //
|
||||
//-------------------------------------------------------//
|
||||
class ContentTypeReaderManager {
|
||||
public:
|
||||
static std::vector<PContentTypeReader> ReadTypeManifest(Int typeCount, sptr<ContentReader>& contentReader, xna_error_nullarg);
|
||||
static sptr<ContentTypeReader> GetTypeReader(sptr<Type> const& targetType, sptr<ContentReader>& contentReader, xna_error_nullarg);
|
||||
|
||||
inline sptr<ContentTypeReader> GetTypeReader(sptr<Type> const& targetType, xna_error_nullarg) {
|
||||
return ContentTypeReaderManager::GetTypeReader(targetType, this->contentReader, err);
|
||||
}
|
||||
|
||||
inline static bool ContainsTypeReader(sptr<Type> const& targetType) {
|
||||
return ContentTypeReaderManager::targetTypeToReader.contains(targetType);
|
||||
}
|
||||
|
||||
private:
|
||||
ContentTypeReaderManager(sptr<ContentReader>& contentReader);
|
||||
static sptr<ContentTypeReader> GetTypeReader(String const& readerTypeName, sptr<ContentReader>& contentReader, std::vector<PContentTypeReader>& newTypeReaders, xna_error_nullarg);
|
||||
static bool InstantiateTypeReader(String const& readerTypeName, sptr<ContentReader>& contentReader, sptr<ContentTypeReader>& reader, xna_error_nullarg);
|
||||
static void AddTypeReader(String const& readerTypeName, sptr<ContentReader>& contentReader, sptr<ContentTypeReader>& reader, xna_error_nullarg);
|
||||
static void RollbackAddReaders(std::vector<sptr<ContentTypeReader>>& newTypeReaders);
|
||||
|
||||
static void RollbackAddReader(std::map<String, PContentTypeReader>& dictionary, sptr<ContentTypeReader>& reader) {
|
||||
std::map<String, sptr<ContentTypeReader>>::iterator it;
|
||||
|
||||
for (it = dictionary.begin(); it != dictionary.end(); it++) {
|
||||
if (it->second == reader) {
|
||||
dictionary.erase(it->first);
|
||||
it = dictionary.begin();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void RollbackAddReader(std::map<PType, PContentTypeReader>& dictionary, sptr<ContentTypeReader>& reader) {
|
||||
std::map<PType, sptr<ContentTypeReader>>::iterator it;
|
||||
|
||||
for (it = dictionary.begin(); it != dictionary.end(); it++) {
|
||||
if (it->second == reader) {
|
||||
dictionary.erase(it->first);
|
||||
it = dictionary.begin();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
sptr<ContentReader> contentReader = nullptr;
|
||||
|
||||
inline static auto nameToReader = std::map<String, PContentTypeReader>();
|
||||
inline static auto targetTypeToReader = std::map<PType, PContentTypeReader>();
|
||||
inline static auto readerTypeToReader = std::map<PType, PContentTypeReader>();
|
||||
|
||||
static void initMaps();
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
@ -1,4 +1,5 @@
|
||||
#include "binary.hpp"
|
||||
#include "../csharp/buffer.hpp"
|
||||
|
||||
namespace xna {
|
||||
Int BinaryReader::PeekChar(xna_error_ptr_arg)
|
||||
@ -6,7 +7,7 @@ namespace xna {
|
||||
if (!stream) {
|
||||
xna_error_apply(err, XnaErrorCode::INVALID_OPERATION);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
const auto position = stream->Position();
|
||||
const auto num = Read(err);
|
||||
@ -260,14 +261,14 @@ namespace xna {
|
||||
|
||||
} while (num < val1);
|
||||
|
||||
return empty;
|
||||
return sb;
|
||||
}
|
||||
|
||||
Int BinaryReader::InternalReadOneChar(xna_error_ptr_arg)
|
||||
{
|
||||
Int num1 = 0;
|
||||
Long num2 = 0;
|
||||
Long num3 = stream->Position();
|
||||
Long num3 = stream->Position();
|
||||
|
||||
if (charBytes.empty())
|
||||
charBytes.resize(128);
|
||||
@ -352,7 +353,7 @@ namespace xna {
|
||||
}
|
||||
}
|
||||
|
||||
Int BinaryReader::InternalReadChars(char* buffer, size_t bufferSize, Int index, Int count, xna_error_ptr_arg)
|
||||
Int BinaryReader::InternalReadChars(Char* buffer, size_t bufferSize, size_t index, size_t count, xna_error_ptr_arg)
|
||||
{
|
||||
auto charCount = count;
|
||||
|
||||
@ -371,18 +372,18 @@ namespace xna {
|
||||
if (count1 > 128)
|
||||
count1 = 128;
|
||||
|
||||
Int num = 0;
|
||||
Int position = 0;
|
||||
Int byteCount;
|
||||
|
||||
std::vector<Byte> numArray;
|
||||
|
||||
byteCount = stream->Read(charBytes, 0, count1);
|
||||
byteCount = stream->Read(charBytes, 0, static_cast<Int>(count1), err);
|
||||
numArray = charBytes;
|
||||
|
||||
if (byteCount == 0)
|
||||
return count - charCount;
|
||||
return static_cast<Int>(count - charCount);
|
||||
|
||||
if (num < 0 || byteCount < 0 || (num + byteCount) > numArray.size()) {
|
||||
if (position < 0 || byteCount < 0 || (position + byteCount) > numArray.size()) {
|
||||
xna_error_apply(err, XnaErrorCode::ARGUMENT_OUT_OF_RANGE);
|
||||
return -1;
|
||||
}
|
||||
@ -393,22 +394,28 @@ namespace xna {
|
||||
}
|
||||
|
||||
auto data = reinterpret_cast<char*>(charBytes.data());
|
||||
const auto result = std::string((data + num), (data + num) + byteCount);
|
||||
auto pChars = reinterpret_cast<char*>(buffer);
|
||||
|
||||
//const auto result = std::string((data + position), (pChars + index) + byteCount);
|
||||
const auto result = std::string((data + position), (data + position) + byteCount);
|
||||
Buffer::BlockCopy(result.c_str(), position, pChars, index, byteCount);
|
||||
|
||||
const auto chars = result.size();
|
||||
buffer = reinterpret_cast<Char*>(pChars);
|
||||
|
||||
charCount -= static_cast<Int>(chars);
|
||||
index += static_cast<Int>(chars);
|
||||
const auto chars = static_cast<Int>(result.size());
|
||||
|
||||
charCount -= chars;
|
||||
index += chars;
|
||||
}
|
||||
|
||||
return count - charCount;
|
||||
return static_cast<Int>(count - charCount);
|
||||
}
|
||||
|
||||
Long BinaryWriter::Seek(Int offset, SeekOrigin origin, xna_error_ptr_arg)
|
||||
{
|
||||
if (!_stream) {
|
||||
xna_error_apply(err, XnaErrorCode::INVALID_OPERATION);
|
||||
return - 1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return _stream->Seek(offset, origin);
|
||||
@ -648,4 +655,60 @@ namespace xna {
|
||||
_buffer[7] = static_cast<Byte>(value >> 56);
|
||||
_stream->Write(_buffer, 0, 8);
|
||||
}
|
||||
|
||||
Int BinaryReader::Read7BitEncodedInt(xna_error_ptr_arg)
|
||||
{
|
||||
Int num1 = 0;
|
||||
Int num2 = 0;
|
||||
|
||||
while (num2 != 35) {
|
||||
auto num3 = ReadByte(err);
|
||||
|
||||
if (xna_error_haserros(err))
|
||||
return -1;
|
||||
|
||||
num1 |= (static_cast<Int>(num3) & static_cast<Int>(SbyteMaxValue)) << num2;
|
||||
num2 += 7;
|
||||
|
||||
if ((static_cast<Int>(num3) & 128) == 0)
|
||||
return num1;
|
||||
}
|
||||
|
||||
xna_error_apply(err, XnaErrorCode::INVALID_OPERATION);
|
||||
return -1;
|
||||
}
|
||||
|
||||
Int BinaryReader::Read(std::vector<Char>& buffer, size_t index, size_t count, xna_error_ptr_arg)
|
||||
{
|
||||
return InternalReadChars(buffer.data(), buffer.size(), index, count, err);
|
||||
}
|
||||
|
||||
Int BinaryReader::Read(std::vector<Byte>& buffer, size_t index, size_t count, xna_error_ptr_arg)
|
||||
{
|
||||
auto data = reinterpret_cast<Char*>(buffer.data());
|
||||
return InternalReadChars(data, buffer.size(), index, count, err);
|
||||
}
|
||||
std::vector<Byte> BinaryReader::ReadBytes(size_t count, xna_error_ptr_arg)
|
||||
{
|
||||
std::vector<Byte> result(count);
|
||||
Int numRead = 0;
|
||||
|
||||
do {
|
||||
const auto n = stream->Read(result, static_cast<Int>(numRead), static_cast<Int>(count), err);
|
||||
|
||||
if (n == 0)
|
||||
break;
|
||||
|
||||
numRead += n;
|
||||
count -= n;
|
||||
} while (count > 0);
|
||||
|
||||
if (numRead != result.size()) {
|
||||
std::vector<Byte> copy(numRead);
|
||||
Buffer::BlockCopy(result.data(), 0, copy.data(), 0, numRead);
|
||||
result = copy;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
@ -7,7 +7,7 @@
|
||||
namespace xna {
|
||||
class BinaryReader {
|
||||
public:
|
||||
BinaryReader(Stream* const& input) {
|
||||
BinaryReader(sptr<Stream> const& input) {
|
||||
stream = input;
|
||||
buffer = std::vector<Byte>(bufferLength);
|
||||
}
|
||||
@ -28,18 +28,15 @@ namespace xna {
|
||||
double ReadDouble(xna_error_nullarg);
|
||||
std::string ReadString(xna_error_nullarg);
|
||||
|
||||
Int Read(std::vector<Char>& buffer, size_t index, size_t count, xna_error_nullarg) {
|
||||
return -1;
|
||||
}
|
||||
Int Read(std::vector<Char>& buffer, size_t index, size_t count, xna_error_nullarg);
|
||||
Int Read(std::vector<Byte>& buffer, size_t index, size_t count, xna_error_nullarg);
|
||||
|
||||
std::vector<Byte> ReadBytes(size_t count, xna_error_nullarg) {
|
||||
return std::vector<Byte>();
|
||||
}
|
||||
std::vector<Byte> ReadBytes(size_t count, xna_error_nullarg);
|
||||
|
||||
private:
|
||||
static constexpr int maxCharBytesSize = 128;
|
||||
static constexpr int bufferLength = 16;
|
||||
Stream* stream = nullptr;
|
||||
sptr<Stream> stream = nullptr;
|
||||
std::vector<Byte> charBytes;
|
||||
std::vector<Char> singleChar;
|
||||
std::vector<Byte> buffer;
|
||||
@ -47,38 +44,19 @@ namespace xna {
|
||||
|
||||
bool m2BytesPerChar{ false };
|
||||
|
||||
protected:
|
||||
Int InternalReadOneChar(xna_error_nullarg);
|
||||
|
||||
void FillBuffer(Int numBytes, xna_error_nullarg);
|
||||
|
||||
Int Read7BitEncodedInt(xna_error_nullarg)
|
||||
{
|
||||
Int num1 = 0;
|
||||
Int num2 = 0;
|
||||
Int Read7BitEncodedInt(xna_error_nullarg);
|
||||
|
||||
while (num2 != 35) {
|
||||
auto num3 = ReadByte(err);
|
||||
|
||||
if (xna_error_haserros(err))
|
||||
return -1;
|
||||
|
||||
num1 |= (static_cast<Int>(num3) & static_cast<Int>(SbyteMaxValue)) << num2;
|
||||
num2 += 7;
|
||||
|
||||
if ((static_cast<Int>(num3) & 128) == 0)
|
||||
return num1;
|
||||
}
|
||||
|
||||
xna_error_apply(err, XnaErrorCode::INVALID_OPERATION);
|
||||
return -1;
|
||||
}
|
||||
|
||||
Int InternalReadChars(char* buffer, size_t bufferSize, Int index, Int count, xna_error_nullarg);
|
||||
Int InternalReadChars(Char* buffer, size_t bufferSize, size_t index, size_t count, xna_error_nullarg);
|
||||
};
|
||||
|
||||
class BinaryWriter {
|
||||
public:
|
||||
BinaryWriter(Stream* stream) : _stream(stream), _buffer(16) {
|
||||
BinaryWriter(sptr<Stream> const& stream) : _stream(stream), _buffer(16) {
|
||||
}
|
||||
|
||||
Long Seek(Int offset, SeekOrigin origin, xna_error_nullarg);
|
||||
@ -103,7 +81,7 @@ namespace xna {
|
||||
void Write(const char* _string, size_t stringLength, xna_error_nullarg);
|
||||
|
||||
public:
|
||||
Stream* _stream;
|
||||
sptr<Stream> _stream = nullptr;
|
||||
|
||||
private:
|
||||
std::vector<Byte> _buffer;
|
||||
|
@ -8,14 +8,14 @@ namespace xna {
|
||||
class Buffer {
|
||||
public:
|
||||
template <typename T>
|
||||
static void BlockCopy(
|
||||
T const* src,
|
||||
rsize_t srcOffset,
|
||||
T* dst,
|
||||
rsize_t dstOffset,
|
||||
rsize_t byteCount) {
|
||||
static void BlockCopy(T const* src, rsize_t srcOffset, T* dst, rsize_t dstOffset, rsize_t byteCount) {
|
||||
memmove_s(dst + dstOffset, byteCount, src + srcOffset, byteCount);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename TSOURCE, typename TDEST>
|
||||
static void BlockCopy(TSOURCE const* src, rsize_t srcOffset, TDEST* dst, rsize_t dstOffset, rsize_t byteCount) {
|
||||
memmove_s(dst + dstOffset, byteCount, src + srcOffset, byteCount);
|
||||
}
|
||||
|
||||
private:
|
||||
constexpr Buffer() = default;
|
||||
|
12
framework/csharp/object.cpp
Normal file
12
framework/csharp/object.cpp
Normal file
@ -0,0 +1,12 @@
|
||||
#include "object.hpp"
|
||||
#include "type.hpp"
|
||||
|
||||
namespace xna {
|
||||
size_t Object::GetHashCode() const
|
||||
{
|
||||
size_t seed = 0;
|
||||
XnaHHashCombine(seed, this);
|
||||
|
||||
return seed;
|
||||
}
|
||||
}
|
13
framework/csharp/object.hpp
Normal file
13
framework/csharp/object.hpp
Normal file
@ -0,0 +1,13 @@
|
||||
#ifndef XNA_CSHARP_OBJECT_HPP
|
||||
#define XNA_CSHARP_OBJECT_HPP
|
||||
|
||||
#include "../default.hpp"
|
||||
|
||||
namespace xna {
|
||||
class Object {
|
||||
public:
|
||||
virtual size_t GetHashCode() const;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
15
framework/csharp/service.hpp
Normal file
15
framework/csharp/service.hpp
Normal file
@ -0,0 +1,15 @@
|
||||
#ifndef XNA_CSHARP_SERVICE_HPP
|
||||
#define XNA_CSHARP_SERVICE_HPP
|
||||
|
||||
#include "../default.hpp"
|
||||
#include "type.hpp"
|
||||
#include <any>
|
||||
|
||||
namespace xna {
|
||||
class IServiceProvider {
|
||||
public:
|
||||
virtual std::any GetService(Type& serviceType) = 0;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
@ -165,7 +165,7 @@ namespace xna {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (_closed)
|
||||
if (_closed || _truncated)
|
||||
return 0;
|
||||
|
||||
auto _buff = reinterpret_cast<char*>(buffer);
|
||||
@ -184,7 +184,7 @@ namespace xna {
|
||||
}
|
||||
|
||||
Int FileStream::ReadByte(xna_error_ptr_arg){
|
||||
if (_closed)
|
||||
if (_closed || _truncated)
|
||||
return 0;
|
||||
|
||||
char c = 0;
|
||||
|
@ -10,9 +10,11 @@
|
||||
namespace xna {
|
||||
class Stream {
|
||||
public:
|
||||
virtual ~Stream(){}
|
||||
virtual Int Length() = 0;
|
||||
virtual Long Position() = 0;
|
||||
virtual void Close() = 0;
|
||||
virtual bool IsClosed() = 0;
|
||||
virtual Long Seek(Long offset, SeekOrigin const& origin, xna_error_nullarg) = 0;
|
||||
virtual Int Read(Byte* buffer, Int bufferLength, Int offset, Int count, xna_error_nullarg) = 0;
|
||||
virtual Int Read(std::vector<Byte>& buffer, Int offset, Int count, xna_error_nullarg) = 0;
|
||||
@ -47,13 +49,17 @@ namespace xna {
|
||||
_buffer = std::vector<Byte>();
|
||||
}
|
||||
|
||||
virtual Long Seek(Long offset, SeekOrigin const& origin, xna_error_ptr_arg) override;
|
||||
virtual Int Read(Byte* buffer, Int bufferLength, Int offset, Int count, xna_error_ptr_arg) override;
|
||||
virtual Int Read(std::vector<Byte>& buffer, Int offset, Int count, xna_error_ptr_arg) override;
|
||||
virtual Int ReadByte(xna_error_ptr_arg) override;
|
||||
virtual void Write(Byte const* buffer, Int bufferLength, Int offset, Int count, xna_error_ptr_arg) override;
|
||||
virtual void Write(std::vector<Byte> const& buffer, Int offset, Int count, xna_error_ptr_arg) override;
|
||||
virtual void WriteByte(Byte value, xna_error_ptr_arg) override;
|
||||
virtual constexpr bool IsClosed() override {
|
||||
return _closed;
|
||||
}
|
||||
|
||||
virtual Long Seek(Long offset, SeekOrigin const& origin, xna_error_nullarg) override;
|
||||
virtual Int Read(Byte* buffer, Int bufferLength, Int offset, Int count, xna_error_nullarg) override;
|
||||
virtual Int Read(std::vector<Byte>& buffer, Int offset, Int count, xna_error_nullarg) override;
|
||||
virtual Int ReadByte(xna_error_nullarg) override;
|
||||
virtual void Write(Byte const* buffer, Int bufferLength, Int offset, Int count, xna_error_nullarg) override;
|
||||
virtual void Write(std::vector<Byte> const& buffer, Int offset, Int count, xna_error_nullarg) override;
|
||||
virtual void WriteByte(Byte value, xna_error_nullarg) override;
|
||||
|
||||
public:
|
||||
Int _position{ 0 };
|
||||
@ -65,7 +71,63 @@ namespace xna {
|
||||
|
||||
class FileStream : public Stream {
|
||||
public:
|
||||
FileStream(std::string const& path){
|
||||
FileStream(String const& path, FileMode fileMode) {
|
||||
int flags = std::fstream::in
|
||||
| std::fstream::out
|
||||
| std::fstream::binary;
|
||||
|
||||
const auto exists = std::filesystem::exists(path);
|
||||
|
||||
switch (fileMode)
|
||||
{
|
||||
//Especifica se deve abrir um arquivo existente.
|
||||
case FileMode::Open:
|
||||
if (!exists) {
|
||||
_closed = true;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
//Especifica que se deve abrir um arquivo, se existir;
|
||||
// caso contrário, um novo arquivo deverá ser criado.
|
||||
case FileMode::OpenOrCreate:
|
||||
case FileMode::Create:
|
||||
if (!exists)
|
||||
flags |= std::fstream::trunc;
|
||||
break;
|
||||
//Especifica que o sistema operacional deve criar um novo arquivo.
|
||||
//Se o arquivo já existir, não abre o arquivo.
|
||||
case FileMode::CreateNew:
|
||||
if (!exists)
|
||||
flags |= std::fstream::trunc;
|
||||
else
|
||||
return;
|
||||
break;
|
||||
//Abre o arquivo, se existir, e busca o final do arquivo ou cria um novo arquivo.
|
||||
case FileMode::Append:
|
||||
if (!exists)
|
||||
flags |= std::fstream::trunc;
|
||||
else
|
||||
flags |= std::fstream::app;
|
||||
break;
|
||||
//Especifica que se deve abrir um arquivo existente.
|
||||
//Quando o arquivo for aberto, ele deverá ser truncado
|
||||
//para que seu tamanho seja zero bytes.
|
||||
//Tentativa de ler um arquivo truncado retornará 0;
|
||||
case FileMode::Truncate:
|
||||
flags |= std::fstream::trunc;
|
||||
_truncated = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
_fstream.open(path.c_str(), flags);
|
||||
|
||||
if (!_fstream.good())
|
||||
_closed = true;
|
||||
}
|
||||
|
||||
FileStream(String const& path){
|
||||
int flags = std::fstream::in
|
||||
| std::fstream::out
|
||||
| std::fstream::binary;
|
||||
@ -78,7 +140,7 @@ namespace xna {
|
||||
|
||||
_fstream.open(path.c_str(), flags);
|
||||
|
||||
if (!_fstream.is_open())
|
||||
if (!_fstream.good())
|
||||
_closed = true;
|
||||
}
|
||||
|
||||
@ -108,18 +170,25 @@ namespace xna {
|
||||
_fstream.close();
|
||||
}
|
||||
|
||||
virtual Long Seek(Long offset, SeekOrigin const& origin, xna_error_ptr_arg) override;
|
||||
virtual Int Read(Byte* buffer, Int bufferLength, Int offset, Int count, xna_error_ptr_arg) override;
|
||||
virtual Int Read(std::vector<Byte>& buffer, Int offset, Int count, xna_error_ptr_arg) override;
|
||||
virtual Int ReadByte(xna_error_ptr_arg) override;
|
||||
virtual void Write(Byte const* buffer, Int bufferLength, Int offset, Int count, xna_error_ptr_arg) override;
|
||||
virtual void Write(std::vector<Byte> const& buffer, Int offset, Int count, xna_error_ptr_arg) override;
|
||||
virtual void WriteByte(Byte value, xna_error_ptr_arg) override;
|
||||
virtual constexpr bool IsClosed() override {
|
||||
return _closed;
|
||||
}
|
||||
|
||||
virtual Long Seek(Long offset, SeekOrigin const& origin, xna_error_nullarg) override;
|
||||
virtual Int Read(Byte* buffer, Int bufferLength, Int offset, Int count, xna_error_nullarg) override;
|
||||
virtual Int Read(std::vector<Byte>& buffer, Int offset, Int count, xna_error_nullarg) override;
|
||||
virtual Int ReadByte(xna_error_nullarg) override;
|
||||
virtual void Write(Byte const* buffer, Int bufferLength, Int offset, Int count, xna_error_nullarg) override;
|
||||
virtual void Write(std::vector<Byte> const& buffer, Int offset, Int count, xna_error_nullarg) override;
|
||||
virtual void WriteByte(Byte value, xna_error_nullarg) override;
|
||||
|
||||
public:
|
||||
std::streampos _filesize{ 0 };
|
||||
std::fstream _fstream;
|
||||
|
||||
private:
|
||||
std::streampos _filesize{ 0 };
|
||||
bool _closed{ false };
|
||||
bool _truncated{ false };
|
||||
|
||||
Int endOfFile() {
|
||||
if (_closed)
|
||||
|
15
framework/csharp/type.cpp
Normal file
15
framework/csharp/type.cpp
Normal file
@ -0,0 +1,15 @@
|
||||
#include "type.hpp"
|
||||
|
||||
namespace xna {
|
||||
size_t Type::GetHashCode() const
|
||||
{
|
||||
size_t seed = 0;
|
||||
XnaHHashCombine(seed, fullName);
|
||||
XnaHHashCombine(seed, isClass);
|
||||
XnaHHashCombine(seed, isEnum);
|
||||
XnaHHashCombine(seed, isValueType);
|
||||
XnaHHashCombine(seed, isPrimitive);
|
||||
|
||||
return seed;
|
||||
}
|
||||
}
|
88
framework/csharp/type.hpp
Normal file
88
framework/csharp/type.hpp
Normal file
@ -0,0 +1,88 @@
|
||||
#ifndef XNA_CSHARP_TYPE_HPP
|
||||
#define XNA_CSHARP_TYPE_HPP
|
||||
|
||||
#include "../default.hpp"
|
||||
#include "object.hpp"
|
||||
#include <type_traits>
|
||||
#include <typeinfo>
|
||||
#include <map>
|
||||
|
||||
namespace xna {
|
||||
class Type : public Object {
|
||||
public:
|
||||
constexpr String FullName() const { return fullName; }
|
||||
constexpr bool IsClass() const { return isClass; }
|
||||
constexpr bool IsEnum() const { return isEnum; }
|
||||
constexpr bool IsValueType() const { return isValueType; }
|
||||
constexpr bool IsPrimitive() const { return isPrimitive; }
|
||||
|
||||
virtual size_t GetHashCode() const;
|
||||
|
||||
constexpr bool operator==(const Type& other) const {
|
||||
return
|
||||
fullName == other.fullName
|
||||
&& isClass == other.isClass
|
||||
&& isEnum == other.isEnum
|
||||
&& isValueType == other.isValueType
|
||||
&& isPrimitive == other.isPrimitive;
|
||||
}
|
||||
|
||||
bool operator()(Type const& t1, Type const& t2) const {
|
||||
return t1.GetHashCode() < t2.GetHashCode();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
friend sptr<Type> typeof();
|
||||
|
||||
public:
|
||||
inline static auto NameOfRegisteredTypes = std::map<std::string, sptr<Type>>();
|
||||
|
||||
private:
|
||||
String fullName;
|
||||
bool isClass{ false };
|
||||
bool isEnum{ false };
|
||||
bool isValueType{ false };
|
||||
bool isPrimitive{ false };
|
||||
};
|
||||
|
||||
template <class T>
|
||||
inline sptr<Type> typeof() {
|
||||
if (std::is_arithmetic<T>::value) {
|
||||
auto primitiveType = New<Type>();
|
||||
primitiveType->fullName = typeid(T).name();
|
||||
primitiveType->isPrimitive = true;
|
||||
primitiveType->isValueType = true;
|
||||
return primitiveType;
|
||||
}
|
||||
|
||||
if (std::is_enum<T>::value) {
|
||||
auto enumType = New<Type>();
|
||||
enumType->fullName = typeid(T).name();
|
||||
enumType->isValueType = true;
|
||||
enumType->isEnum = true;
|
||||
return enumType;
|
||||
}
|
||||
|
||||
if (std::is_class<T>::value) {
|
||||
auto classType = New<Type>();
|
||||
classType->fullName = typeid(T).name();
|
||||
classType->isClass = true;
|
||||
|
||||
return classType;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline sptr<Type> typeof(T const* object) {
|
||||
return typeof<T>();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline sptr<Type> typeof(T const& object) {
|
||||
return typeof<T>();
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@ -165,6 +165,15 @@ namespace xna {
|
||||
Stretched = 2
|
||||
};
|
||||
|
||||
enum class FileMode {
|
||||
CreateNew,
|
||||
Create,
|
||||
Append,
|
||||
Open,
|
||||
OpenOrCreate,
|
||||
Truncate
|
||||
};
|
||||
|
||||
enum class FillMode
|
||||
{
|
||||
WireFrame,
|
||||
|
@ -15,10 +15,14 @@ namespace xna {
|
||||
class Stream;
|
||||
class FileStream;
|
||||
class MemoryStream;
|
||||
class Object;
|
||||
class Type;
|
||||
|
||||
//Content
|
||||
class ContentManager;
|
||||
class ContentReader;
|
||||
class ContentTypeReader;
|
||||
class ContentTypeReaderManager;
|
||||
|
||||
//Framework
|
||||
class BoundingBox;
|
||||
@ -49,6 +53,7 @@ namespace xna {
|
||||
class GraphicsDeviceManager;
|
||||
class IGameTime;
|
||||
class IGameComponent;
|
||||
class GameServiceContainer;
|
||||
|
||||
//Graphics
|
||||
class BlendState;
|
||||
@ -83,6 +88,9 @@ namespace xna {
|
||||
struct GamePadState;
|
||||
struct KeyboardState;
|
||||
struct MouseState;
|
||||
|
||||
//Pointer
|
||||
using PTexture2D = std::shared_ptr<Texture2D>;
|
||||
}
|
||||
|
||||
#endif
|
@ -1,23 +1,21 @@
|
||||
#ifndef XNA_GAME_GAME_HPP
|
||||
#define XNA_GAME_GAME_HPP
|
||||
|
||||
#include "../enums.hpp"
|
||||
#include "../forward.hpp"
|
||||
#include "../types.hpp"
|
||||
#include "../default.hpp"
|
||||
#include "time.hpp"
|
||||
#include "window.hpp"
|
||||
#include "../game/component.hpp"
|
||||
#include "component.hpp"
|
||||
#include "servicecontainer.hpp"
|
||||
|
||||
namespace xna {
|
||||
class IGame {
|
||||
public:
|
||||
virtual ~IGame(){}
|
||||
|
||||
virtual void Exit() = 0;
|
||||
virtual int Run() = 0;
|
||||
virtual sptr<GameWindow> Window() = 0;
|
||||
virtual sptr<GraphicsDevice> GetGraphicsDevice() = 0;
|
||||
virtual sptr<GameComponentCollection> Components() = 0;
|
||||
virtual sptr<GameServiceContainer> Services() = 0;
|
||||
virtual sptr<ContentManager> Content() = 0;
|
||||
|
||||
protected:
|
||||
virtual void Draw(GameTime const& gameTime) = 0;
|
||||
|
18
framework/game/servicecontainer.cpp
Normal file
18
framework/game/servicecontainer.cpp
Normal file
@ -0,0 +1,18 @@
|
||||
#include "servicecontainer.hpp"
|
||||
|
||||
namespace xna {
|
||||
void GameServiceContainer::AddService(Type& type, std::any& provider)
|
||||
{
|
||||
auto hashCode = type.GetHashCode();
|
||||
services.insert({ hashCode, provider });
|
||||
}
|
||||
|
||||
std::any GameServiceContainer::GetService(Type& serviceType)
|
||||
{
|
||||
auto hashCode = serviceType.GetHashCode();
|
||||
|
||||
return services.contains(hashCode)
|
||||
? services[hashCode]
|
||||
: std::any();
|
||||
}
|
||||
}
|
@ -2,12 +2,19 @@
|
||||
#define XNA_GAME_SERVICECONTAINER_HPP
|
||||
|
||||
#include "../default.hpp"
|
||||
#include "../csharp/service.hpp"
|
||||
#include <map>
|
||||
|
||||
namespace xna {
|
||||
class IServiceProvider {
|
||||
};
|
||||
class GameServiceContainer : public IServiceProvider {
|
||||
public:
|
||||
void AddService(Type& type, std::any& provider);
|
||||
|
||||
class GameServiceContainer {
|
||||
// Inherited via IServiceProvider
|
||||
std::any GetService(Type& serviceType) override;
|
||||
|
||||
private:
|
||||
std::map<size_t, std::any> services;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -6,11 +6,11 @@
|
||||
namespace xna {
|
||||
class GraphicsResource {
|
||||
public:
|
||||
GraphicsResource(GraphicsDevice* device) : m_device(device){}
|
||||
GraphicsResource(sptr<GraphicsDevice> const& device) : m_device(device){}
|
||||
|
||||
virtual ~GraphicsResource(){}
|
||||
|
||||
virtual bool Bind(GraphicsDevice* device) {
|
||||
virtual bool Bind(sptr<GraphicsDevice> const& device) {
|
||||
if (device == m_device)
|
||||
return false;
|
||||
|
||||
@ -20,7 +20,7 @@ namespace xna {
|
||||
}
|
||||
|
||||
protected:
|
||||
GraphicsDevice* m_device = nullptr;
|
||||
sptr<GraphicsDevice> m_device = nullptr;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
#ifndef XNA_GRAPHICS_RENDERTARGET_HPP
|
||||
#define XNA_GRAPHICS_RENDERTARGET_HPP
|
||||
|
||||
#include "texture.hpp"
|
||||
#include "../default.hpp"
|
||||
|
||||
|
||||
namespace xna {
|
||||
@ -9,8 +9,8 @@ namespace xna {
|
||||
public:
|
||||
virtual ~IRenderTarget2D(){}
|
||||
|
||||
virtual bool Initialize(GraphicsDevice& device) = 0;
|
||||
virtual bool Apply(GraphicsDevice& device) = 0;
|
||||
virtual bool Initialize(xna_error_nullarg) = 0;
|
||||
virtual bool Apply(xna_error_nullarg) = 0;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -1,9 +1,7 @@
|
||||
#ifndef XNA_GRAPHICS_TEXTURE_HPP
|
||||
#define XNA_GRAPHICS_TEXTURE_HPP
|
||||
|
||||
#include "../forward.hpp"
|
||||
#include "../types.hpp"
|
||||
#include "../enums.hpp"
|
||||
#include "../default.hpp"
|
||||
|
||||
namespace xna {
|
||||
class Texture {
|
||||
@ -14,6 +12,8 @@ namespace xna {
|
||||
virtual ~ITexture2D(){}
|
||||
virtual Int Width() const = 0;
|
||||
virtual Int Height() const = 0;
|
||||
virtual Rectangle Bounds() const = 0;
|
||||
virtual bool Initialize(xna_error_nullarg) = 0;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
#define XNA_HELPERS_HPP
|
||||
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
namespace xna {
|
||||
inline std::wstring XnaHToWString(const std::string& str)
|
||||
@ -21,6 +22,12 @@ namespace xna {
|
||||
wcstombs_s(&size, &str[0], str.size() + 1, wstr.c_str(), wstr.size());
|
||||
return str;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static constexpr void XnaHHashCombine(std::size_t& seed, const T& v) {
|
||||
std::hash<T> hasher;
|
||||
seed ^= hasher(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@ -45,7 +45,7 @@ namespace xna {
|
||||
switch (format)
|
||||
{
|
||||
case SurfaceFormat::Color://21
|
||||
return DXGI_FORMAT_B8G8R8A8_UNORM;
|
||||
return DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
case SurfaceFormat::Bgr565: //23
|
||||
return DXGI_FORMAT_B5G6R5_UNORM;
|
||||
case SurfaceFormat::Bgra5551://25
|
||||
@ -92,6 +92,7 @@ namespace xna {
|
||||
static constexpr SurfaceFormat ConvertDXGIFORMATToSurface(DXGI_FORMAT format) {
|
||||
switch (format)
|
||||
{
|
||||
case DXGI_FORMAT_R8G8B8A8_UNORM:
|
||||
case DXGI_FORMAT_B8G8R8A8_UNORM:
|
||||
return SurfaceFormat::Color;
|
||||
case DXGI_FORMAT_B5G6R5_UNORM:
|
||||
|
@ -21,7 +21,7 @@ namespace xna {
|
||||
|
||||
class BlendState : public IBlendState, public GraphicsResource {
|
||||
public:
|
||||
BlendState(GraphicsDevice* device) : GraphicsResource(device) {};
|
||||
BlendState(sptr<GraphicsDevice> const& device) : GraphicsResource(device) {};
|
||||
|
||||
virtual ~BlendState() override {
|
||||
if (dxBlendState) {
|
||||
|
40
framework/platform/content-readers/texture2Dreader-dx.hpp
Normal file
40
framework/platform/content-readers/texture2Dreader-dx.hpp
Normal file
@ -0,0 +1,40 @@
|
||||
#ifndef XNA_PLATFORM_CONTENTREADERS_TEXTURE2D_HPP
|
||||
#define XNA_PLATFORM_CONTENTREADERS_TEXTURE2D_HPP
|
||||
|
||||
#include "../../content/manager.hpp"
|
||||
#include "../../content/reader.hpp"
|
||||
#include "../../csharp/type.hpp"
|
||||
#include "../texture-dx.hpp"
|
||||
|
||||
namespace xna {
|
||||
class Texture2DReader : public ContentTypeReaderT<PTexture2D> {
|
||||
public:
|
||||
Texture2DReader() : ContentTypeReaderT(typeof<Texture2D>()){}
|
||||
|
||||
PTexture2D Read(ContentReader& input, PTexture2D& existingInstance) override{
|
||||
const auto format = static_cast<SurfaceFormat>(input.ReadInt32());
|
||||
const auto width = input.ReadInt32();
|
||||
const auto height = input.ReadInt32();
|
||||
const auto mipMaps = input.ReadInt32();
|
||||
|
||||
auto a_device = ContentManager::Services()->GetService(*typeof<GraphicsDevice>());
|
||||
sptr<GraphicsDevice> device = nullptr;
|
||||
|
||||
if(a_device.has_value())
|
||||
device = std::any_cast<sptr<GraphicsDevice>>(a_device);
|
||||
|
||||
auto texture2D = New<Texture2D>(device, width, height, mipMaps, format);
|
||||
|
||||
for (size_t level = 0; level < mipMaps; ++level) {
|
||||
auto elementCount = input.ReadInt32();
|
||||
std::vector<Byte> data = input.ReadByteBuffer(elementCount);
|
||||
|
||||
texture2D->SetData(static_cast<Int>(level), nullptr, data, 0, elementCount);
|
||||
}
|
||||
|
||||
return texture2D;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
@ -8,7 +8,7 @@
|
||||
namespace xna {
|
||||
class DepthStencilState : public IDepthStencilState, public GraphicsResource {
|
||||
public:
|
||||
DepthStencilState(GraphicsDevice* device) : GraphicsResource(device) {
|
||||
DepthStencilState(sptr<GraphicsDevice> const& device) : GraphicsResource(device) {
|
||||
dxDescription = defaultDesc();
|
||||
}
|
||||
|
||||
|
@ -22,6 +22,8 @@ namespace xna {
|
||||
|
||||
bool GraphicsDevice::Initialize(GameWindow& gameWindow) {
|
||||
reset();
|
||||
|
||||
auto _this = shared_from_this();
|
||||
|
||||
if (!createDevice()) return false;
|
||||
|
||||
@ -41,16 +43,17 @@ namespace xna {
|
||||
_backgroundColor[2] = GetBValue(color) / 255.0f;
|
||||
_backgroundColor[3] = 1.0f;
|
||||
|
||||
_swapChain = New<xna::SwapChain>(this);
|
||||
_swapChain = New<xna::SwapChain>(_this);
|
||||
_swapChain->Initialize();
|
||||
|
||||
hr = _factory->MakeWindowAssociation(gameWindow.WindowHandle(), DXGI_MWA_NO_ALT_ENTER);
|
||||
if (FAILED(hr)) return false;
|
||||
|
||||
_renderTarget2D = New<RenderTarget2D>();
|
||||
if (!_renderTarget2D->Initialize(*this)) return false;
|
||||
_renderTarget2D = New<RenderTarget2D>(_this);
|
||||
if (!_renderTarget2D->Initialize())
|
||||
return false;
|
||||
|
||||
_renderTarget2D->Apply(*this);
|
||||
_renderTarget2D->Apply();
|
||||
|
||||
D3D11_VIEWPORT view{};
|
||||
view.TopLeftX = _viewport.X;
|
||||
@ -63,7 +66,7 @@ namespace xna {
|
||||
_context->RSSetViewports(1, &view);
|
||||
|
||||
_blendState = BlendState::NonPremultiplied();
|
||||
_blendState->Bind(this);
|
||||
_blendState->Bind(_this);
|
||||
_blendState->Apply();
|
||||
|
||||
return true;
|
||||
|
@ -14,7 +14,7 @@
|
||||
#include "presentparameters-dx.hpp"
|
||||
|
||||
namespace xna {
|
||||
class GraphicsDevice : public IGraphicsDevice {
|
||||
class GraphicsDevice : public IGraphicsDevice, public std::enable_shared_from_this<GraphicsDevice> {
|
||||
public:
|
||||
GraphicsDevice();
|
||||
GraphicsDevice(GraphicsDeviceInformation const& info);
|
||||
|
@ -1,9 +1,33 @@
|
||||
//DirectX
|
||||
#include "dxgi.h"
|
||||
#include "d3d11.h"
|
||||
#include <d3d11_1.h>
|
||||
#include <d3d11_2.h>
|
||||
//HSLS
|
||||
#include <d3dcompiler.h>
|
||||
//DirectXTK
|
||||
#include <DirectXMath.h>
|
||||
#include <Audio.h>
|
||||
#include <BufferHelpers.h>
|
||||
#include <CommonStates.h>
|
||||
#include <DDSTextureLoader.h>
|
||||
#include <DirectXHelpers.h>
|
||||
#include <Effects.h>
|
||||
#include <GamePad.h>
|
||||
#include <GeometricPrimitive.h>
|
||||
#include <GraphicsMemory.h>
|
||||
#include <Keyboard.h>
|
||||
#include <Model.h>
|
||||
#include <Mouse.h>
|
||||
#include <PostProcess.h>
|
||||
#include <PrimitiveBatch.h>
|
||||
#include <ScreenGrab.h>
|
||||
#include <SimpleMath.h>
|
||||
#include <SpriteBatch.h>
|
||||
#include <SpriteFont.h>
|
||||
#include <VertexTypes.h>
|
||||
#include <WICTextureLoader.h>
|
||||
//Windows
|
||||
#define NOMINMAX
|
||||
#include <Windows.h>
|
||||
#include <Windows.Foundation.h>
|
||||
|
@ -1,4 +1,4 @@
|
||||
#define NOMINMAX
|
||||
#include "../csharp/type.hpp"
|
||||
#include "../game/time.hpp"
|
||||
#include "audioengine-dx.hpp"
|
||||
#include "device-dx.hpp"
|
||||
@ -8,12 +8,14 @@
|
||||
#include "keyboard-dx.hpp"
|
||||
#include "mouse-dx.hpp"
|
||||
#include "window-dx.hpp"
|
||||
#include <Windows.h>
|
||||
|
||||
namespace xna {
|
||||
Game::Game() {
|
||||
services = New<GameServiceContainer>();
|
||||
_contentManager = New<ContentManager>("", services);
|
||||
|
||||
_gameWindow = New<GameWindow>();
|
||||
_gameWindow->Color(255, 155, 55);
|
||||
_gameWindow->Color(146, 150, 154);
|
||||
_gameWindow->Title("XN65");
|
||||
_gameWindow->Size(
|
||||
GraphicsDeviceManager::DefaultBackBufferWidth,
|
||||
@ -22,15 +24,14 @@ namespace xna {
|
||||
_gameComponents = New<GameComponentCollection>();
|
||||
}
|
||||
|
||||
void Game::Exit()
|
||||
{
|
||||
void Game::Exit() {
|
||||
_gameWindow->Close();
|
||||
}
|
||||
|
||||
int Game::Run() {
|
||||
Initialize();
|
||||
|
||||
if (_graphicsDevice == nullptr) {
|
||||
if (graphicsDevice == nullptr) {
|
||||
MessageBox(nullptr, "O dispositivo gráfico não foi inicializado corretamente", "XN65", MB_OK);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
@ -40,21 +41,21 @@ namespace xna {
|
||||
|
||||
void Game::Initialize() {
|
||||
Keyboard::Initialize();
|
||||
Mouse::Initialize();
|
||||
Mouse::Initialize();
|
||||
|
||||
//initialize é requisito para GamePad
|
||||
#if (_WIN32_WINNT >= 0x0A00 /*_WIN32_WINNT_WIN10*/)
|
||||
Microsoft::WRL::Wrappers::RoInitializeWrapper initialize(RO_INIT_MULTITHREADED);
|
||||
|
||||
if (FAILED(initialize))
|
||||
MessageBox(nullptr, "Ocorreu um erro ao executar Microsoft::WRL::Wrappers::RoInitializeWrapper. O GamePad não foi inicializado corretamente.", "XN65", MB_OK);
|
||||
|
||||
GamePad.Initialize();
|
||||
|
||||
//CoInitializeEx é requisito para AudioEngine
|
||||
const auto hr = CoInitializeEx(nullptr, COINIT_MULTITHREADED);
|
||||
|
||||
{
|
||||
MessageBox(nullptr, "Ocorreu um erro ao chamar Microsoft::WRL::Wrappers::RoInitializeWrapper.", "XN65", MB_OK);
|
||||
}
|
||||
#else
|
||||
HRESULT hr = CoInitializeEx(nullptr, COINIT_MULTITHREADED);
|
||||
if (FAILED(hr))
|
||||
MessageBox(nullptr, "Ocorreu um erro ao executar CoInitializeEx. O AudioEngine não foi inicializado corretamente.", "XN65", MB_OK);
|
||||
{
|
||||
MessageBox(nullptr, "Ocorreu um erro ao chamar CoInitializeEx.", "XN65", MB_OK);
|
||||
}
|
||||
#endif
|
||||
|
||||
_audioEngine = New<AudioEngine>();
|
||||
|
||||
@ -84,7 +85,7 @@ namespace xna {
|
||||
_drawableGameComponents.clear();
|
||||
}
|
||||
|
||||
_graphicsDevice->Present();
|
||||
graphicsDevice->Present();
|
||||
}
|
||||
|
||||
void Game::Update(GameTime const& gameTime) {
|
||||
@ -142,5 +143,5 @@ namespace xna {
|
||||
});
|
||||
|
||||
Draw(_currentGameTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,65 +1,52 @@
|
||||
#ifndef XNA_PLATFORM_GAME_DX_HPP
|
||||
#define XNA_PLATFORM_GAME_DX_HPP
|
||||
|
||||
#include "../content/manager.hpp"
|
||||
#include "../default.hpp"
|
||||
#include "../game/game.hpp"
|
||||
#include "dxheaders.hpp"
|
||||
#include "dx/StepTimer.hpp"
|
||||
#include "dxheaders.hpp"
|
||||
|
||||
namespace xna {
|
||||
class Game : public IGame {
|
||||
public:
|
||||
Game();
|
||||
Game();
|
||||
|
||||
virtual ~Game() override {
|
||||
}
|
||||
|
||||
virtual void Exit() override;
|
||||
|
||||
virtual int Run() override;
|
||||
void Exit() override;
|
||||
int Run() override;
|
||||
|
||||
virtual sptr<GameWindow> Window() override {
|
||||
return _gameWindow;
|
||||
}
|
||||
|
||||
virtual sptr<GraphicsDevice> GetGraphicsDevice() override {
|
||||
return _graphicsDevice;
|
||||
}
|
||||
|
||||
sptr<GameComponentCollection> Components() override {
|
||||
return _gameComponents;
|
||||
}
|
||||
|
||||
constexpr void EnableGameComponents(bool value) {
|
||||
_enabledGameComponents = value;
|
||||
}
|
||||
inline sptr<GameWindow> Window() override { return _gameWindow; }
|
||||
inline sptr<GraphicsDevice> GetGraphicsDevice() override { return graphicsDevice; }
|
||||
inline sptr<GameComponentCollection> Components() override { return _gameComponents; }
|
||||
inline sptr<GameServiceContainer> Services() override { return services; }
|
||||
inline sptr<ContentManager> Content() override { return _contentManager; }
|
||||
constexpr void EnableGameComponents(bool value) { _enabledGameComponents = value; }
|
||||
|
||||
protected:
|
||||
virtual void Draw(GameTime const& gameTime) override;
|
||||
|
||||
virtual void Draw(GameTime const& gameTime) override;
|
||||
virtual void Initialize() override;
|
||||
|
||||
virtual void LoadContent() override{}
|
||||
|
||||
virtual void LoadContent() override{}
|
||||
virtual void Update(GameTime const& gameTime) override;
|
||||
|
||||
public:
|
||||
sptr<GraphicsDevice> _graphicsDevice{ nullptr };
|
||||
sptr<GraphicsDevice> graphicsDevice = nullptr;
|
||||
|
||||
protected:
|
||||
sptr<GameWindow> _gameWindow{ nullptr };
|
||||
sptr<AudioEngine> _audioEngine = nullptr;
|
||||
|
||||
GameTime _currentGameTime{};
|
||||
DX::StepTimer _stepTimer;
|
||||
|
||||
private:
|
||||
int startLoop();
|
||||
void step();
|
||||
protected:
|
||||
sptr<GameServiceContainer> services = nullptr;
|
||||
|
||||
private:
|
||||
sptr<GameComponentCollection> _gameComponents = nullptr;
|
||||
sptr<GameWindow> _gameWindow{ nullptr };
|
||||
sptr<AudioEngine> _audioEngine = nullptr;
|
||||
sptr<ContentManager> _contentManager;
|
||||
std::vector<sptr<IGameComponent>> _drawableGameComponents;
|
||||
size_t _drawableGameComponentsCount{ 0 };
|
||||
bool _enabledGameComponents{ false };
|
||||
bool _enabledGameComponents{ false };
|
||||
GameTime _currentGameTime{};
|
||||
DX::StepTimer _stepTimer{};
|
||||
|
||||
int startLoop();
|
||||
void step();
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -33,10 +33,10 @@ namespace xna {
|
||||
}
|
||||
|
||||
bool GraphicsDeviceManager::ToggleFullScreen() {
|
||||
if (!_game || !_game->_graphicsDevice || !_game->_graphicsDevice->_swapChain)
|
||||
if (!_game || !_game->graphicsDevice || !_game->graphicsDevice->_swapChain)
|
||||
return false;
|
||||
|
||||
auto& swap = _game->_graphicsDevice->_swapChain;
|
||||
auto& swap = _game->graphicsDevice->_swapChain;
|
||||
|
||||
BOOL state = false;
|
||||
auto hr = swap->dxSwapChain->GetFullscreenState(&state, nullptr);
|
||||
@ -110,7 +110,7 @@ namespace xna {
|
||||
return false;
|
||||
}
|
||||
|
||||
_game->_graphicsDevice = _device;
|
||||
_game->graphicsDevice = _device;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
64
framework/platform/init-dx.cpp
Normal file
64
framework/platform/init-dx.cpp
Normal file
@ -0,0 +1,64 @@
|
||||
#include "init-dx.hpp"
|
||||
#include "../csharp/type.hpp"
|
||||
#include "texture-dx.hpp"
|
||||
#include "content-readers/texture2Dreader-dx.hpp"
|
||||
#include "../content/typereadermanager.hpp"
|
||||
#include "../content/defaultreaders.hpp"
|
||||
|
||||
namespace xna {
|
||||
|
||||
|
||||
void InitPlatform::InitRegisteredTypes()
|
||||
{
|
||||
insertRegisteredReader<ObjectReader>("ObjecReader");
|
||||
insertRegisteredReader<BooleanReader>("BooleanReader");
|
||||
insertRegisteredReader<ByteReader>("ByteReader");
|
||||
insertRegisteredReader<CharReader>("CharReader");
|
||||
insertRegisteredReader<ColorReader>("ColorReader");
|
||||
insertRegisteredReader<DoubleReader>("DoubleReader");
|
||||
insertRegisteredReader<Int16Reader>("Int16Reader");
|
||||
insertRegisteredReader<Int32Reader>("Int32Reader");
|
||||
insertRegisteredReader<Int64Reader>("Int64Reader");
|
||||
insertRegisteredReader<MatrixReader>("MatrixReader");
|
||||
insertRegisteredReader<PointReader>("PointReader");
|
||||
insertRegisteredReader<QuaternionReader>("QuaternionReader");
|
||||
insertRegisteredReader<RectangleReader>("RectangleReader");
|
||||
insertRegisteredReader<SByteReader>("SByteReader");
|
||||
insertRegisteredReader<SingleReader>("SingleReader");
|
||||
insertRegisteredReader<TimeSpanReader>("TimeSpanReader");
|
||||
insertRegisteredReader<UInt16Reader>("UInt16Reader");
|
||||
insertRegisteredReader<UInt32Reader>("UInt32Reader");
|
||||
insertRegisteredReader<UInt64Reader>("UInt64Reader");
|
||||
insertRegisteredReader<Vector2Reader>("Vector2Reader");
|
||||
insertRegisteredReader<Vector3Reader>("Vector3Reader");
|
||||
insertRegisteredReader<Vector4Reader>("Vector4Reader");
|
||||
insertRegisteredReader<Texture2DReader>("Texture2DReader");
|
||||
}
|
||||
|
||||
void InitPlatform::InitActivadors()
|
||||
{
|
||||
insertActivadorReader<ObjectReader>();
|
||||
insertActivadorReader<BooleanReader>();
|
||||
insertActivadorReader<ByteReader>();
|
||||
insertActivadorReader<CharReader>();
|
||||
insertActivadorReader<ColorReader>();
|
||||
insertActivadorReader<DoubleReader>();
|
||||
insertActivadorReader<Int16Reader>();
|
||||
insertActivadorReader<Int32Reader>();
|
||||
insertActivadorReader<Int64Reader>();
|
||||
insertActivadorReader<MatrixReader>();
|
||||
insertActivadorReader<PointReader>();
|
||||
insertActivadorReader<QuaternionReader>();
|
||||
insertActivadorReader<RectangleReader>();
|
||||
insertActivadorReader<SByteReader>();
|
||||
insertActivadorReader<SingleReader>();
|
||||
insertActivadorReader<TimeSpanReader>();
|
||||
insertActivadorReader<UInt16Reader>();
|
||||
insertActivadorReader<UInt32Reader>();
|
||||
insertActivadorReader<UInt64Reader>();
|
||||
insertActivadorReader<Vector2Reader>();
|
||||
insertActivadorReader<Vector3Reader>();
|
||||
insertActivadorReader<Vector4Reader>();
|
||||
insertActivadorReader<Texture2DReader>();
|
||||
}
|
||||
}
|
36
framework/platform/init-dx.hpp
Normal file
36
framework/platform/init-dx.hpp
Normal file
@ -0,0 +1,36 @@
|
||||
#ifndef XNA_PLATFORM_INIT_HPP
|
||||
#define XNA_PLATFORM_INIT_HPP
|
||||
|
||||
#include "../default.hpp"
|
||||
#include "../csharp/type.hpp"
|
||||
#include "../content/typereadermanager.hpp"
|
||||
|
||||
namespace xna {
|
||||
struct InitPlatform {
|
||||
static void Init() {
|
||||
InitRegisteredTypes();
|
||||
InitActivadors();
|
||||
}
|
||||
|
||||
static void InitRegisteredTypes();
|
||||
static void InitActivadors();
|
||||
|
||||
private:
|
||||
template <typename T>
|
||||
static void insertRegisteredReader(String const& readerName) {
|
||||
const auto reader = typeof<T>();
|
||||
Type::NameOfRegisteredTypes.insert({ "xna::" + readerName, reader });
|
||||
Type::NameOfRegisteredTypes.insert({ "Microsoft.Xna.Framework.Content." + readerName, reader });
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static void insertActivadorReader() {
|
||||
ContentTypeReaderActivador::SetActivador(typeof<T>(), []() -> sptr<ContentTypeReader> {
|
||||
auto obj = New <T>();
|
||||
return reinterpret_pointer_cast<ContentTypeReader>(obj);
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
@ -8,7 +8,7 @@
|
||||
namespace xna {
|
||||
class RasterizerState : public IRasterizerState, public GraphicsResource {
|
||||
public:
|
||||
RasterizerState(GraphicsDevice* device) : GraphicsResource(device){}
|
||||
RasterizerState(sptr<GraphicsDevice> const& device) : GraphicsResource(device){}
|
||||
|
||||
virtual ~RasterizerState() override {
|
||||
if (dxRasterizerState) {
|
||||
|
@ -4,30 +4,39 @@
|
||||
#include "device-dx.hpp"
|
||||
|
||||
namespace xna {
|
||||
bool RenderTarget2D::Initialize(GraphicsDevice& device) {
|
||||
if (!device._device)
|
||||
bool RenderTarget2D::Initialize(xna_error_ptr_arg) {
|
||||
if (!m_device || !m_device->_device) {
|
||||
xna_error_apply(err, XnaErrorCode::INVALID_OPERATION);
|
||||
return false;
|
||||
|
||||
if (_texture2D) {
|
||||
_texture2D->Release();
|
||||
_texture2D = nullptr;
|
||||
}
|
||||
|
||||
if (!device._swapChain->GetBackBuffer(_texture2D))
|
||||
if (dxTexture2D) {
|
||||
dxTexture2D->Release();
|
||||
dxTexture2D = nullptr;
|
||||
}
|
||||
|
||||
if (!m_device->_swapChain->GetBackBuffer(dxTexture2D))
|
||||
return false;
|
||||
|
||||
auto& dxdevice = device._device;
|
||||
auto& dxdevice = m_device->_device;
|
||||
|
||||
const auto hr = dxdevice->CreateRenderTargetView(_texture2D, NULL, &_renderTargetView);
|
||||
const auto hr = dxdevice->CreateRenderTargetView(dxTexture2D, NULL, &_renderTargetView);
|
||||
|
||||
if (FAILED(hr))
|
||||
if (FAILED(hr)) {
|
||||
xna_error_apply(err, XnaErrorCode::FAILED_OPERATION);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RenderTarget2D::Apply(GraphicsDevice& device) {
|
||||
auto& context = device._context;
|
||||
bool RenderTarget2D::Apply(xna_error_ptr_arg) {
|
||||
if (!m_device || !m_device->_context) {
|
||||
xna_error_apply(err, XnaErrorCode::INVALID_OPERATION);
|
||||
return false;
|
||||
}
|
||||
|
||||
auto& context = m_device->_context;
|
||||
context->OMSetRenderTargets(1, &_renderTargetView, nullptr);
|
||||
return true;
|
||||
}
|
||||
|
@ -9,6 +9,8 @@
|
||||
namespace xna {
|
||||
class RenderTarget2D : public IRenderTarget2D, public Texture2D {
|
||||
public:
|
||||
RenderTarget2D(sptr<GraphicsDevice> const& device) : Texture2D(device){}
|
||||
|
||||
virtual ~RenderTarget2D() override {
|
||||
if (_renderTargetView) {
|
||||
_renderTargetView->Release();
|
||||
@ -16,8 +18,8 @@ namespace xna {
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool Initialize(GraphicsDevice& device) override;
|
||||
virtual bool Apply(GraphicsDevice& device) override;
|
||||
virtual bool Initialize(xna_error_nullarg) override;
|
||||
virtual bool Apply(xna_error_nullarg) override;
|
||||
|
||||
public:
|
||||
ID3D11RenderTargetView* _renderTargetView = nullptr;
|
||||
|
@ -8,7 +8,7 @@
|
||||
namespace xna {
|
||||
class SamplerState : public ISamplerState, public GraphicsResource {
|
||||
public:
|
||||
SamplerState(GraphicsDevice* device) : GraphicsResource(device) {
|
||||
SamplerState(sptr<GraphicsDevice> const& device) : GraphicsResource(device) {
|
||||
_description.MaxAnisotropy = 4;
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
namespace xna {
|
||||
class Shader : public IShader, public GraphicsResource {
|
||||
public:
|
||||
Shader(GraphicsDevice* device) : GraphicsResource(device){}
|
||||
Shader(sptr<GraphicsDevice> const& device) : GraphicsResource(device){}
|
||||
|
||||
virtual ~Shader() override {}
|
||||
|
||||
@ -19,7 +19,7 @@ namespace xna {
|
||||
|
||||
class VertexShader : public Shader {
|
||||
public:
|
||||
VertexShader(GraphicsDevice* device) : Shader(device){}
|
||||
VertexShader(sptr<GraphicsDevice> const& device) : Shader(device){}
|
||||
|
||||
virtual ~VertexShader() override {
|
||||
if (_vertexShader) {
|
||||
@ -36,7 +36,7 @@ namespace xna {
|
||||
|
||||
class PixelShader : public Shader {
|
||||
public:
|
||||
PixelShader(GraphicsDevice* device) : Shader(device) {}
|
||||
PixelShader(sptr<GraphicsDevice> const& device) : Shader(device) {}
|
||||
|
||||
virtual ~PixelShader() override {
|
||||
if (_pixelShader) {
|
||||
|
@ -63,7 +63,7 @@ namespace xna {
|
||||
if (!_dxspriteBatch)
|
||||
return;
|
||||
|
||||
if (!texture._textureView)
|
||||
if (!texture.dxShaderResource)
|
||||
return;
|
||||
|
||||
const auto _position = XMFLOAT2(position.X, position.Y);
|
||||
@ -71,7 +71,7 @@ namespace xna {
|
||||
XMVECTORF32 _color = { v4.X, v4.Y, v4.Z, v4.W };
|
||||
|
||||
_dxspriteBatch->Draw(
|
||||
texture._textureView,
|
||||
texture.dxShaderResource,
|
||||
_position,
|
||||
_color
|
||||
);
|
||||
@ -81,7 +81,7 @@ namespace xna {
|
||||
if (!_dxspriteBatch)
|
||||
return;
|
||||
|
||||
if (!texture._textureView)
|
||||
if (!texture.dxShaderResource)
|
||||
return;
|
||||
|
||||
const auto _position = XMFLOAT2(position.X, position.Y);
|
||||
@ -98,7 +98,7 @@ namespace xna {
|
||||
};
|
||||
|
||||
_dxspriteBatch->Draw(
|
||||
texture._textureView,
|
||||
texture.dxShaderResource,
|
||||
_position,
|
||||
sourceRectangle ? &_sourceRect : nullptr,
|
||||
_color);
|
||||
@ -108,7 +108,7 @@ namespace xna {
|
||||
if (!_dxspriteBatch)
|
||||
return;
|
||||
|
||||
if (!texture._textureView)
|
||||
if (!texture.dxShaderResource)
|
||||
return;
|
||||
|
||||
const auto _position = XMFLOAT2(position.X, position.Y);
|
||||
@ -128,7 +128,7 @@ namespace xna {
|
||||
const DxSpriteEffects _effects = static_cast<DxSpriteEffects>(effects);
|
||||
|
||||
_dxspriteBatch->Draw(
|
||||
texture._textureView,
|
||||
texture.dxShaderResource,
|
||||
_position,
|
||||
sourceRectangle ? &_sourceRect : nullptr,
|
||||
_color,
|
||||
@ -143,7 +143,7 @@ namespace xna {
|
||||
if (!_dxspriteBatch)
|
||||
return;
|
||||
|
||||
if (!texture._textureView)
|
||||
if (!texture.dxShaderResource)
|
||||
return;
|
||||
|
||||
const auto _position = XMFLOAT2(position.X, position.Y);
|
||||
@ -164,7 +164,7 @@ namespace xna {
|
||||
const XMFLOAT2 _scale = { scale.X, scale.Y };
|
||||
|
||||
_dxspriteBatch->Draw(
|
||||
texture._textureView,
|
||||
texture.dxShaderResource,
|
||||
_position,
|
||||
sourceRectangle ? &_sourceRect : nullptr,
|
||||
_color,
|
||||
@ -179,7 +179,7 @@ namespace xna {
|
||||
if (!_dxspriteBatch)
|
||||
return;
|
||||
|
||||
if (!texture._textureView)
|
||||
if (!texture.dxShaderResource)
|
||||
return;
|
||||
|
||||
RECT _destinationRect{};
|
||||
@ -191,14 +191,14 @@ namespace xna {
|
||||
const auto v4 = color.ToVector4();
|
||||
const XMVECTORF32 _color = { v4.X, v4.Y, v4.Z, v4.W };
|
||||
|
||||
_dxspriteBatch->Draw(texture._textureView, _destinationRect, _color);
|
||||
_dxspriteBatch->Draw(texture.dxShaderResource, _destinationRect, _color);
|
||||
}
|
||||
|
||||
void SpriteBatch::Draw(Texture2D& texture, Rectangle const& destinationRectangle, Rectangle const* sourceRectangle, Color const& color) {
|
||||
if (!_dxspriteBatch)
|
||||
return;
|
||||
|
||||
if (!texture._textureView)
|
||||
if (!texture.dxShaderResource)
|
||||
return;
|
||||
|
||||
RECT _destinationRect{};
|
||||
@ -219,14 +219,14 @@ namespace xna {
|
||||
_sourceRect.bottom = sourceRectangle->Y + sourceRectangle->Height;
|
||||
};
|
||||
|
||||
_dxspriteBatch->Draw(texture._textureView, _destinationRect, sourceRectangle ? &_sourceRect : nullptr, _color);
|
||||
_dxspriteBatch->Draw(texture.dxShaderResource, _destinationRect, sourceRectangle ? &_sourceRect : nullptr, _color);
|
||||
}
|
||||
|
||||
void SpriteBatch::Draw(Texture2D& texture, Rectangle const& destinationRectangle, Rectangle const* sourceRectangle, Color const& color, float rotation, Vector2 const& origin, SpriteEffects effects, float layerDepth) {
|
||||
if (!_dxspriteBatch)
|
||||
return;
|
||||
|
||||
if (!texture._textureView)
|
||||
if (!texture.dxShaderResource)
|
||||
return;
|
||||
|
||||
RECT _destinationRect{};
|
||||
@ -251,7 +251,7 @@ namespace xna {
|
||||
const auto _effects = static_cast<DxSpriteEffects>(effects);
|
||||
|
||||
_dxspriteBatch->Draw(
|
||||
texture._textureView,
|
||||
texture.dxShaderResource,
|
||||
_destinationRect,
|
||||
sourceRectangle ? &_sourceRect : nullptr,
|
||||
_color,
|
||||
|
@ -9,7 +9,7 @@
|
||||
namespace xna {
|
||||
class SwapChain : public ISwapChain, public GraphicsResource {
|
||||
public:
|
||||
SwapChain(GraphicsDevice* device): GraphicsResource(device){}
|
||||
SwapChain(sptr<GraphicsDevice> const& device): GraphicsResource(device){}
|
||||
|
||||
virtual ~SwapChain() override {
|
||||
if (dxSwapChain) {
|
||||
|
@ -1,15 +1,12 @@
|
||||
#include "texture-dx.hpp"
|
||||
#include "WICTextureLoader.h"
|
||||
#include "device-dx.hpp"
|
||||
#include "../helpers.hpp"
|
||||
|
||||
namespace xna {
|
||||
Texture2D::Texture2D() {
|
||||
}
|
||||
#include "adapter-dx.hpp"
|
||||
|
||||
namespace xna {
|
||||
sptr<Texture2D> Texture2D::FromStream(GraphicsDevice& device, String const& fileName, xna_error_ptr_arg)
|
||||
{
|
||||
auto texture2d = New<Texture2D>();
|
||||
auto _this = device.shared_from_this();
|
||||
auto texture2d = New<Texture2D>(_this);
|
||||
ID3D11Resource* resource = nullptr;
|
||||
auto wstr = XnaHToWString(fileName);
|
||||
|
||||
@ -18,7 +15,7 @@ namespace xna {
|
||||
device._context,
|
||||
wstr.c_str(),
|
||||
&resource,
|
||||
&texture2d->_textureView,
|
||||
&texture2d->dxShaderResource,
|
||||
0U);
|
||||
|
||||
if (FAILED(result))
|
||||
@ -33,7 +30,7 @@ namespace xna {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
result = resource->QueryInterface(IID_ID3D11Texture2D, (void**)&texture2d->_texture2D);
|
||||
result = resource->QueryInterface(IID_ID3D11Texture2D, (void**)&texture2d->dxTexture2D);
|
||||
|
||||
if (FAILED(result)) {
|
||||
xna_error_apply(err, XnaErrorCode::FAILED_OPERATION);
|
||||
@ -47,12 +44,284 @@ namespace xna {
|
||||
}
|
||||
|
||||
D3D11_TEXTURE2D_DESC desc;
|
||||
texture2d->_texture2D->GetDesc(&desc);
|
||||
texture2d->_description = desc;
|
||||
texture2d->dxTexture2D->GetDesc(&desc);
|
||||
texture2d->dxDescription = desc;
|
||||
|
||||
resource->Release();
|
||||
resource = nullptr;
|
||||
|
||||
return texture2d;
|
||||
}
|
||||
|
||||
bool Texture2D::Initialize(xna_error_ptr_arg)
|
||||
{
|
||||
if (dxTexture2D) {
|
||||
xna_error_apply(err, XnaErrorCode::WARNING_INITIALIZED_RESOURCE);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m_device || !m_device->_device) {
|
||||
xna_error_apply(err, XnaErrorCode::INVALID_OPERATION);
|
||||
return false;
|
||||
}
|
||||
|
||||
auto hr = m_device->_device->CreateTexture2D(&dxDescription, nullptr, &dxTexture2D);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
xna_error_apply(err, XnaErrorCode::FAILED_OPERATION);
|
||||
return false;
|
||||
}
|
||||
|
||||
ID3D11Resource* resource = nullptr;
|
||||
hr = dxTexture2D->QueryInterface(IID_ID3D11Resource, (void**)&resource);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
xna_error_apply(err, XnaErrorCode::FAILED_OPERATION);
|
||||
return false;
|
||||
}
|
||||
|
||||
hr = m_device->_device->CreateShaderResourceView(resource, &dxShaderDescription, &dxShaderResource);
|
||||
|
||||
if (resource) {
|
||||
resource->Release();
|
||||
resource = nullptr;
|
||||
}
|
||||
|
||||
if (FAILED(hr)) {
|
||||
xna_error_apply(err, XnaErrorCode::FAILED_OPERATION);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Texture2D::Texture2D(sptr<GraphicsDevice> const& device, size_t width, size_t height) : GraphicsResource(device) {
|
||||
setDefaultDesc();
|
||||
dxDescription.Width = static_cast<UINT>(width);
|
||||
dxDescription.Height = static_cast<UINT>(height);
|
||||
}
|
||||
|
||||
Texture2D::Texture2D(sptr<GraphicsDevice> const& device) : GraphicsResource(device) {
|
||||
setDefaultDesc();
|
||||
}
|
||||
|
||||
Texture2D::Texture2D(sptr<GraphicsDevice> const& device, size_t width, size_t height, size_t mipMap, SurfaceFormat format) : GraphicsResource(device)
|
||||
{
|
||||
setDefaultDesc();
|
||||
dxDescription.Width = static_cast<UINT>(width);
|
||||
dxDescription.Height = static_cast<UINT>(height);
|
||||
dxDescription.MipLevels = static_cast<UINT>(mipMap);
|
||||
dxDescription.Format = GraphicsAdapter::ConvertSurfaceToDXGIFORMAT(format);
|
||||
}
|
||||
|
||||
void Texture2D::SetData(std::vector<Uint> const& data, size_t startIndex, size_t elementCount, xna_error_ptr_arg)
|
||||
{
|
||||
if (!m_device || !m_device->_device || !m_device->_context) {
|
||||
xna_error_apply(err, XnaErrorCode::INVALID_OPERATION);
|
||||
return;
|
||||
}
|
||||
|
||||
internalSetData(data.data(), err);
|
||||
}
|
||||
|
||||
void Texture2D::SetData(std::vector<Byte> const& data, size_t startIndex, size_t elementCount, xna_error_ptr_arg)
|
||||
{
|
||||
if (!m_device || !m_device->_device || !m_device->_context) {
|
||||
xna_error_apply(err, XnaErrorCode::INVALID_OPERATION);
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<UINT> finalData(elementCount / 4);
|
||||
auto fIndex = 0;
|
||||
|
||||
for (size_t i = startIndex; i < elementCount; ++i) {
|
||||
const auto& r = data[i];
|
||||
const auto& g = data[++i];
|
||||
const auto& b = data[++i];
|
||||
const auto& a = data[++i];
|
||||
finalData[fIndex] = Color(r, g, b, a);
|
||||
++fIndex;
|
||||
}
|
||||
|
||||
internalSetData(finalData.data(), err);
|
||||
}
|
||||
|
||||
void Texture2D::SetData(Int level, Rectangle* rect, std::vector<Byte> const& data, size_t startIndex, size_t elementCount, xna_error_ptr_arg)
|
||||
{
|
||||
if (!m_device || !m_device->_device || !m_device->_context) {
|
||||
xna_error_apply(err, XnaErrorCode::INVALID_OPERATION);
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<UINT> finalData(elementCount / 4);
|
||||
auto fIndex = 0;
|
||||
|
||||
for (size_t i = startIndex; i < elementCount; ++i) {
|
||||
const auto& r = data[i];
|
||||
const auto& g = data[++i];
|
||||
const auto& b = data[++i];
|
||||
const auto& a = data[++i];
|
||||
finalData[fIndex] = Color(r, g, b, a);
|
||||
++fIndex;
|
||||
}
|
||||
|
||||
if (!dxTexture2D) {
|
||||
auto hr = m_device->_device->CreateTexture2D(&dxDescription, nullptr, &dxTexture2D);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
xna_error_apply(err, XnaErrorCode::FAILED_OPERATION);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ID3D11Resource* resource = nullptr;
|
||||
auto hr = dxTexture2D->QueryInterface(IID_ID3D11Resource, (void**)&resource);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
xna_error_apply(err, XnaErrorCode::FAILED_OPERATION);
|
||||
return;
|
||||
}
|
||||
|
||||
D3D11_BOX box{};
|
||||
|
||||
if (rect) {
|
||||
box.left = rect->X;
|
||||
box.right = rect->X + rect->Width;
|
||||
box.top = rect->Y;
|
||||
box.bottom = rect->Y + rect->Height;
|
||||
box.back = level;
|
||||
box.front = 0;
|
||||
}
|
||||
|
||||
m_device->_context->UpdateSubresource(resource, 0, rect ? &box : nullptr, finalData.data(), dxDescription.Width * R8G8B8A8U_BYTE_SIZE, 0);
|
||||
|
||||
if (dxShaderResource) {
|
||||
dxShaderResource->Release();
|
||||
dxShaderResource = nullptr;
|
||||
}
|
||||
|
||||
dxShaderDescription.Texture2D.MipLevels = dxDescription.MipLevels;
|
||||
hr = m_device->_device->CreateShaderResourceView(resource, &dxShaderDescription, &dxShaderResource);
|
||||
|
||||
if (resource) {
|
||||
resource->Release();
|
||||
resource = nullptr;
|
||||
}
|
||||
|
||||
if (FAILED(hr)) {
|
||||
xna_error_apply(err, XnaErrorCode::FAILED_OPERATION);
|
||||
return;
|
||||
}
|
||||
|
||||
dxTexture2D->GetDesc(&dxDescription);
|
||||
}
|
||||
|
||||
void Texture2D::SetData(std::vector<Color> const& data, size_t startIndex, size_t elementCount, xna_error_ptr_arg)
|
||||
{
|
||||
if (!m_device || !m_device->_device || !m_device->_context) {
|
||||
xna_error_apply(err, XnaErrorCode::INVALID_OPERATION);
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<UINT> finalData(elementCount);
|
||||
auto finalDataIndex = 0;
|
||||
|
||||
for (size_t i = startIndex; i < elementCount; ++i) {
|
||||
finalData[finalDataIndex] = static_cast<UINT>(data[i]);
|
||||
++finalDataIndex;
|
||||
}
|
||||
|
||||
internalSetData(finalData.data(), err);
|
||||
}
|
||||
|
||||
sptr<Texture2D> Texture2D::FromMemory(GraphicsDevice& device, std::vector<Byte> const& data, xna_error_ptr_arg)
|
||||
{
|
||||
auto _this = device.shared_from_this();
|
||||
auto texture2d = New<Texture2D>(_this);
|
||||
ID3D11Resource* resource = nullptr;
|
||||
|
||||
auto hr = DirectX::CreateWICTextureFromMemory(
|
||||
device._device,
|
||||
device._context,
|
||||
data.data(),
|
||||
data.size(),
|
||||
&resource,
|
||||
&texture2d->dxShaderResource);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
xna_error_apply(err, XnaErrorCode::FAILED_OPERATION);
|
||||
|
||||
if (resource) {
|
||||
resource->Release();
|
||||
resource = nullptr;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
hr = resource->QueryInterface(IID_ID3D11Texture2D, (void**)&texture2d->dxTexture2D);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
xna_error_apply(err, XnaErrorCode::FAILED_OPERATION);
|
||||
|
||||
if (resource) {
|
||||
resource->Release();
|
||||
resource = nullptr;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
D3D11_TEXTURE2D_DESC desc;
|
||||
texture2d->dxTexture2D->GetDesc(&desc);
|
||||
texture2d->dxDescription = desc;
|
||||
|
||||
resource->Release();
|
||||
resource = nullptr;
|
||||
|
||||
return texture2d;
|
||||
}
|
||||
|
||||
void Texture2D::internalSetData(UINT const* data, xna_error_ptr_arg)
|
||||
{
|
||||
if (!dxTexture2D) {
|
||||
auto hr = m_device->_device->CreateTexture2D(&dxDescription, nullptr, &dxTexture2D);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
xna_error_apply(err, XnaErrorCode::FAILED_OPERATION);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ID3D11Resource* resource = nullptr;
|
||||
auto hr = dxTexture2D->QueryInterface(IID_ID3D11Resource, (void**)&resource);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
xna_error_apply(err, XnaErrorCode::FAILED_OPERATION);
|
||||
return;
|
||||
}
|
||||
|
||||
m_device->_context->UpdateSubresource(resource, 0, nullptr, data, dxDescription.Width * R8G8B8A8U_BYTE_SIZE, 0);
|
||||
|
||||
if (dxShaderResource) {
|
||||
dxShaderResource->Release();
|
||||
dxShaderResource = nullptr;
|
||||
}
|
||||
|
||||
dxShaderDescription.Texture2D.MipLevels = dxDescription.MipLevels;
|
||||
hr = m_device->_device->CreateShaderResourceView(resource, &dxShaderDescription, &dxShaderResource);
|
||||
|
||||
if (resource) {
|
||||
resource->Release();
|
||||
resource = nullptr;
|
||||
}
|
||||
|
||||
if (FAILED(hr)) {
|
||||
xna_error_apply(err, XnaErrorCode::FAILED_OPERATION);
|
||||
return;
|
||||
}
|
||||
|
||||
dxTexture2D->GetDesc(&dxDescription);
|
||||
}
|
||||
}
|
@ -1,44 +1,84 @@
|
||||
#ifndef XNA_PLATFORM_TEXTURE_DX_HPP
|
||||
#define XNA_PLATFORM_TEXTURE_DX_HPP
|
||||
|
||||
#include "../common/rectangle.hpp"
|
||||
#include "../graphics/gresource.hpp"
|
||||
#include "../graphics/texture.hpp"
|
||||
#include "dxgi.h"
|
||||
#include "d3d11.h"
|
||||
#include "../xnaerror.hpp"
|
||||
#include "dxheaders.hpp"
|
||||
#include "device-dx.hpp"
|
||||
|
||||
namespace xna {
|
||||
class Texture2D : public ITexture2D {
|
||||
class Texture2D : public ITexture2D, public GraphicsResource {
|
||||
public:
|
||||
Texture2D();
|
||||
Texture2D() : GraphicsResource(nullptr){
|
||||
setDefaultDesc();
|
||||
}
|
||||
|
||||
Texture2D(sptr<GraphicsDevice> const& device);
|
||||
Texture2D(sptr<GraphicsDevice> const& device, size_t width, size_t height);
|
||||
Texture2D(sptr<GraphicsDevice> const& device, size_t width, size_t height, size_t mipMap, SurfaceFormat format);
|
||||
|
||||
virtual ~Texture2D() override {
|
||||
if (_texture2D) {
|
||||
_texture2D->Release();
|
||||
_texture2D = nullptr;
|
||||
if (dxTexture2D) {
|
||||
dxTexture2D->Release();
|
||||
dxTexture2D = nullptr;
|
||||
}
|
||||
|
||||
if (_textureView) {
|
||||
_textureView->Release();
|
||||
_textureView = nullptr;
|
||||
if (dxShaderResource) {
|
||||
dxShaderResource->Release();
|
||||
dxShaderResource = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
virtual constexpr Int Width() const override {
|
||||
return _description.Width;
|
||||
return dxDescription.Width;
|
||||
}
|
||||
|
||||
virtual constexpr Int Height() const override {
|
||||
return _description.Height;
|
||||
return dxDescription.Height;
|
||||
}
|
||||
|
||||
static sptr<Texture2D> FromStream(GraphicsDevice& device, String const& fileName, xna_error_nullarg);
|
||||
constexpr Rectangle Bounds() const override {
|
||||
return { 0, 0, static_cast<Int>(dxDescription.Width), static_cast<Int>(dxDescription.Height) };
|
||||
}
|
||||
|
||||
bool Initialize(xna_error_nullarg) override;
|
||||
|
||||
void SetData(std::vector<Color> const& data, size_t startIndex = 0, size_t elementCount = 0, xna_error_nullarg);
|
||||
void SetData(std::vector<Uint> const& data, size_t startIndex = 0, size_t elementCount = 0, xna_error_nullarg);
|
||||
void SetData(std::vector<Byte> const& data, size_t startIndex = 0, size_t elementCount = 0, xna_error_nullarg);
|
||||
|
||||
void SetData(Int level, Rectangle* rect, std::vector<Byte> const& data, size_t startIndex, size_t elementCount, xna_error_nullarg);
|
||||
|
||||
static sptr<Texture2D> FromStream(GraphicsDevice& device, String const& fileName, xna_error_nullarg);
|
||||
static sptr<Texture2D> FromMemory(GraphicsDevice& device, std::vector<Byte> const& data, xna_error_nullarg);
|
||||
|
||||
public:
|
||||
ID3D11Texture2D* _texture2D{nullptr};
|
||||
ID3D11ShaderResourceView* _textureView{ nullptr };
|
||||
D3D11_TEXTURE2D_DESC _description{};
|
||||
|
||||
};
|
||||
ID3D11Texture2D* dxTexture2D{ nullptr };
|
||||
ID3D11ShaderResourceView* dxShaderResource{ nullptr };
|
||||
D3D11_SUBRESOURCE_DATA dxSubResource{};
|
||||
D3D11_TEXTURE2D_DESC dxDescription{};
|
||||
D3D11_SHADER_RESOURCE_VIEW_DESC dxShaderDescription{};
|
||||
|
||||
private:
|
||||
static constexpr int R8G8B8A8U_BYTE_SIZE = 4;
|
||||
|
||||
void setDefaultDesc() {
|
||||
dxDescription.MipLevels = 1;
|
||||
dxDescription.ArraySize = 1;
|
||||
dxDescription.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
dxDescription.SampleDesc.Count = 1;
|
||||
dxDescription.Usage = D3D11_USAGE_DEFAULT;
|
||||
dxDescription.BindFlags = D3D11_BIND_SHADER_RESOURCE;
|
||||
|
||||
dxShaderDescription.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
dxShaderDescription.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
|
||||
dxShaderDescription.Texture2D.MipLevels = dxDescription.MipLevels;
|
||||
dxShaderDescription.Texture2D.MostDetailedMip = 0;
|
||||
}
|
||||
|
||||
void internalSetData(UINT const* data, xna_error_nullarg);
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
@ -44,6 +44,7 @@ namespace xna {
|
||||
constexpr double DoubleMinValue = std::numeric_limits<double>::min();
|
||||
|
||||
using String = std::string;
|
||||
using WString = std::wstring;
|
||||
|
||||
template <typename T>
|
||||
using sptr = std::shared_ptr<T>;
|
||||
|
@ -9,28 +9,26 @@ using namespace xna;
|
||||
namespace xna {
|
||||
class Game1 : public Game {
|
||||
public:
|
||||
Game1() {
|
||||
Game1() : Game() {
|
||||
auto _game = reinterpret_cast<Game*>(this);
|
||||
graphics = New<GraphicsDeviceManager>(_game);
|
||||
graphics->PreferredBackBufferWidth(1280);
|
||||
graphics->PreferredBackBufferHeight(720);
|
||||
|
||||
contentManager = New<ContentManager>("Content");
|
||||
//const auto s = contentManager->_path.string();
|
||||
// const auto current = std::filesystem::current_path();
|
||||
auto s = contentManager->OpenStream("file");
|
||||
Content()->RootDirectory("Content");
|
||||
}
|
||||
|
||||
void Initialize() override {
|
||||
graphics->Initialize();
|
||||
|
||||
std::any device = graphicsDevice;
|
||||
services->AddService(*typeof<GraphicsDevice>(), device);
|
||||
|
||||
Game::Initialize();
|
||||
}
|
||||
|
||||
void LoadContent() override {
|
||||
spriteBatch = New<SpriteBatch>(*_graphicsDevice);
|
||||
spriteBatch = New<SpriteBatch>(*graphicsDevice);
|
||||
|
||||
XnaErrorCode err;
|
||||
texture = Texture2D::FromStream(*_graphicsDevice, "D:\\sprite.jpg", &err);
|
||||
texture = Content()->Load<PTexture2D>("idle");
|
||||
|
||||
Game::LoadContent();
|
||||
}
|
||||
@ -43,10 +41,10 @@ namespace xna {
|
||||
}
|
||||
|
||||
void Draw(GameTime const& gameTime) override {
|
||||
_graphicsDevice->Clear(Colors::CornflowerBlue);
|
||||
graphicsDevice->Clear(Colors::CornflowerBlue);
|
||||
|
||||
spriteBatch->Begin();
|
||||
spriteBatch->Draw(*texture, position, Colors::White);
|
||||
spriteBatch->Draw(*texture, Vector2(10, 10), Colors::White);
|
||||
spriteBatch->End();
|
||||
|
||||
Game::Draw(gameTime);
|
||||
@ -55,20 +53,14 @@ namespace xna {
|
||||
private:
|
||||
sptr<GraphicsDeviceManager> graphics = nullptr;
|
||||
sptr<SpriteBatch> spriteBatch = nullptr;
|
||||
sptr<Texture2D> texture = nullptr; //200x200
|
||||
Vector2 position{};
|
||||
std::vector<Vector2> points;
|
||||
MouseState currentState{};
|
||||
MouseState oldState{};
|
||||
float vel = 1;
|
||||
int var = 0;
|
||||
sptr<ContentManager> contentManager;
|
||||
PTexture2D texture = nullptr;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
int APIENTRY WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nCmdShow) {
|
||||
|
||||
xna::InitPlatform::Init();
|
||||
|
||||
auto game = xna::Game1();
|
||||
const auto result = game.Run();
|
||||
return result;
|
||||
|
@ -24,5 +24,7 @@
|
||||
#include "Windows.h"
|
||||
#include <iostream>
|
||||
#include "content/manager.hpp"
|
||||
#include "platform/init-dx.hpp"
|
||||
#include "csharp/type.hpp"
|
||||
|
||||
// TODO: Reference additional headers your program requires here.
|
||||
|
@ -13,7 +13,9 @@ namespace xna {
|
||||
BAD_CAST,
|
||||
STREAM_ERROR,
|
||||
UNINTIALIZED_RESOURCE,
|
||||
END_OF_FILE
|
||||
END_OF_FILE,
|
||||
BAD_TYPE,
|
||||
WARNING_INITIALIZED_RESOURCE
|
||||
};
|
||||
|
||||
inline void xna_error_apply(XnaErrorCode* source, XnaErrorCode const& value) {
|
||||
@ -22,7 +24,7 @@ namespace xna {
|
||||
}
|
||||
|
||||
inline bool xna_error_haserros(XnaErrorCode* source) {
|
||||
return source != nullptr;
|
||||
return source != nullptr && *source != XnaErrorCode::NONE;
|
||||
}
|
||||
|
||||
#define xna_error_nullarg XnaErrorCode* err = nullptr
|
||||
|
Loading…
x
Reference in New Issue
Block a user