2024-04-28 20:19:37 -03:00
|
|
|
#ifndef XNA_CONTENT_READER_HPP
|
|
|
|
#define XNA_CONTENT_READER_HPP
|
|
|
|
|
2024-06-03 21:55:09 -03:00
|
|
|
#include "../common/color.hpp"
|
|
|
|
#include "../common/numerics.hpp"
|
|
|
|
#include "../csharp/binary.hpp"
|
|
|
|
#include "../csharp/type.hpp"
|
|
|
|
#include "../default.hpp"
|
2024-05-03 11:49:01 -03:00
|
|
|
#include "typereadermanager.hpp"
|
|
|
|
#include <any>
|
2024-04-28 20:19:37 -03:00
|
|
|
|
|
|
|
namespace xna {
|
2024-06-03 10:13:59 -03:00
|
|
|
//A worker object that implements most of ContentManager.Load.
|
2024-05-06 09:58:40 -03:00
|
|
|
class ContentReader : public BinaryReader, public std::enable_shared_from_this<ContentReader> {
|
2024-04-28 20:19:37 -03:00
|
|
|
public:
|
2024-06-03 10:13:59 -03:00
|
|
|
static sptr<ContentReader> Create(sptr<ContentManager> const& contentManager, sptr<Stream>& input, String const& assetName);
|
2024-05-06 09:58:40 -03:00
|
|
|
|
2024-06-03 10:13:59 -03:00
|
|
|
// Reads a single object from the current stream.
|
2024-05-03 11:49:01 -03:00
|
|
|
template <typename T>
|
2024-06-01 20:33:35 -03:00
|
|
|
auto ReadObject();
|
2024-05-03 11:49:01 -03:00
|
|
|
|
2024-06-03 10:13:59 -03:00
|
|
|
// Reads a single object from the current stream.
|
2024-05-03 11:49:01 -03:00
|
|
|
template <typename T>
|
2024-07-13 22:50:52 -03:00
|
|
|
auto ReadObject(T& existingInstance);
|
2024-05-03 11:49:01 -03:00
|
|
|
|
2024-06-03 10:13:59 -03:00
|
|
|
// Reads a single object from the current stream.
|
2024-05-07 17:27:04 -03:00
|
|
|
template <typename T>
|
2024-06-01 20:33:35 -03:00
|
|
|
auto ReadObject(ContentTypeReader& typeReader);
|
2024-05-07 17:27:04 -03:00
|
|
|
|
2024-06-03 10:13:59 -03:00
|
|
|
// Reads a single object from the current stream.
|
2024-05-07 17:27:04 -03:00
|
|
|
template <typename T>
|
2024-07-13 22:50:52 -03:00
|
|
|
auto ReadObject(ContentTypeReader& typeReader, T& existingInstance);
|
2024-05-07 17:27:04 -03:00
|
|
|
|
2024-06-03 10:13:59 -03:00
|
|
|
//Reads a Vector2 value from the current stream.
|
2024-05-03 11:49:01 -03:00
|
|
|
Vector2 ReadVector2();
|
2024-06-03 10:13:59 -03:00
|
|
|
//Reads a Vector3 value from the current stream.
|
2024-05-03 11:49:01 -03:00
|
|
|
Vector3 ReadVector3();
|
2024-06-03 10:13:59 -03:00
|
|
|
//Reads a Vector4 value from the current stream.
|
2024-05-03 11:49:01 -03:00
|
|
|
Vector4 ReadVector4();
|
2024-06-03 10:13:59 -03:00
|
|
|
//Reads a Matrix value from the currently open stream.
|
2024-05-03 11:49:01 -03:00
|
|
|
Matrix ReadMatrix();
|
2024-06-03 10:13:59 -03:00
|
|
|
//Reads a Quaternion value from the current stream.
|
2024-05-03 11:49:01 -03:00
|
|
|
Quaternion ReadQuaternion();
|
2024-06-03 10:13:59 -03:00
|
|
|
//Reads a Color value from the currently open stream.
|
2024-05-03 11:49:01 -03:00
|
|
|
Color ReadColor();
|
2024-06-03 10:13:59 -03:00
|
|
|
//Reads a float value from the currently open stream.
|
2024-07-13 22:50:52 -03:00
|
|
|
float ReadSingle() override;
|
2024-06-03 10:13:59 -03:00
|
|
|
//Reads a double value from the currently open stream.
|
2024-07-13 22:50:52 -03:00
|
|
|
double ReadDouble() override;
|
2024-05-05 15:50:17 -03:00
|
|
|
|
2024-06-03 10:13:59 -03:00
|
|
|
//Gets the name of the asset currently being read by this ContentReader.
|
|
|
|
constexpr String AssetName() const {
|
|
|
|
return _assetName;
|
|
|
|
}
|
|
|
|
|
|
|
|
//Gets the ContentManager associated with the ContentReader.
|
|
|
|
sptr<xna::ContentManager> ContentManager() const;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Internal methods
|
|
|
|
//
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
auto ReadAsset();
|
|
|
|
|
2024-06-03 11:05:10 -03:00
|
|
|
std::vector<Byte> ReadByteBuffer(size_t size);
|
2024-04-28 20:19:37 -03:00
|
|
|
|
|
|
|
private:
|
2024-06-03 10:13:59 -03:00
|
|
|
ContentReader(sptr<xna::ContentManager> const& contentManager, sptr<Stream>& input, String const& assetName, Int graphicsProfile)
|
2024-05-06 09:58:40 -03:00
|
|
|
: BinaryReader(input), _contentManager(contentManager), _assetName(assetName) {}
|
2024-05-01 19:09:43 -03:00
|
|
|
|
2024-05-03 11:49:01 -03:00
|
|
|
static sptr<Stream> PrepareStream(sptr<Stream>& input, String const& assetName, Int& graphicsProfile);
|
2024-05-01 19:09:43 -03:00
|
|
|
|
|
|
|
Int ReadHeader();
|
|
|
|
|
2024-05-03 11:49:01 -03:00
|
|
|
template <typename T>
|
2024-06-03 11:05:10 -03:00
|
|
|
auto ReadObjectInternal(std::any& existingInstance);
|
2024-05-07 17:27:04 -03:00
|
|
|
|
|
|
|
template <typename T>
|
2024-07-13 22:50:52 -03:00
|
|
|
auto ReadObjectInternal(ContentTypeReader& typeReader, Object& existingInstance);
|
2024-05-06 09:58:40 -03:00
|
|
|
|
2024-05-03 11:49:01 -03:00
|
|
|
template <typename T>
|
2024-07-13 22:50:52 -03:00
|
|
|
auto InvokeReader(ContentTypeReader& reader, Object& existingInstance);
|
2024-05-03 11:49:01 -03:00
|
|
|
|
2024-05-01 19:09:43 -03:00
|
|
|
private:
|
2024-06-03 10:13:59 -03:00
|
|
|
sptr<xna::ContentManager> _contentManager = nullptr;
|
2024-05-01 19:09:43 -03:00
|
|
|
String _assetName;
|
2024-05-03 11:49:01 -03:00
|
|
|
std::vector<sptr<ContentTypeReader>> typeReaders;
|
|
|
|
Int graphicsProfile{ 0 };
|
2024-06-03 10:13:59 -03:00
|
|
|
std::vector<Byte> byteBuffer;
|
2024-05-06 09:58:40 -03:00
|
|
|
|
|
|
|
static constexpr Ushort XnbVersionProfileMask = 32512;
|
|
|
|
static constexpr Ushort XnbCompressedVersion = 32773;
|
|
|
|
static constexpr Ushort XnbVersion = 5;
|
|
|
|
static constexpr Int XnbVersionProfileShift = 8;
|
2024-07-13 22:50:52 -03:00
|
|
|
static constexpr Char PlatformLabel = 'w';
|
|
|
|
static constexpr Int XnbPrologueSize = 10;
|
|
|
|
static constexpr Int XnbCompressedPrologueSize = 14;
|
2024-04-28 20:19:37 -03:00
|
|
|
};
|
2024-05-03 11:49:01 -03:00
|
|
|
|
|
|
|
template<typename T>
|
2024-07-13 22:50:52 -03:00
|
|
|
inline auto ContentReader::ReadObjectInternal(Object& existingInstance)
|
2024-05-03 11:49:01 -03:00
|
|
|
{
|
|
|
|
const auto num = Read7BitEncodedInt();
|
|
|
|
|
|
|
|
if (num == 0) {
|
2024-06-01 20:45:00 -03:00
|
|
|
XnaHelper::ReturnDefaultOrNull<T>();
|
2024-05-03 11:49:01 -03:00
|
|
|
}
|
2024-05-06 09:58:40 -03:00
|
|
|
|
2024-05-03 11:49:01 -03:00
|
|
|
const auto index = num - 1;
|
|
|
|
|
|
|
|
if (index >= typeReaders.size()) {
|
2024-07-13 22:50:52 -03:00
|
|
|
Exception::Throw(Exception::BAD_XNB);
|
2024-05-30 17:37:40 -03:00
|
|
|
}
|
|
|
|
|
2024-07-13 22:50:52 -03:00
|
|
|
auto& reader = typeReaders[index];
|
2024-06-01 20:33:35 -03:00
|
|
|
|
2024-06-03 11:05:10 -03:00
|
|
|
return InvokeReader<T>(*reader, existingInstance);
|
2024-05-03 11:49:01 -03:00
|
|
|
}
|
2024-05-06 09:58:40 -03:00
|
|
|
|
2024-05-03 11:49:01 -03:00
|
|
|
template<typename T>
|
2024-07-13 22:50:52 -03:00
|
|
|
inline auto ContentReader::InvokeReader(ContentTypeReader& reader, Object& existingInstance)
|
2024-05-03 11:49:01 -03:00
|
|
|
{
|
|
|
|
auto contentTypeReader = reinterpret_cast<ContentTypeReaderT<T>*>(&reader);
|
2024-05-08 10:51:49 -03:00
|
|
|
T objB;
|
2024-05-03 11:49:01 -03:00
|
|
|
|
|
|
|
if (contentTypeReader) {
|
2024-05-08 10:51:49 -03:00
|
|
|
auto existingInstance1 = existingInstance.has_value() ? std::any_cast<T>(existingInstance) : T();
|
|
|
|
objB = contentTypeReader->Read(*this, existingInstance1);
|
2024-05-06 09:58:40 -03:00
|
|
|
return objB;
|
2024-05-03 11:49:01 -03:00
|
|
|
}
|
2024-07-07 16:06:05 -03:00
|
|
|
else {
|
|
|
|
Exception::Throw(Exception::NOT_IMPLEMENTED);
|
|
|
|
}
|
2024-05-03 11:49:01 -03:00
|
|
|
|
2024-06-01 20:45:00 -03:00
|
|
|
return XnaHelper::ReturnDefaultOrNull<T>();
|
2024-05-03 11:49:01 -03:00
|
|
|
}
|
2024-05-06 09:58:40 -03:00
|
|
|
|
|
|
|
template<typename T>
|
2024-06-01 20:33:35 -03:00
|
|
|
inline auto ContentReader::ReadAsset()
|
2024-05-03 11:49:01 -03:00
|
|
|
{
|
|
|
|
const auto sharedResourceCount = ReadHeader();
|
2024-05-06 11:35:27 -03:00
|
|
|
auto obj = ReadObject<T>();
|
2024-05-03 11:49:01 -03:00
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T>
|
2024-06-01 20:33:35 -03:00
|
|
|
inline auto ContentReader::ReadObject()
|
2024-05-03 11:49:01 -03:00
|
|
|
{
|
2024-05-06 09:58:40 -03:00
|
|
|
auto a = std::any();
|
|
|
|
return ReadObjectInternal<T>(a);
|
2024-05-03 11:49:01 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T>
|
2024-07-13 22:50:52 -03:00
|
|
|
inline auto ContentReader::ReadObject(T& existingInstance)
|
2024-05-03 11:49:01 -03:00
|
|
|
{
|
2024-07-13 22:50:52 -03:00
|
|
|
return ReadObjectInternal<T>(Object(existingInstance));
|
2024-05-06 09:58:40 -03:00
|
|
|
}
|
2024-05-07 17:27:04 -03:00
|
|
|
|
|
|
|
template<typename T>
|
2024-06-01 20:33:35 -03:00
|
|
|
inline auto ContentReader::ReadObject(ContentTypeReader& typeReader)
|
2024-05-07 17:27:04 -03:00
|
|
|
{
|
|
|
|
auto obj = std::any();
|
|
|
|
return ReadObjectInternal<T>(typeReader, obj);
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T>
|
2024-07-13 22:50:52 -03:00
|
|
|
inline auto ContentReader::ReadObject(ContentTypeReader& typeReader, T& existingInstance)
|
2024-05-07 17:27:04 -03:00
|
|
|
{
|
|
|
|
return ReadObjectInternal<T>(typeReader, std::any(existingInstance));
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T>
|
2024-07-13 22:50:52 -03:00
|
|
|
inline auto ContentReader::ReadObjectInternal(ContentTypeReader& typeReader, Object& existingInstance)
|
2024-05-07 17:27:04 -03:00
|
|
|
{
|
2024-07-13 22:50:52 -03:00
|
|
|
if (typeReader.TargetIsValueType)
|
|
|
|
return InvokeReader<T>(typeReader, existingInstance);
|
|
|
|
|
2024-07-16 09:50:53 -03:00
|
|
|
return ReadObjectInternal<T>(existingInstance);
|
2024-05-07 17:27:04 -03:00
|
|
|
}
|
2024-04-28 20:19:37 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|