diff --git a/CMakeLists.txt b/CMakeLists.txt index 4f8c094..5f9f0f0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,6 +9,8 @@ if (POLICY CMP0141) set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "$,$>,$<$:EditAndContinue>,$<$:ProgramDatabase>>") endif() +set(ENV{VCPKG_ROOT} C:\\vcpkg) + project ("xna") # Include sub-projects. diff --git a/framework/CMakeLists.txt b/framework/CMakeLists.txt index d127244..5eb9432 100644 --- a/framework/CMakeLists.txt +++ b/framework/CMakeLists.txt @@ -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 +) diff --git a/framework/common/color.cpp b/framework/common/color.cpp new file mode 100644 index 0000000..c25e283 --- /dev/null +++ b/framework/common/color.cpp @@ -0,0 +1,5 @@ +#include "color.hpp" + +namespace xna { + +} \ No newline at end of file diff --git a/framework/common/color.hpp b/framework/common/color.hpp index a366598..40f52d1 100644 --- a/framework/common/color.hpp +++ b/framework/common/color.hpp @@ -189,6 +189,10 @@ namespace xna { return Color::Multiply(value, scale); } + constexpr operator Uint() const { + return _packedValue; + } + private: Uint _packedValue{ 0 }; diff --git a/framework/common/math.hpp b/framework/common/math.hpp index a417d1f..452d28d 100644 --- a/framework/common/math.hpp +++ b/framework/common/math.hpp @@ -2,6 +2,7 @@ #define XNA_COMMON_MATH_HPP #include +#include 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::epsilon(); - }; - using Math = MathHelper; + static constexpr float ToRadians(float degrees) { return degrees * (static_cast(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 \ No newline at end of file diff --git a/framework/common/matrix.cpp b/framework/common/matrix.cpp index b2bcf1f..bcd2621 100644 --- a/framework/common/matrix.cpp +++ b/framework/common/matrix.cpp @@ -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(); } diff --git a/framework/common/matrix.hpp b/framework/common/matrix.hpp index 3a2959c..3da4588 100644 --- a/framework/common/matrix.hpp +++ b/framework/common/matrix.hpp @@ -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 \ No newline at end of file diff --git a/framework/common/quaternion.hpp b/framework/common/quaternion.hpp index 87372d7..d7adeba 100644 --- a/framework/common/quaternion.hpp +++ b/framework/common/quaternion.hpp @@ -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 \ No newline at end of file diff --git a/framework/common/rectangle.hpp b/framework/common/rectangle.hpp index c454bc8..ed14fdc 100644 --- a/framework/common/rectangle.hpp +++ b/framework/common/rectangle.hpp @@ -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; + } }; } diff --git a/framework/common/vectors.cpp b/framework/common/vectors.cpp index eb7dc6c..67c4034 100644 --- a/framework/common/vectors.cpp +++ b/framework/common/vectors.cpp @@ -17,6 +17,14 @@ namespace xna { return true; } + bool Vector2::Transform(std::vector sourceArray, Matrix const& matrix, std::vector& 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 const& sourceArray, size_t sourceIndex, Matrix const& matrix, std::vector& 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 const& sourceArray, Matrix const& matrix, std::vector& 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 const& sourceArray, size_t sourceIndex, Matrix const& matrix, std::vector& 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 const& sourceArray, Quaternion const& rotation, std::vector& 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 const& sourceArray, Matrix const& matrix, std::vector& destinationArray) + bool Vector2::Transform(std::vector const& sourceArray, size_t sourceIndex, Quaternion const& rotation, std::vector& 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 const& sourceArray, size_t sourceIndex, Matrix const& matrix, std::vector& destinationArray, size_t destinationIndex, size_t length) + bool Vector3::Transform(std::vector const& sourceArray, Matrix const& matrix, std::vector& 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 const& sourceArray, Matrix const& matrix, std::vector& destinationArray) + bool Vector3::Transform(std::vector const& sourceArray, size_t sourceIndex, Matrix const& matrix, std::vector& 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 const& sourceArray, size_t sourceIndex, Matrix const& matrix, std::vector& destinationArray, size_t destinationIndex, size_t length) + bool Vector3::TransformNormal(std::vector const& sourceArray, Matrix const& matrix, std::vector& 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 const& sourceArray, Quaternion const& rotation, std::vector& destinationArray) + bool Vector3::TransformNormal(std::vector const& sourceArray, size_t sourceIndex, Matrix const& matrix, std::vector& 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 const& sourceArray, size_t sourceIndex, Quaternion const& rotation, std::vector& destinationArray, size_t destinationIndex, size_t length) + bool Vector3::TransformNormal(std::vector const& sourceArray, Quaternion const& rotation, std::vector& 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 const& sourceArray, size_t sourceIndex, Quaternion const& rotation, std::vector& 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 const& sourceArray, size_t sourceLength, Matrix const& matrix, std::vector& 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 const& sourceArray, size_t sourceIndex, Matrix const& matrix, std::vector& 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 const& sourceArray, Quaternion const& rotation, std::vector& 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 const& sourceArray, size_t sourceIndex, Quaternion const& rotation, std::vector& 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); + } } \ No newline at end of file diff --git a/framework/common/vectors.hpp b/framework/common/vectors.hpp index 5587285..20a3abb 100644 --- a/framework/common/vectors.hpp +++ b/framework/common/vectors.hpp @@ -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 sourceArray, Matrix const& matrix, std::vector& 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 const& sourceArray, size_t sourceIndex, Matrix const& matrix, std::vector& 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 const& sourceArray, Matrix const& matrix, std::vector& 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 const& sourceArray, size_t sourceIndex, Matrix const& matrix, std::vector& 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 const& sourceArray, Quaternion const& rotation, std::vector& 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 const& sourceArray, size_t sourceIndex, Quaternion const& rotation, std::vector& 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 const& sourceArray, Matrix const& matrix, std::vector& 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 const& sourceArray, size_t sourceIndex, Matrix const& matrix, std::vector& 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 const& sourceArray, Matrix const& matrix, std::vector& 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 const& sourceArray, size_t sourceIndex, Matrix const& matrix, std::vector& 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 const& sourceArray, Quaternion const& rotation, std::vector& 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 const& sourceArray, size_t sourceIndex, Quaternion const& rotation, std::vector& 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 const& sourceArray, size_t sourceLength, Matrix const& matrix, std::vector& 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 const& sourceArray, size_t sourceIndex, Matrix const& matrix, std::vector& 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 const& sourceArray, Quaternion const& rotation, std::vector& 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 const& sourceArray, size_t sourceIndex, Quaternion const& rotation, std::vector& 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); + } }; } diff --git a/framework/content/defaultreaders.hpp b/framework/content/defaultreaders.hpp new file mode 100644 index 0000000..376bb58 --- /dev/null +++ b/framework/content/defaultreaders.hpp @@ -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 { + public: + ObjectReader() : ContentTypeReaderT(typeof()) {} + + virtual Object Read(ContentReader& input, Object& existingInstance) override { + return Object(); + } + }; + + class BooleanReader : public ContentTypeReaderT { + public: + BooleanReader() : ContentTypeReaderT(typeof()) {} + + bool Read(ContentReader& input, bool& existingInstance) override { + return input.ReadBoolean(); + } + }; + + class ByteReader : public ContentTypeReaderT { + public: + ByteReader() : ContentTypeReaderT(typeof()) {} + + Byte Read(ContentReader& input, Byte& existingInstance) override { + const auto b = input.ReadByte(); + return b; + } + }; + + class CharReader : public ContentTypeReaderT { + public: + CharReader() : ContentTypeReaderT(typeof()) {} + + Char Read(ContentReader& input, Char& existingInstance) override { + const auto b = input.ReadChar(); + return b; + } + }; + + class ColorReader : public ContentTypeReaderT { + public: + ColorReader() : ContentTypeReaderT(typeof()) {} + + Color Read(ContentReader& input, Color& existingInstance) override { + const auto i = input.ReadUInt32(); + return { i }; + } + }; + + class DoubleReader : public ContentTypeReaderT { + public: + DoubleReader() : ContentTypeReaderT(typeof()) {} + + double Read(ContentReader& input, double& existingInstance) override { + return input.ReadDouble(); + } + }; + + class Int16Reader : public ContentTypeReaderT { + public: + Int16Reader() : ContentTypeReaderT(typeof()) {} + + Short Read(ContentReader& input, Short& existingInstance) override { + return input.ReadInt16(); + } + }; + + class Int32Reader : public ContentTypeReaderT { + public: + Int32Reader() : ContentTypeReaderT(typeof()) {} + + Int Read(ContentReader& input, Int& existingInstance) override { + return input.ReadInt32(); + } + }; + + class Int64Reader : public ContentTypeReaderT { + public: + Int64Reader() : ContentTypeReaderT(typeof()) {} + + Long Read(ContentReader& input, Long& existingInstance) override { + return input.ReadInt64(); + } + }; + + class MatrixReader : public ContentTypeReaderT { + public: + MatrixReader() : ContentTypeReaderT(typeof()) {} + + Matrix Read(ContentReader& input, Matrix& existingInstance) override { + return input.ReadMatrix(); + } + }; + + class PointReader : public ContentTypeReaderT { + public: + PointReader() : ContentTypeReaderT(typeof()) {} + + Point Read(ContentReader& input, Point& existingInstance) override { + Point point; + point.X = input.ReadInt32(); + point.Y = input.ReadInt32(); + return point; + } + }; + + class QuaternionReader : public ContentTypeReaderT { + public: + QuaternionReader() : ContentTypeReaderT(typeof()) {} + + Quaternion Read(ContentReader& input, Quaternion& existingInstance) override { + return input.ReadQuaternion(); + } + }; + + class RectangleReader : public ContentTypeReaderT { + public: + RectangleReader() : ContentTypeReaderT(typeof()) {} + + 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 { + public: + SByteReader() : ContentTypeReaderT(typeof()) {} + + Sbyte Read(ContentReader& input, Sbyte& existingInstance) override { + return input.ReadSByte(); + } + }; + + class SingleReader : public ContentTypeReaderT { + public: + SingleReader() : ContentTypeReaderT(typeof()) {} + + float Read(ContentReader& input, float& existingInstance) override { + return input.ReadSingle(); + } + }; + + class TimeSpanReader : public ContentTypeReaderT { + public: + TimeSpanReader() : ContentTypeReaderT(typeof()) {} + + TimeSpan Read(ContentReader& input, TimeSpan& existingInstance) override { + return TimeSpan::FromTicks(input.ReadInt64()); + } + }; + + class UInt16Reader : public ContentTypeReaderT { + public: + UInt16Reader() : ContentTypeReaderT(typeof()) {} + + Ushort Read(ContentReader& input, Ushort& existingInstance) override { + return input.ReadUInt16(); + } + }; + + class UInt32Reader : public ContentTypeReaderT { + public: + UInt32Reader() : ContentTypeReaderT(typeof()) {} + + Uint Read(ContentReader& input, Uint& existingInstance) override { + return input.ReadUInt32(); + } + }; + + class UInt64Reader : public ContentTypeReaderT { + public: + UInt64Reader() : ContentTypeReaderT(typeof()) {} + + Ulong Read(ContentReader& input, Ulong& existingInstance) override { + return input.ReadUInt64(); + } + }; + + class Vector2Reader : public ContentTypeReaderT { + public: + Vector2Reader() : ContentTypeReaderT(typeof()) {} + + Vector2 Read(ContentReader& input, Vector2& existingInstance) override { + return input.ReadVector2(); + } + }; + + class Vector3Reader : public ContentTypeReaderT { + public: + Vector3Reader() : ContentTypeReaderT(typeof()) {} + + Vector3 Read(ContentReader& input, Vector3& existingInstance) override { + return input.ReadVector3(); + } + }; + + class Vector4Reader : public ContentTypeReaderT { + public: + Vector4Reader() : ContentTypeReaderT(typeof()) {} + + Vector4 Read(ContentReader& input, Vector4& existingInstance) override { + return input.ReadVector4(); + } + }; +} + +#endif \ No newline at end of file diff --git a/framework/content/lzx/decoder.cpp b/framework/content/lzx/decoder.cpp new file mode 100644 index 0000000..4639276 --- /dev/null +++ b/framework/content/lzx/decoder.cpp @@ -0,0 +1,5 @@ +#include "decoder.hpp" + +namespace xna { + +} \ No newline at end of file diff --git a/framework/content/lzx/decoder.hpp b/framework/content/lzx/decoder.hpp new file mode 100644 index 0000000..5c44679 --- /dev/null +++ b/framework/content/lzx/decoder.hpp @@ -0,0 +1,787 @@ +#ifndef XNA_CONTENT_LZX_LZXDECODE_HPP +#define XNA_CONTENT_LZX_LZXDECODE_HPP + +#include "../../default.hpp" +#include "../../csharp/stream.hpp" +#include + +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 PRETREE_table; + std::vector PRETREE_len; + std::vector MAINTREE_table; + std::vector MAINTREE_len; + std::vector LENGTH_table; + std::vector LENGTH_len; + std::vector ALIGNED_table; + std::vector ALIGNED_len; + + // NEEDED MEMBERS + // CAB actualsize + // CAB window + // CAB window_size + // CAB window_posn + Uint actual_size{ 0 }; + std::vector window; + Uint window_size{ 0 }; + Uint window_posn{ 0 }; + }; + + class BitBuffer { + public: + BitBuffer(sptr const& stream) : byteStream(stream) { + InitBitStream(); + } + + constexpr void InitBitStream() { + buffer = 0; + bitsleft = 0; + } + + void EnsureBits(Byte bits) { + while (bitsleft < bits) { + const auto lo = static_cast(byteStream->ReadByte()); + const auto hi = static_cast(byteStream->ReadByte()); + //int amount2shift = sizeofstatic_cast(*8 - 16 - bitsleft; + buffer |= static_cast(((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 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(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(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(j); + j += static_cast(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(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((1 << LzxConstants::PRETREE_TABLEBITS) + (LzxConstants::PRETREE_MAXSYMBOLS << 1)); + m_state.PRETREE_len = std::vector(LzxConstants::PRETREE_MAXSYMBOLS + LzxConstants::LENTABLE_SAFETY); + m_state.MAINTREE_table = std::vector((1 << LzxConstants::MAINTREE_TABLEBITS) + (LzxConstants::MAINTREE_MAXSYMBOLS << 1)); + m_state.MAINTREE_len = std::vector(LzxConstants::MAINTREE_MAXSYMBOLS + LzxConstants::LENTABLE_SAFETY); + m_state.LENGTH_table = std::vector((1 << LzxConstants::LENGTH_TABLEBITS) + (LzxConstants::LENGTH_MAXSYMBOLS << 1)); + m_state.LENGTH_len = std::vector(LzxConstants::LENGTH_MAXSYMBOLS + LzxConstants::LENTABLE_SAFETY); + m_state.ALIGNED_table = std::vector((1 << LzxConstants::ALIGNED_TABLEBITS) + (LzxConstants::ALIGNED_MAXSYMBOLS << 1)); + m_state.ALIGNED_len = std::vector(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& inData, Int inLen, sptr& 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((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(bitbuf.ReadBits(3)); + i = bitbuf.ReadBits(16); + j = bitbuf.ReadBits(8); + m_state.block_remaining = m_state.block_length = static_cast((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(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(inData->ReadByte()); + ml = static_cast(inData->ReadByte()); + mh = static_cast(inData->ReadByte()); + hi = static_cast(inData->ReadByte()); + R0 = static_cast(lo | ml << 8 | mh << 16 | hi << 24); + lo = static_cast(inData->ReadByte()); + ml = static_cast(inData->ReadByte()); + mh = static_cast(inData->ReadByte()); + hi = static_cast(inData->ReadByte()); + R1 = static_cast(lo | ml << 8 | mh << 16 | hi << 24); + lo = static_cast(inData->ReadByte()); + ml = static_cast(inData->ReadByte()); + mh = static_cast(inData->ReadByte()); + hi = static_cast(inData->ReadByte()); + R2 = static_cast(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(m_state.block_remaining)) > 0 && togo > 0) + { + if (this_run > togo) + this_run = togo; + + togo -= this_run; + m_state.block_remaining -= static_cast(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(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(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(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(bitbuf.ReadBits(static_cast(extra))); + match_offset = static_cast(position_base[match_offset]) - 2 + verbatim_bits; + } + else + { + match_offset = 1; + } + + /* update repeated offset LRU queue */ + R2 = R1; R1 = R0; R0 = static_cast(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(match_offset); + } + else /* match_offset == 2 */ + { + match_offset = (int)R2; + R2 = R0; R0 = static_cast(match_offset); + } + + rundest = (int)window_posn; + this_run -= match_length; + + /* copy any wrapped around source data */ + if (static_cast(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(copy_length); + while (copy_length-- > 0) window[rundest++] = window[runsrc++]; + runsrc = 0; + } + } + window_posn += static_cast(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(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(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(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(position_base[match_offset]) - 2; + if (extra > 3) + { + /* verbatim and aligned bits */ + extra -= 3; + verbatim_bits = static_cast(bitbuf.ReadBits(static_cast(extra))); + match_offset += (verbatim_bits << 3); + aligned_bits = static_cast(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(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(bitbuf.ReadBits(static_cast(extra))); + match_offset += verbatim_bits; + } + else /* extra == 0 */ + { + /* ??? */ + match_offset = 1; + } + + /* update repeated offset LRU queue */ + R2 = R1; R1 = R0; R0 = static_cast(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(match_offset); + } + else /* match_offset == 2 */ + { + match_offset = (int)R2; + R2 = R0; R0 = static_cast(match_offset); + } + + rundest = (int)window_posn; + this_run -= match_length; + + /* copy any wrapped around source data */ + if (static_cast(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(copy_length); + while (copy_length-- > 0) window[rundest++] = window[runsrc++]; + runsrc = 0; + } + } + window_posn += static_cast(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 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(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(window_posn); + + if (start_window_pos == 0) + start_window_pos = static_cast(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(m_state.intel_curpos); + + m_state.intel_curpos = static_cast(curpos) + outLen; + + while (outData->Position() < dataend) + { + if (outData->ReadByte() != 0xE8) { + curpos++; + continue; + } + } + } + + return -1; + } + + return 0; + } + + public: + inline static std::vector position_base; + inline static std::vector extra_bits; + + private: + LzxState m_state; + + Int MakeDecodeTable(Uint nsyms, Uint nbits, std::vector& length, std::vector& 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(1 << static_cast(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(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(next_symbol++); + } + /* follow the path and select either left or right for next bit */ + leaf = static_cast(table[leaf] << 1); + if (((pos >> static_cast(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& 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(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(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(z); + } + else + { + z = lens[x] - z; if (z < 0) z += 17; + lens[x++] = static_cast(z); + } + } + } + + Uint ReadHuffSym(std::vector& table, std::vector& lengths, Uint nsyms, Uint nbits, BitBuffer& bitbuf) { + Uint i = 0; + Uint j = 0; + + bitbuf.EnsureBits(16); + + if ((i = table[bitbuf.PeekBits(static_cast(nbits))]) >= nsyms) + { + j = static_cast(1 << static_cast((sizeof(Uint) * 8) - nbits)); + do + { + j >>= 1; i <<= 1; i |= (bitbuf.GetBuffer() & j) != 0 ? static_cast(1) : 0; + if (j == 0) return 0; // TODO throw proper exception + } while ((i = table[i]) >= nsyms); + } + j = lengths[i]; + bitbuf.RemoveBits(static_cast(j)); + + return i; + } + }; +} + +#endif \ No newline at end of file diff --git a/framework/content/lzx/decoderstream.cpp b/framework/content/lzx/decoderstream.cpp new file mode 100644 index 0000000..b9276f9 --- /dev/null +++ b/framework/content/lzx/decoderstream.cpp @@ -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& 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 const& buffer, Int offset, Int count, xna_error_ptr_arg) + { + } + void LzxDecoderStream::WriteByte(Byte value, xna_error_ptr_arg) + { + } +} \ No newline at end of file diff --git a/framework/content/lzx/decoderstream.hpp b/framework/content/lzx/decoderstream.hpp new file mode 100644 index 0000000..882a5bf --- /dev/null +++ b/framework/content/lzx/decoderstream.hpp @@ -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& input, Int decompressedSize, Int compressedSize) { + dec = New(16); + Decompress(input, decompressedSize, compressedSize); + } + + private: + void Decompress(sptr& 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(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(stream->ReadByte()); + frame_size = (hi << 8) | lo; + hi = static_cast(stream->ReadByte()); + lo = static_cast(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(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 dec = nullptr; + sptrdecompressedStream = 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& 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 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 \ No newline at end of file diff --git a/framework/content/manager.hpp b/framework/content/manager.hpp index 7dfe009..a1a6ff7 100644 --- a/framework/content/manager.hpp +++ b/framework/content/manager.hpp @@ -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 #include #include -#include -#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 const& services) : + _rootDirectory(rootDirectory){ + _services = services; + }; + + static sptr 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 - sptr 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(ptr); + auto obj2 = ReadAsset(assetName); - return obj1; - } - - const auto obj2 = ReadAsset(assetName); return obj2; - } + } - public: + protected: template - sptr 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(); } sptr OpenStream(String const& assetName) { String filePath = _rootDirectory + "\\" + assetName + contentExtension; - const auto stream = New(filePath); + const auto stream = New(filePath, FileMode::Open); + //const auto stream = New(filePath); return reinterpret_pointer_cast(stream); } private: - String _rootDirectory; - std::filesystem::path _path; - std::map> _loadedAssets; + String _rootDirectory; + std::vector byteBuffer; + inline const static String contentExtension = ".xnb"; + inline static sptr _services = nullptr; }; } diff --git a/framework/content/reader.cpp b/framework/content/reader.cpp index c229138..69cded6 100644 --- a/framework/content/reader.cpp +++ b/framework/content/reader.cpp @@ -1,9 +1,173 @@ #include "reader.hpp" #include "manager.hpp" +#include "lzx/decoderstream.hpp" +#include "typereadermanager.hpp" +#include "manager.hpp" namespace xna { - sptr ContentReader::Create(ContentManager* contentManager, Stream& input, String const& assetName) + sptr ContentReader::Create(ContentManager* contentManager, sptr& input, String const& assetName) { - return sptr(); + Int graphicsProfile = 0; + input = ContentReader::PrepareStream(input, assetName, graphicsProfile); + return std::shared_ptr(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 ContentReader::ReadByteBuffer(size_t size, xna_error_ptr_arg) + { + std::vector& buffer = _contentManager->byteBuffer; + + if (buffer.empty() || buffer.size() < size) + { + buffer = std::vector(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(); + } + } + + return buffer; + } + + sptr ContentReader::PrepareStream(sptr& 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(input, compressedTodo, decompressedTodo); + + return reinterpret_pointer_cast(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; + } } diff --git a/framework/content/reader.hpp b/framework/content/reader.hpp index 7d00001..f953d5f 100644 --- a/framework/content/reader.hpp +++ b/framework/content/reader.hpp @@ -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 namespace xna { - class ContentReader { + class ContentReader : public BinaryReader, public std::enable_shared_from_this { public: - static sptr Create(ContentManager* contentManager, Stream& input, String const& assetName); + static sptr Create(ContentManager* contentManager, sptr& input, String const& assetName); + + template + T ReadAsset(); + + template + T ReadObject(); + + template + T ReadObject(T existingInstance); + + template + T ReadObject(ContentTypeReader& typeReader); + + template + T ReadObject(ContentTypeReader& typeReader, T existingInstance); + + Vector2 ReadVector2(); + Vector3 ReadVector3(); + Vector4 ReadVector4(); + Matrix ReadMatrix(); + Quaternion ReadQuaternion(); + Color ReadColor(); + float ReadSingle(); + double ReadDouble(); + + std::vector ReadByteBuffer(size_t size, xna_error_nullarg); private: - //ContentReader(ContentManager* contentManager, Stream& inut) + ContentReader(ContentManager* contentManager, sptr& input, String const& assetName, Int graphicsProfile) + : BinaryReader(input), _contentManager(contentManager), _assetName(assetName) {} + + static sptr PrepareStream(sptr& input, String const& assetName, Int& graphicsProfile); + + Int ReadHeader(); + + template + T ReadObjectInternal(std::any& existingInstance, xna_error_nullarg); + + template + T ReadObjectInternal(ContentTypeReader& typeReader, std::any& existingInstance, xna_error_nullarg); + + template + T InvokeReader(ContentTypeReader& reader, std::any& existingInstance, xna_error_nullarg); + + private: + ContentManager* _contentManager = nullptr; + String _assetName; + std::vector> 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 + 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(*reader, existingInstance, err); + } + + template + inline T ContentReader::InvokeReader(ContentTypeReader& reader, std::any& existingInstance, xna_error_ptr_arg) + { + auto contentTypeReader = reinterpret_cast*>(&reader); + T objB; + + if (contentTypeReader) { + auto existingInstance1 = existingInstance.has_value() ? std::any_cast(existingInstance) : T(); + objB = contentTypeReader->Read(*this, existingInstance1); + return objB; + } + + return T(); + } + + template + inline T ContentReader::ReadAsset() + { + const auto sharedResourceCount = ReadHeader(); + auto obj = ReadObject(); + return obj; + } + + template + inline T ContentReader::ReadObject() + { + auto a = std::any(); + return ReadObjectInternal(a); + } + + template + inline T ContentReader::ReadObject(T existingInstance) + { + return ReadObjectInternal(std::any(existingInstance)); + } + + template + inline T ContentReader::ReadObject(ContentTypeReader& typeReader) + { + auto obj = std::any(); + return ReadObjectInternal(typeReader, obj); + } + + template + inline T ContentReader::ReadObject(ContentTypeReader& typeReader, T existingInstance) + { + return ReadObjectInternal(typeReader, std::any(existingInstance)); + } + + template + inline T ContentReader::ReadObjectInternal(ContentTypeReader& typeReader, std::any& existingInstance, xna_error_ptr_arg) + { + return typeReader.TargetIsValueType + ? InvokeReader(typeReader, existingInstance, err) + : ReadObjectInternal(existingInstance, err); + } } #endif \ No newline at end of file diff --git a/framework/content/typereadermanager.cpp b/framework/content/typereadermanager.cpp new file mode 100644 index 0000000..488f5da --- /dev/null +++ b/framework/content/typereadermanager.cpp @@ -0,0 +1,148 @@ +#include "typereadermanager.hpp" +#include "reader.hpp" +#include "defaultreaders.hpp" + +namespace xna { + std::vector ContentTypeReaderManager::ReadTypeManifest(Int typeCount, sptr& contentReader, xna_error_ptr_arg) + { + initMaps(); + + auto contentTypeReaderArray = std::vector(typeCount); + std::vector 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(); + } + + contentTypeReaderArray[index] = typeReader; + + if (!newTypeReaders.empty()) { + auto manager = std::shared_ptr(new ContentTypeReaderManager(contentReader)); + + for (size_t i = 0; i < newTypeReaders.size(); ++i) { + auto& contentTypeReader = newTypeReaders[i]; + contentTypeReader->Initialize(manager); + } + } + } + + return contentTypeReaderArray; + } + + sptr ContentTypeReaderManager::GetTypeReader(sptr const& targetType, sptr& contentReader, xna_error_ptr_arg) + { + if (!targetType) { + xna_error_apply(err, XnaErrorCode::ARGUMENT_IS_NULL); + return nullptr; + } + + sptr 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) { + initMaps(); + } + + sptr ContentTypeReaderManager::GetTypeReader(String const& readerTypeName, sptr& contentReader, std::vector& newTypeReaders, xna_error_ptr_arg) + { + sptr 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, sptr& reader, xna_error_ptr_arg) + { + sptr 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, sptr& 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>& 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(); + auto contentTypeReader = reinterpret_pointer_cast(typeReader); + + //targetTypeToReader.insert({ typeReader->TargetType(), contentTypeReader}); + //readerTypeToReader.insert({ typeReader->GetType(), contentTypeReader}); + targetTypeToReader.insert({ typeof(), contentTypeReader}); + readerTypeToReader.insert({ typeof(), contentTypeReader}); + } + } +} \ No newline at end of file diff --git a/framework/content/typereadermanager.hpp b/framework/content/typereadermanager.hpp new file mode 100644 index 0000000..3da2683 --- /dev/null +++ b/framework/content/typereadermanager.hpp @@ -0,0 +1,153 @@ +#ifndef XNA_CONTENT_TYPEREADER_HPP +#define XNA_CONTENT_TYPEREADER_HPP + +#include "../csharp/type.hpp" +#include "../default.hpp" +#include +#include +#include + +namespace xna { + //-------------------------------------------------------// + // ContentTypeReader // + //-------------------------------------------------------// + class ContentTypeReader { + public: + virtual Int TypeVersion() { return 0; } + virtual bool CanDeserializeIntoExistingObject() { return false; } + virtual void Initialize(sptr const& manager) {} + + sptr TargetType() { return _targetType; } + virtual std::any Read(ContentReader& input, std::any& existingInstance) = 0; + + protected: + ContentTypeReader(sptr const& targetType) : _targetType(targetType) + {} + + public: + bool TargetIsValueType{ false }; + + private: + sptr _targetType = nullptr; + }; + + template + class ContentTypeReaderT : public ContentTypeReader { + protected: + ContentTypeReaderT(sptr 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(*)(); + + static sptr CreateInstance(sptr 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 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(); + + ContentTypeReaderActivador(); + ContentTypeReaderActivador(ContentTypeReaderActivador&&); + ContentTypeReaderActivador(ContentTypeReaderActivador&); + }; + + using PContentTypeReader = sptr; + using PType = sptr; + + //-------------------------------------------------------// + // ContentTypeReaderManager // + //-------------------------------------------------------// + class ContentTypeReaderManager { + public: + static std::vector ReadTypeManifest(Int typeCount, sptr& contentReader, xna_error_nullarg); + static sptr GetTypeReader(sptr const& targetType, sptr& contentReader, xna_error_nullarg); + + inline sptr GetTypeReader(sptr const& targetType, xna_error_nullarg) { + return ContentTypeReaderManager::GetTypeReader(targetType, this->contentReader, err); + } + + inline static bool ContainsTypeReader(sptr const& targetType) { + return ContentTypeReaderManager::targetTypeToReader.contains(targetType); + } + + private: + ContentTypeReaderManager(sptr& contentReader); + static sptr GetTypeReader(String const& readerTypeName, sptr& contentReader, std::vector& newTypeReaders, xna_error_nullarg); + static bool InstantiateTypeReader(String const& readerTypeName, sptr& contentReader, sptr& reader, xna_error_nullarg); + static void AddTypeReader(String const& readerTypeName, sptr& contentReader, sptr& reader, xna_error_nullarg); + static void RollbackAddReaders(std::vector>& newTypeReaders); + + static void RollbackAddReader(std::map& dictionary, sptr& reader) { + std::map>::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& dictionary, sptr& reader) { + std::map>::iterator it; + + for (it = dictionary.begin(); it != dictionary.end(); it++) { + if (it->second == reader) { + dictionary.erase(it->first); + it = dictionary.begin(); + } + } + } + + + private: + sptr contentReader = nullptr; + + inline static auto nameToReader = std::map(); + inline static auto targetTypeToReader = std::map(); + inline static auto readerTypeToReader = std::map(); + + static void initMaps(); + }; +} + +#endif \ No newline at end of file diff --git a/framework/csharp/binary.cpp b/framework/csharp/binary.cpp index 20adc25..b419b2a 100644 --- a/framework/csharp/binary.cpp +++ b/framework/csharp/binary.cpp @@ -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 numArray; - byteCount = stream->Read(charBytes, 0, count1); + byteCount = stream->Read(charBytes, 0, static_cast(count1), err); numArray = charBytes; if (byteCount == 0) - return count - charCount; + return static_cast(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(charBytes.data()); - const auto result = std::string((data + num), (data + num) + byteCount); + auto pChars = reinterpret_cast(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(pChars); - charCount -= static_cast(chars); - index += static_cast(chars); + const auto chars = static_cast(result.size()); + + charCount -= chars; + index += chars; } - return count - charCount; + return static_cast(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(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(num3) & static_cast(SbyteMaxValue)) << num2; + num2 += 7; + + if ((static_cast(num3) & 128) == 0) + return num1; + } + + xna_error_apply(err, XnaErrorCode::INVALID_OPERATION); + return -1; + } + + Int BinaryReader::Read(std::vector& 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& buffer, size_t index, size_t count, xna_error_ptr_arg) + { + auto data = reinterpret_cast(buffer.data()); + return InternalReadChars(data, buffer.size(), index, count, err); + } + std::vector BinaryReader::ReadBytes(size_t count, xna_error_ptr_arg) + { + std::vector result(count); + Int numRead = 0; + + do { + const auto n = stream->Read(result, static_cast(numRead), static_cast(count), err); + + if (n == 0) + break; + + numRead += n; + count -= n; + } while (count > 0); + + if (numRead != result.size()) { + std::vector copy(numRead); + Buffer::BlockCopy(result.data(), 0, copy.data(), 0, numRead); + result = copy; + } + + return result; + } } \ No newline at end of file diff --git a/framework/csharp/binary.hpp b/framework/csharp/binary.hpp index a8ad428..1c9cea3 100644 --- a/framework/csharp/binary.hpp +++ b/framework/csharp/binary.hpp @@ -7,7 +7,7 @@ namespace xna { class BinaryReader { public: - BinaryReader(Stream* const& input) { + BinaryReader(sptr const& input) { stream = input; buffer = std::vector(bufferLength); } @@ -28,18 +28,15 @@ namespace xna { double ReadDouble(xna_error_nullarg); std::string ReadString(xna_error_nullarg); - Int Read(std::vector& buffer, size_t index, size_t count, xna_error_nullarg) { - return -1; - } + Int Read(std::vector& buffer, size_t index, size_t count, xna_error_nullarg); + Int Read(std::vector& buffer, size_t index, size_t count, xna_error_nullarg); - std::vector ReadBytes(size_t count, xna_error_nullarg) { - return std::vector(); - } + std::vector ReadBytes(size_t count, xna_error_nullarg); private: static constexpr int maxCharBytesSize = 128; static constexpr int bufferLength = 16; - Stream* stream = nullptr; + sptr stream = nullptr; std::vector charBytes; std::vector singleChar; std::vector 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(num3) & static_cast(SbyteMaxValue)) << num2; - num2 += 7; - - if ((static_cast(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 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 = nullptr; private: std::vector _buffer; diff --git a/framework/csharp/buffer.hpp b/framework/csharp/buffer.hpp index 6c5775f..9810c1f 100644 --- a/framework/csharp/buffer.hpp +++ b/framework/csharp/buffer.hpp @@ -8,14 +8,14 @@ namespace xna { class Buffer { public: template - 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 + 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; diff --git a/framework/csharp/object.cpp b/framework/csharp/object.cpp new file mode 100644 index 0000000..6b61c37 --- /dev/null +++ b/framework/csharp/object.cpp @@ -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; + } +} \ No newline at end of file diff --git a/framework/csharp/object.hpp b/framework/csharp/object.hpp new file mode 100644 index 0000000..6fedc8c --- /dev/null +++ b/framework/csharp/object.hpp @@ -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 \ No newline at end of file diff --git a/framework/csharp/service.hpp b/framework/csharp/service.hpp new file mode 100644 index 0000000..b7a9cb8 --- /dev/null +++ b/framework/csharp/service.hpp @@ -0,0 +1,15 @@ +#ifndef XNA_CSHARP_SERVICE_HPP +#define XNA_CSHARP_SERVICE_HPP + +#include "../default.hpp" +#include "type.hpp" +#include + +namespace xna { + class IServiceProvider { + public: + virtual std::any GetService(Type& serviceType) = 0; + }; +} + +#endif \ No newline at end of file diff --git a/framework/csharp/stream.cpp b/framework/csharp/stream.cpp index 67089dc..39277df 100644 --- a/framework/csharp/stream.cpp +++ b/framework/csharp/stream.cpp @@ -165,7 +165,7 @@ namespace xna { return -1; } - if (_closed) + if (_closed || _truncated) return 0; auto _buff = reinterpret_cast(buffer); @@ -184,7 +184,7 @@ namespace xna { } Int FileStream::ReadByte(xna_error_ptr_arg){ - if (_closed) + if (_closed || _truncated) return 0; char c = 0; diff --git a/framework/csharp/stream.hpp b/framework/csharp/stream.hpp index 4b3fad6..d41b8df 100644 --- a/framework/csharp/stream.hpp +++ b/framework/csharp/stream.hpp @@ -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& buffer, Int offset, Int count, xna_error_nullarg) = 0; @@ -47,13 +49,17 @@ namespace xna { _buffer = std::vector(); } - 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& 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 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& 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 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& 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 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& 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 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) diff --git a/framework/csharp/type.cpp b/framework/csharp/type.cpp new file mode 100644 index 0000000..28e0123 --- /dev/null +++ b/framework/csharp/type.cpp @@ -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; + } +} \ No newline at end of file diff --git a/framework/csharp/type.hpp b/framework/csharp/type.hpp new file mode 100644 index 0000000..a2ff3cd --- /dev/null +++ b/framework/csharp/type.hpp @@ -0,0 +1,88 @@ +#ifndef XNA_CSHARP_TYPE_HPP +#define XNA_CSHARP_TYPE_HPP + +#include "../default.hpp" +#include "object.hpp" +#include +#include +#include + +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 + friend sptr typeof(); + + public: + inline static auto NameOfRegisteredTypes = std::map>(); + + private: + String fullName; + bool isClass{ false }; + bool isEnum{ false }; + bool isValueType{ false }; + bool isPrimitive{ false }; + }; + + template + inline sptr typeof() { + if (std::is_arithmetic::value) { + auto primitiveType = New(); + primitiveType->fullName = typeid(T).name(); + primitiveType->isPrimitive = true; + primitiveType->isValueType = true; + return primitiveType; + } + + if (std::is_enum::value) { + auto enumType = New(); + enumType->fullName = typeid(T).name(); + enumType->isValueType = true; + enumType->isEnum = true; + return enumType; + } + + if (std::is_class::value) { + auto classType = New(); + classType->fullName = typeid(T).name(); + classType->isClass = true; + + return classType; + } + + return nullptr; + } + + template + inline sptr typeof(T const* object) { + return typeof(); + } + + template + inline sptr typeof(T const& object) { + return typeof(); + } +} + +#endif \ No newline at end of file diff --git a/framework/enums.hpp b/framework/enums.hpp index 0e2fa74..62ba815 100644 --- a/framework/enums.hpp +++ b/framework/enums.hpp @@ -165,6 +165,15 @@ namespace xna { Stretched = 2 }; + enum class FileMode { + CreateNew, + Create, + Append, + Open, + OpenOrCreate, + Truncate + }; + enum class FillMode { WireFrame, diff --git a/framework/forward.hpp b/framework/forward.hpp index 4df05f8..3085424 100644 --- a/framework/forward.hpp +++ b/framework/forward.hpp @@ -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; } #endif \ No newline at end of file diff --git a/framework/game/game.hpp b/framework/game/game.hpp index 936335a..3656808 100644 --- a/framework/game/game.hpp +++ b/framework/game/game.hpp @@ -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 Window() = 0; virtual sptr GetGraphicsDevice() = 0; virtual sptr Components() = 0; + virtual sptr Services() = 0; + virtual sptr Content() = 0; protected: virtual void Draw(GameTime const& gameTime) = 0; diff --git a/framework/game/servicecontainer.cpp b/framework/game/servicecontainer.cpp new file mode 100644 index 0000000..20c2689 --- /dev/null +++ b/framework/game/servicecontainer.cpp @@ -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(); + } +} \ No newline at end of file diff --git a/framework/game/servicecontainer.hpp b/framework/game/servicecontainer.hpp index 2ce68aa..69255d0 100644 --- a/framework/game/servicecontainer.hpp +++ b/framework/game/servicecontainer.hpp @@ -2,12 +2,19 @@ #define XNA_GAME_SERVICECONTAINER_HPP #include "../default.hpp" +#include "../csharp/service.hpp" +#include 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 services; }; } diff --git a/framework/graphics/gresource.hpp b/framework/graphics/gresource.hpp index 74381fe..59e441d 100644 --- a/framework/graphics/gresource.hpp +++ b/framework/graphics/gresource.hpp @@ -6,11 +6,11 @@ namespace xna { class GraphicsResource { public: - GraphicsResource(GraphicsDevice* device) : m_device(device){} + GraphicsResource(sptr const& device) : m_device(device){} virtual ~GraphicsResource(){} - virtual bool Bind(GraphicsDevice* device) { + virtual bool Bind(sptr const& device) { if (device == m_device) return false; @@ -20,7 +20,7 @@ namespace xna { } protected: - GraphicsDevice* m_device = nullptr; + sptr m_device = nullptr; }; } diff --git a/framework/graphics/rendertarget.hpp b/framework/graphics/rendertarget.hpp index 1e8ca1c..90361db 100644 --- a/framework/graphics/rendertarget.hpp +++ b/framework/graphics/rendertarget.hpp @@ -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; }; } diff --git a/framework/graphics/texture.hpp b/framework/graphics/texture.hpp index bbf9bba..ec7dbf4 100644 --- a/framework/graphics/texture.hpp +++ b/framework/graphics/texture.hpp @@ -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; }; } diff --git a/framework/helpers.hpp b/framework/helpers.hpp index aba54eb..afc396c 100644 --- a/framework/helpers.hpp +++ b/framework/helpers.hpp @@ -2,6 +2,7 @@ #define XNA_HELPERS_HPP #include +#include 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 + static constexpr void XnaHHashCombine(std::size_t& seed, const T& v) { + std::hash hasher; + seed ^= hasher(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2); + } } #endif \ No newline at end of file diff --git a/framework/platform/adapter-dx.hpp b/framework/platform/adapter-dx.hpp index 0e32cbc..099fc78 100644 --- a/framework/platform/adapter-dx.hpp +++ b/framework/platform/adapter-dx.hpp @@ -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: diff --git a/framework/platform/blendstate-dx.hpp b/framework/platform/blendstate-dx.hpp index fcd3e99..1941daa 100644 --- a/framework/platform/blendstate-dx.hpp +++ b/framework/platform/blendstate-dx.hpp @@ -21,7 +21,7 @@ namespace xna { class BlendState : public IBlendState, public GraphicsResource { public: - BlendState(GraphicsDevice* device) : GraphicsResource(device) {}; + BlendState(sptr const& device) : GraphicsResource(device) {}; virtual ~BlendState() override { if (dxBlendState) { diff --git a/framework/platform/content-readers/texture2Dreader-dx.hpp b/framework/platform/content-readers/texture2Dreader-dx.hpp new file mode 100644 index 0000000..7bff5bc --- /dev/null +++ b/framework/platform/content-readers/texture2Dreader-dx.hpp @@ -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 { + public: + Texture2DReader() : ContentTypeReaderT(typeof()){} + + PTexture2D Read(ContentReader& input, PTexture2D& existingInstance) override{ + const auto format = static_cast(input.ReadInt32()); + const auto width = input.ReadInt32(); + const auto height = input.ReadInt32(); + const auto mipMaps = input.ReadInt32(); + + auto a_device = ContentManager::Services()->GetService(*typeof()); + sptr device = nullptr; + + if(a_device.has_value()) + device = std::any_cast>(a_device); + + auto texture2D = New(device, width, height, mipMaps, format); + + for (size_t level = 0; level < mipMaps; ++level) { + auto elementCount = input.ReadInt32(); + std::vector data = input.ReadByteBuffer(elementCount); + + texture2D->SetData(static_cast(level), nullptr, data, 0, elementCount); + } + + return texture2D; + } + }; +} + +#endif \ No newline at end of file diff --git a/framework/platform/depthstencilstate-dx.hpp b/framework/platform/depthstencilstate-dx.hpp index 4126faa..76b16e4 100644 --- a/framework/platform/depthstencilstate-dx.hpp +++ b/framework/platform/depthstencilstate-dx.hpp @@ -8,7 +8,7 @@ namespace xna { class DepthStencilState : public IDepthStencilState, public GraphicsResource { public: - DepthStencilState(GraphicsDevice* device) : GraphicsResource(device) { + DepthStencilState(sptr const& device) : GraphicsResource(device) { dxDescription = defaultDesc(); } diff --git a/framework/platform/device-dx.cpp b/framework/platform/device-dx.cpp index 86bd563..d068eb0 100644 --- a/framework/platform/device-dx.cpp +++ b/framework/platform/device-dx.cpp @@ -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(this); + _swapChain = New(_this); _swapChain->Initialize(); hr = _factory->MakeWindowAssociation(gameWindow.WindowHandle(), DXGI_MWA_NO_ALT_ENTER); if (FAILED(hr)) return false; - _renderTarget2D = New(); - if (!_renderTarget2D->Initialize(*this)) return false; + _renderTarget2D = New(_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; diff --git a/framework/platform/device-dx.hpp b/framework/platform/device-dx.hpp index 07e013a..c9a6a4e 100644 --- a/framework/platform/device-dx.hpp +++ b/framework/platform/device-dx.hpp @@ -14,7 +14,7 @@ #include "presentparameters-dx.hpp" namespace xna { - class GraphicsDevice : public IGraphicsDevice { + class GraphicsDevice : public IGraphicsDevice, public std::enable_shared_from_this { public: GraphicsDevice(); GraphicsDevice(GraphicsDeviceInformation const& info); diff --git a/framework/platform/dxheaders.hpp b/framework/platform/dxheaders.hpp index a2fc464..c08436a 100644 --- a/framework/platform/dxheaders.hpp +++ b/framework/platform/dxheaders.hpp @@ -1,9 +1,33 @@ +//DirectX #include "dxgi.h" #include "d3d11.h" #include #include +//HSLS #include +//DirectXTK #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//Windows #define NOMINMAX #include #include diff --git a/framework/platform/game-dx.cpp b/framework/platform/game-dx.cpp index 3121df2..de5ff30 100644 --- a/framework/platform/game-dx.cpp +++ b/framework/platform/game-dx.cpp @@ -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 namespace xna { Game::Game() { + services = New(); + _contentManager = New("", services); + _gameWindow = New(); - _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(); } - 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(); @@ -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); - } + } } diff --git a/framework/platform/game-dx.hpp b/framework/platform/game-dx.hpp index b1b42c0..66ffef0 100644 --- a/framework/platform/game-dx.hpp +++ b/framework/platform/game-dx.hpp @@ -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 Window() override { - return _gameWindow; - } - - virtual sptr GetGraphicsDevice() override { - return _graphicsDevice; - } - - sptr Components() override { - return _gameComponents; - } - - constexpr void EnableGameComponents(bool value) { - _enabledGameComponents = value; - } + inline sptr Window() override { return _gameWindow; } + inline sptr GetGraphicsDevice() override { return graphicsDevice; } + inline sptr Components() override { return _gameComponents; } + inline sptr Services() override { return services; } + inline sptr 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{ nullptr }; + sptr graphicsDevice = nullptr; - protected: - sptr _gameWindow{ nullptr }; - sptr _audioEngine = nullptr; - - GameTime _currentGameTime{}; - DX::StepTimer _stepTimer; - - private: - int startLoop(); - void step(); + protected: + sptr services = nullptr; + + private: sptr _gameComponents = nullptr; + sptr _gameWindow{ nullptr }; + sptr _audioEngine = nullptr; + sptr _contentManager; std::vector> _drawableGameComponents; size_t _drawableGameComponentsCount{ 0 }; - bool _enabledGameComponents{ false }; + bool _enabledGameComponents{ false }; + GameTime _currentGameTime{}; + DX::StepTimer _stepTimer{}; + + int startLoop(); + void step(); }; } diff --git a/framework/platform/gdevicemanager-dx.cpp b/framework/platform/gdevicemanager-dx.cpp index d656c69..8226f68 100644 --- a/framework/platform/gdevicemanager-dx.cpp +++ b/framework/platform/gdevicemanager-dx.cpp @@ -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; } diff --git a/framework/platform/init-dx.cpp b/framework/platform/init-dx.cpp new file mode 100644 index 0000000..077d162 --- /dev/null +++ b/framework/platform/init-dx.cpp @@ -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("ObjecReader"); + insertRegisteredReader("BooleanReader"); + insertRegisteredReader("ByteReader"); + insertRegisteredReader("CharReader"); + insertRegisteredReader("ColorReader"); + insertRegisteredReader("DoubleReader"); + insertRegisteredReader("Int16Reader"); + insertRegisteredReader("Int32Reader"); + insertRegisteredReader("Int64Reader"); + insertRegisteredReader("MatrixReader"); + insertRegisteredReader("PointReader"); + insertRegisteredReader("QuaternionReader"); + insertRegisteredReader("RectangleReader"); + insertRegisteredReader("SByteReader"); + insertRegisteredReader("SingleReader"); + insertRegisteredReader("TimeSpanReader"); + insertRegisteredReader("UInt16Reader"); + insertRegisteredReader("UInt32Reader"); + insertRegisteredReader("UInt64Reader"); + insertRegisteredReader("Vector2Reader"); + insertRegisteredReader("Vector3Reader"); + insertRegisteredReader("Vector4Reader"); + insertRegisteredReader("Texture2DReader"); + } + + void InitPlatform::InitActivadors() + { + insertActivadorReader(); + insertActivadorReader(); + insertActivadorReader(); + insertActivadorReader(); + insertActivadorReader(); + insertActivadorReader(); + insertActivadorReader(); + insertActivadorReader(); + insertActivadorReader(); + insertActivadorReader(); + insertActivadorReader(); + insertActivadorReader(); + insertActivadorReader(); + insertActivadorReader(); + insertActivadorReader(); + insertActivadorReader(); + insertActivadorReader(); + insertActivadorReader(); + insertActivadorReader(); + insertActivadorReader(); + insertActivadorReader(); + insertActivadorReader(); + insertActivadorReader(); + } +} \ No newline at end of file diff --git a/framework/platform/init-dx.hpp b/framework/platform/init-dx.hpp new file mode 100644 index 0000000..29cacb7 --- /dev/null +++ b/framework/platform/init-dx.hpp @@ -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 + static void insertRegisteredReader(String const& readerName) { + const auto reader = typeof(); + Type::NameOfRegisteredTypes.insert({ "xna::" + readerName, reader }); + Type::NameOfRegisteredTypes.insert({ "Microsoft.Xna.Framework.Content." + readerName, reader }); + } + + template + static void insertActivadorReader() { + ContentTypeReaderActivador::SetActivador(typeof(), []() -> sptr { + auto obj = New (); + return reinterpret_pointer_cast(obj); + }); + } + }; +} + +#endif \ No newline at end of file diff --git a/framework/platform/rasterizerstate-dx.hpp b/framework/platform/rasterizerstate-dx.hpp index 33f088e..3b46701 100644 --- a/framework/platform/rasterizerstate-dx.hpp +++ b/framework/platform/rasterizerstate-dx.hpp @@ -8,7 +8,7 @@ namespace xna { class RasterizerState : public IRasterizerState, public GraphicsResource { public: - RasterizerState(GraphicsDevice* device) : GraphicsResource(device){} + RasterizerState(sptr const& device) : GraphicsResource(device){} virtual ~RasterizerState() override { if (dxRasterizerState) { diff --git a/framework/platform/rendertarget-dx.cpp b/framework/platform/rendertarget-dx.cpp index 564a58d..32820ac 100644 --- a/framework/platform/rendertarget-dx.cpp +++ b/framework/platform/rendertarget-dx.cpp @@ -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; } diff --git a/framework/platform/rendertarget-dx.hpp b/framework/platform/rendertarget-dx.hpp index 81493c3..0ed0667 100644 --- a/framework/platform/rendertarget-dx.hpp +++ b/framework/platform/rendertarget-dx.hpp @@ -9,6 +9,8 @@ namespace xna { class RenderTarget2D : public IRenderTarget2D, public Texture2D { public: + RenderTarget2D(sptr 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; diff --git a/framework/platform/samplerstate-dx.hpp b/framework/platform/samplerstate-dx.hpp index 9e93f38..2b2dfe7 100644 --- a/framework/platform/samplerstate-dx.hpp +++ b/framework/platform/samplerstate-dx.hpp @@ -8,7 +8,7 @@ namespace xna { class SamplerState : public ISamplerState, public GraphicsResource { public: - SamplerState(GraphicsDevice* device) : GraphicsResource(device) { + SamplerState(sptr const& device) : GraphicsResource(device) { _description.MaxAnisotropy = 4; } diff --git a/framework/platform/shader-dx.hpp b/framework/platform/shader-dx.hpp index c0842e0..e7938f7 100644 --- a/framework/platform/shader-dx.hpp +++ b/framework/platform/shader-dx.hpp @@ -8,7 +8,7 @@ namespace xna { class Shader : public IShader, public GraphicsResource { public: - Shader(GraphicsDevice* device) : GraphicsResource(device){} + Shader(sptr 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 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 const& device) : Shader(device) {} virtual ~PixelShader() override { if (_pixelShader) { diff --git a/framework/platform/spritebatch-dx.cpp b/framework/platform/spritebatch-dx.cpp index f4d0fbb..0345150 100644 --- a/framework/platform/spritebatch-dx.cpp +++ b/framework/platform/spritebatch-dx.cpp @@ -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(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(effects); _dxspriteBatch->Draw( - texture._textureView, + texture.dxShaderResource, _destinationRect, sourceRectangle ? &_sourceRect : nullptr, _color, diff --git a/framework/platform/swapchain-dx.hpp b/framework/platform/swapchain-dx.hpp index 9a12b0b..a229f76 100644 --- a/framework/platform/swapchain-dx.hpp +++ b/framework/platform/swapchain-dx.hpp @@ -9,7 +9,7 @@ namespace xna { class SwapChain : public ISwapChain, public GraphicsResource { public: - SwapChain(GraphicsDevice* device): GraphicsResource(device){} + SwapChain(sptr const& device): GraphicsResource(device){} virtual ~SwapChain() override { if (dxSwapChain) { diff --git a/framework/platform/texture-dx.cpp b/framework/platform/texture-dx.cpp index 63757e1..ff3c847 100644 --- a/framework/platform/texture-dx.cpp +++ b/framework/platform/texture-dx.cpp @@ -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::FromStream(GraphicsDevice& device, String const& fileName, xna_error_ptr_arg) { - auto texture2d = New(); + auto _this = device.shared_from_this(); + auto texture2d = New(_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 const& device, size_t width, size_t height) : GraphicsResource(device) { + setDefaultDesc(); + dxDescription.Width = static_cast(width); + dxDescription.Height = static_cast(height); + } + + Texture2D::Texture2D(sptr const& device) : GraphicsResource(device) { + setDefaultDesc(); + } + + Texture2D::Texture2D(sptr const& device, size_t width, size_t height, size_t mipMap, SurfaceFormat format) : GraphicsResource(device) + { + setDefaultDesc(); + dxDescription.Width = static_cast(width); + dxDescription.Height = static_cast(height); + dxDescription.MipLevels = static_cast(mipMap); + dxDescription.Format = GraphicsAdapter::ConvertSurfaceToDXGIFORMAT(format); + } + + void Texture2D::SetData(std::vector 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 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 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 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 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 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 finalData(elementCount); + auto finalDataIndex = 0; + + for (size_t i = startIndex; i < elementCount; ++i) { + finalData[finalDataIndex] = static_cast(data[i]); + ++finalDataIndex; + } + + internalSetData(finalData.data(), err); + } + + sptr Texture2D::FromMemory(GraphicsDevice& device, std::vector const& data, xna_error_ptr_arg) + { + auto _this = device.shared_from_this(); + auto texture2d = New(_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); + } } \ No newline at end of file diff --git a/framework/platform/texture-dx.hpp b/framework/platform/texture-dx.hpp index dbd5b16..8bfb433 100644 --- a/framework/platform/texture-dx.hpp +++ b/framework/platform/texture-dx.hpp @@ -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 const& device); + Texture2D(sptr const& device, size_t width, size_t height); + Texture2D(sptr 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 FromStream(GraphicsDevice& device, String const& fileName, xna_error_nullarg); + constexpr Rectangle Bounds() const override { + return { 0, 0, static_cast(dxDescription.Width), static_cast(dxDescription.Height) }; + } + + bool Initialize(xna_error_nullarg) override; + + void SetData(std::vector const& data, size_t startIndex = 0, size_t elementCount = 0, xna_error_nullarg); + void SetData(std::vector const& data, size_t startIndex = 0, size_t elementCount = 0, xna_error_nullarg); + void SetData(std::vector const& data, size_t startIndex = 0, size_t elementCount = 0, xna_error_nullarg); + + void SetData(Int level, Rectangle* rect, std::vector const& data, size_t startIndex, size_t elementCount, xna_error_nullarg); + + static sptr FromStream(GraphicsDevice& device, String const& fileName, xna_error_nullarg); + static sptr FromMemory(GraphicsDevice& device, std::vector 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 \ No newline at end of file diff --git a/framework/types.hpp b/framework/types.hpp index c37d8a0..c647ee4 100644 --- a/framework/types.hpp +++ b/framework/types.hpp @@ -44,6 +44,7 @@ namespace xna { constexpr double DoubleMinValue = std::numeric_limits::min(); using String = std::string; + using WString = std::wstring; template using sptr = std::shared_ptr; diff --git a/framework/xna.cpp b/framework/xna.cpp index 615e12d..86e6e80 100644 --- a/framework/xna.cpp +++ b/framework/xna.cpp @@ -9,28 +9,26 @@ using namespace xna; namespace xna { class Game1 : public Game { public: - Game1() { + Game1() : Game() { auto _game = reinterpret_cast(this); graphics = New(_game); - graphics->PreferredBackBufferWidth(1280); - graphics->PreferredBackBufferHeight(720); - contentManager = New("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(), device); + Game::Initialize(); } void LoadContent() override { - spriteBatch = New(*_graphicsDevice); + spriteBatch = New(*graphicsDevice); - XnaErrorCode err; - texture = Texture2D::FromStream(*_graphicsDevice, "D:\\sprite.jpg", &err); + texture = Content()->Load("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 graphics = nullptr; sptr spriteBatch = nullptr; - sptr texture = nullptr; //200x200 - Vector2 position{}; - std::vector points; - MouseState currentState{}; - MouseState oldState{}; - float vel = 1; - int var = 0; - sptr 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; diff --git a/framework/xna.h b/framework/xna.h index e81e780..1a82cc9 100644 --- a/framework/xna.h +++ b/framework/xna.h @@ -24,5 +24,7 @@ #include "Windows.h" #include #include "content/manager.hpp" +#include "platform/init-dx.hpp" +#include "csharp/type.hpp" // TODO: Reference additional headers your program requires here. diff --git a/framework/xnaerror.hpp b/framework/xnaerror.hpp index bd0a11b..dcdf274 100644 --- a/framework/xnaerror.hpp +++ b/framework/xnaerror.hpp @@ -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