Major ResourceLoader rework (using Nz::Result)
This commit is contained in:
@@ -20,34 +20,18 @@ namespace Nz
|
||||
|
||||
static bool IsSupported(const std::string_view& extension)
|
||||
{
|
||||
return (extension == "dds");
|
||||
return (extension == ".dds");
|
||||
}
|
||||
|
||||
static Ternary Check(Stream& stream, const ImageParams& parameters)
|
||||
static Result<std::shared_ptr<Image>, ResourceLoadingError> Load(Stream& stream, const ImageParams& parameters)
|
||||
{
|
||||
bool skip;
|
||||
if (parameters.custom.GetBooleanParameter("SkipBuiltinDDSLoader", &skip) && skip)
|
||||
return Ternary::False;
|
||||
|
||||
ByteStream byteStream(&stream);
|
||||
byteStream.SetDataEndianness(Endianness::LittleEndian);
|
||||
|
||||
UInt32 magic;
|
||||
byteStream >> magic;
|
||||
|
||||
return (magic == DDS_Magic) ? Ternary::True : Ternary::False;
|
||||
}
|
||||
|
||||
static std::shared_ptr<Image> Load(Stream& stream, const ImageParams& parameters)
|
||||
{
|
||||
NazaraUnused(parameters);
|
||||
|
||||
ByteStream byteStream(&stream);
|
||||
byteStream.SetDataEndianness(Endianness::LittleEndian);
|
||||
|
||||
UInt32 magic;
|
||||
byteStream >> magic;
|
||||
NazaraAssert(magic == DDS_Magic, "Invalid DDS file"); // The Check function should make sure this doesn't happen
|
||||
if (magic != DDS_Magic)
|
||||
return Nz::Err(ResourceLoadingError::Unrecognized);
|
||||
|
||||
DDSHeader header;
|
||||
byteStream >> header;
|
||||
@@ -81,12 +65,12 @@ namespace Nz
|
||||
// First, identify the type
|
||||
ImageType type;
|
||||
if (!IdentifyImageType(header, headerDX10, &type))
|
||||
return nullptr;
|
||||
return Nz::Err(ResourceLoadingError::Unsupported);
|
||||
|
||||
// Then the format
|
||||
PixelFormat format;
|
||||
if (!IdentifyPixelFormat(header, headerDX10, &format))
|
||||
return nullptr;
|
||||
return Nz::Err(ResourceLoadingError::Unsupported);
|
||||
|
||||
std::shared_ptr<Image> image = std::make_shared<Image>(type, format, width, height, depth, levelCount);
|
||||
|
||||
@@ -100,7 +84,7 @@ namespace Nz
|
||||
if (byteStream.Read(ptr, byteCount) != byteCount)
|
||||
{
|
||||
NazaraError("Failed to read level #" + NumberToString(i));
|
||||
return nullptr;
|
||||
return Nz::Err(ResourceLoadingError::DecodingError);
|
||||
}
|
||||
|
||||
if (width > 1)
|
||||
@@ -271,8 +255,15 @@ namespace Nz
|
||||
{
|
||||
ImageLoader::Entry loaderEntry;
|
||||
loaderEntry.extensionSupport = DDSLoader::IsSupported;
|
||||
loaderEntry.streamChecker = DDSLoader::Check;
|
||||
loaderEntry.streamLoader = DDSLoader::Load;
|
||||
loaderEntry.parameterFilter = [](const ImageParams& parameters)
|
||||
{
|
||||
bool skip;
|
||||
if (parameters.custom.GetBooleanParameter("SkipBuiltinDDSLoader", &skip) && skip)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
return loaderEntry;
|
||||
}
|
||||
|
||||
@@ -15,8 +15,9 @@
|
||||
#include <Nazara/Utility/Font.hpp>
|
||||
#include <Nazara/Utility/FontData.hpp>
|
||||
#include <Nazara/Utility/FontGlyph.hpp>
|
||||
#include <frozen/string.h>
|
||||
#include <frozen/unordered_set.h>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <Nazara/Utility/Debug.hpp>
|
||||
|
||||
@@ -108,12 +109,6 @@ namespace Nz
|
||||
FT_Done_Face(m_face);
|
||||
}
|
||||
|
||||
bool Check()
|
||||
{
|
||||
// Test d'ouverture (http://www.freetype.org/freetype2/docs/reference/ft2-base_interface.html#FT_Open_Face)
|
||||
return FT_Open_Face(s_freetypeLibrary, &m_args, -1, nullptr) == 0;
|
||||
}
|
||||
|
||||
bool ExtractGlyph(unsigned int characterSize, char32_t character, TextStyleFlags style, float outlineThickness, FontGlyph* dst) override
|
||||
{
|
||||
#ifdef NAZARA_DEBUG
|
||||
@@ -383,32 +378,14 @@ namespace Nz
|
||||
mutable unsigned int m_characterSize;
|
||||
};
|
||||
|
||||
constexpr auto s_supportedExtensions = frozen::make_unordered_set<frozen::string>({ ".afm", ".bdf", ".cff", ".cid", ".dfont", ".fnt", ".fon", ".otf", ".pfa", ".pfb", ".pfm", ".pfr", ".sfnt", ".ttc", ".tte", ".ttf" });
|
||||
|
||||
bool IsFreetypeSupported(const std::string_view& extension)
|
||||
{
|
||||
///FIXME: Je suppose qu'il en manque quelques unes..
|
||||
static std::set<std::string_view> supportedExtensions = {
|
||||
"afm", "bdf", "cff", "cid", "dfont", "fnt", "fon", "otf", "pfa", "pfb", "pfm", "pfr", "sfnt", "ttc", "tte", "ttf"
|
||||
};
|
||||
|
||||
return supportedExtensions.find(extension) != supportedExtensions.end();
|
||||
return s_supportedExtensions.find(extension) != s_supportedExtensions.end();
|
||||
}
|
||||
|
||||
Ternary CheckFreetype(Stream& stream, const FontParams& parameters)
|
||||
{
|
||||
bool skip;
|
||||
if (parameters.custom.GetBooleanParameter("SkipBuiltinFreeTypeLoader", &skip) && skip)
|
||||
return Ternary::False;
|
||||
|
||||
FreeTypeStream face;
|
||||
face.SetStream(stream);
|
||||
|
||||
if (face.Check())
|
||||
return Ternary::True;
|
||||
else
|
||||
return Ternary::False;
|
||||
}
|
||||
|
||||
std::shared_ptr<Font> LoadFreetypeFile(const std::filesystem::path& filePath, const FontParams& parameters)
|
||||
Result<std::shared_ptr<Font>, ResourceLoadingError> LoadFreetypeFile(const std::filesystem::path& filePath, const FontParams& parameters)
|
||||
{
|
||||
NazaraUnused(parameters);
|
||||
|
||||
@@ -416,23 +393,20 @@ namespace Nz
|
||||
if (!face->SetFile(filePath))
|
||||
{
|
||||
NazaraError("Failed to open file");
|
||||
return nullptr;
|
||||
return Err(ResourceLoadingError::FailedToOpenFile);
|
||||
}
|
||||
|
||||
if (!face->Open())
|
||||
{
|
||||
NazaraError("Failed to open face");
|
||||
return nullptr;
|
||||
}
|
||||
return Err(ResourceLoadingError::Unrecognized);
|
||||
|
||||
std::shared_ptr<Font> font = std::make_shared<Font>();
|
||||
if (!font->Create(std::move(face)))
|
||||
return nullptr;
|
||||
return Err(ResourceLoadingError::Internal);
|
||||
|
||||
return font;
|
||||
}
|
||||
|
||||
std::shared_ptr<Font> LoadFreetypeMemory(const void* data, std::size_t size, const FontParams& parameters)
|
||||
Result<std::shared_ptr<Font>, ResourceLoadingError> LoadFreetypeMemory(const void* data, std::size_t size, const FontParams& parameters)
|
||||
{
|
||||
NazaraUnused(parameters);
|
||||
|
||||
@@ -440,34 +414,28 @@ namespace Nz
|
||||
face->SetMemory(data, size);
|
||||
|
||||
if (!face->Open())
|
||||
{
|
||||
NazaraError("Failed to open face");
|
||||
return nullptr;
|
||||
}
|
||||
return Err(ResourceLoadingError::Unrecognized);
|
||||
|
||||
std::shared_ptr<Font> font = std::make_shared<Font>();
|
||||
if (!font->Create(std::move(face)))
|
||||
return nullptr;
|
||||
return Err(ResourceLoadingError::Internal);
|
||||
|
||||
return font;
|
||||
}
|
||||
|
||||
std::shared_ptr<Font> LoadFreetypeStream(Stream& stream, const FontParams& parameters)
|
||||
Result<std::shared_ptr<Font>, ResourceLoadingError> LoadFreetypeStream(Stream& stream, const FontParams& parameters)
|
||||
{
|
||||
NazaraUnused(parameters);
|
||||
|
||||
std::unique_ptr<FreeTypeStream> face(new FreeTypeStream);
|
||||
std::unique_ptr<FreeTypeStream> face = std::make_unique<FreeTypeStream>();
|
||||
face->SetStream(stream);
|
||||
|
||||
if (!face->Open())
|
||||
{
|
||||
NazaraError("Failed to open face");
|
||||
return nullptr;
|
||||
}
|
||||
return Err(ResourceLoadingError::Unrecognized);
|
||||
|
||||
std::shared_ptr<Font> font = std::make_shared<Font>();
|
||||
if (!font->Create(std::move(face)))
|
||||
return nullptr;
|
||||
return Err(ResourceLoadingError::Internal);
|
||||
|
||||
return font;
|
||||
}
|
||||
@@ -492,14 +460,21 @@ namespace Nz
|
||||
{
|
||||
NazaraAssert(s_freetypeLibraryOwner, "FreeType has not been initialized");
|
||||
|
||||
FontLoader::Entry entry;
|
||||
entry.extensionSupport = IsFreetypeSupported;
|
||||
entry.fileLoader = LoadFreetypeFile;
|
||||
entry.memoryLoader = LoadFreetypeMemory;
|
||||
entry.streamChecker = CheckFreetype;
|
||||
entry.streamLoader = LoadFreetypeStream;
|
||||
FontLoader::Entry loader;
|
||||
loader.extensionSupport = IsFreetypeSupported;
|
||||
loader.fileLoader = LoadFreetypeFile;
|
||||
loader.memoryLoader = LoadFreetypeMemory;
|
||||
loader.streamLoader = LoadFreetypeStream;
|
||||
loader.parameterFilter = [](const FontParams& parameters)
|
||||
{
|
||||
bool skip;
|
||||
if (parameters.custom.GetBooleanParameter("SkipBuiltinFreeTypeLoader", &skip) && skip)
|
||||
return false;
|
||||
|
||||
return entry;
|
||||
return true;
|
||||
};
|
||||
|
||||
return loader;
|
||||
}
|
||||
|
||||
void UninitializeFreeType()
|
||||
|
||||
@@ -262,13 +262,10 @@ namespace Nz
|
||||
return m_currentFrame;
|
||||
}
|
||||
|
||||
bool Open()
|
||||
Result<void, ResourceLoadingError> Open()
|
||||
{
|
||||
if (!Check())
|
||||
{
|
||||
NazaraError("stream has invalid GIF header");
|
||||
return false;
|
||||
}
|
||||
return Err(ResourceLoadingError::Unrecognized);
|
||||
|
||||
m_byteStream >> m_header.width >> m_header.height;
|
||||
m_byteStream >> m_header.flags >> m_header.backgroundPaletteIndex >> m_header.ratio;
|
||||
@@ -322,13 +319,13 @@ namespace Nz
|
||||
if (left + width > m_header.width)
|
||||
{
|
||||
NazaraError("corrupt gif (out of range)");
|
||||
return false;
|
||||
return Err(ResourceLoadingError::DecodingError);
|
||||
}
|
||||
|
||||
if (top + height > m_header.height)
|
||||
{
|
||||
NazaraError("corrupt gif (out of range)");
|
||||
return false;
|
||||
return Err(ResourceLoadingError::DecodingError);
|
||||
}
|
||||
|
||||
if (left != 0 || top != 0 || width < m_header.width || height < m_header.height)
|
||||
@@ -343,7 +340,7 @@ namespace Nz
|
||||
else if (!hasGlobalColorTable)
|
||||
{
|
||||
NazaraError("corrupt gif (no color table for image #" + std::to_string(m_frames.size() - 1) + ")");
|
||||
return false;
|
||||
return Err(ResourceLoadingError::DecodingError);
|
||||
}
|
||||
|
||||
UInt8 minimumCodeSize;
|
||||
@@ -351,7 +348,7 @@ namespace Nz
|
||||
if (minimumCodeSize > 12)
|
||||
{
|
||||
NazaraError("unexpected LZW Minimum Code Size (" + std::to_string(minimumCodeSize) + ")");
|
||||
return false;
|
||||
return Err(ResourceLoadingError::DecodingError);
|
||||
}
|
||||
|
||||
SkipUntilTerminationBlock();
|
||||
@@ -382,7 +379,7 @@ namespace Nz
|
||||
if (blockSize != 4)
|
||||
{
|
||||
NazaraError("corrupt gif (invalid block size for graphic control extension)");
|
||||
return false;
|
||||
return Err(ResourceLoadingError::DecodingError);
|
||||
}
|
||||
|
||||
nextFrame.disposalMethod = (flags & 0b0001'1100) >> 2;
|
||||
@@ -423,7 +420,7 @@ namespace Nz
|
||||
|
||||
default:
|
||||
NazaraError("corrupt gif (unknown tag 0x" + NumberToString(tag, 16) + ")");
|
||||
return false;
|
||||
return Err(ResourceLoadingError::DecodingError);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -445,7 +442,7 @@ namespace Nz
|
||||
|
||||
m_currentFrame = 0;
|
||||
|
||||
return true;
|
||||
return Ok();
|
||||
}
|
||||
|
||||
bool SetFile(const std::filesystem::path& filePath)
|
||||
@@ -709,55 +706,35 @@ namespace Nz
|
||||
|
||||
bool CheckGIFExtension(const std::string_view& extension)
|
||||
{
|
||||
return extension == "gif";
|
||||
return extension == ".gif";
|
||||
}
|
||||
|
||||
Ternary CheckGIF(Stream& stream, const ImageStreamParams& parameters)
|
||||
{
|
||||
bool skip;
|
||||
if (parameters.custom.GetBooleanParameter("SkipBuiltinGIFLoader", &skip) && skip)
|
||||
return Ternary::False;
|
||||
|
||||
GIFImageStream gif;
|
||||
gif.SetStream(stream);
|
||||
|
||||
if (gif.Check())
|
||||
return Ternary::True;
|
||||
else
|
||||
return Ternary::False;
|
||||
}
|
||||
|
||||
std::shared_ptr<ImageStream> LoadGIFFile(const std::filesystem::path& filePath, const ImageStreamParams& /*parameters*/)
|
||||
Result<std::shared_ptr<ImageStream>, ResourceLoadingError> LoadGIFFile(const std::filesystem::path& filePath, const ImageStreamParams& /*parameters*/)
|
||||
{
|
||||
std::shared_ptr<GIFImageStream> gifStream = std::make_shared<GIFImageStream>();
|
||||
gifStream->SetFile(filePath);
|
||||
if (!gifStream->SetFile(filePath))
|
||||
return Err(ResourceLoadingError::FailedToOpenFile);
|
||||
|
||||
if (!gifStream->Open())
|
||||
return {};
|
||||
|
||||
return gifStream;
|
||||
Result status = gifStream->Open();
|
||||
return status.Map([&] { return std::move(gifStream); });
|
||||
}
|
||||
|
||||
std::shared_ptr<ImageStream> LoadGIFMemory(const void* ptr, std::size_t size, const ImageStreamParams& /*parameters*/)
|
||||
Result<std::shared_ptr<ImageStream>, ResourceLoadingError> LoadGIFMemory(const void* ptr, std::size_t size, const ImageStreamParams& /*parameters*/)
|
||||
{
|
||||
std::shared_ptr<GIFImageStream> gifStream = std::make_shared<GIFImageStream>();
|
||||
gifStream->SetMemory(ptr, size);
|
||||
|
||||
if (!gifStream->Open())
|
||||
return {};
|
||||
|
||||
return gifStream;
|
||||
Result status = gifStream->Open();
|
||||
return status.Map([&] { return std::move(gifStream); });
|
||||
}
|
||||
|
||||
std::shared_ptr<ImageStream> LoadGIFStream(Stream& stream, const ImageStreamParams& /*parameters*/)
|
||||
Result<std::shared_ptr<ImageStream>, ResourceLoadingError> LoadGIFStream(Stream& stream, const ImageStreamParams& /*parameters*/)
|
||||
{
|
||||
std::shared_ptr<GIFImageStream> gifStream = std::make_shared<GIFImageStream>();
|
||||
gifStream->SetStream(stream);
|
||||
|
||||
if (!gifStream->Open())
|
||||
return {};
|
||||
|
||||
return gifStream;
|
||||
Result status = gifStream->Open();
|
||||
return status.Map([&] { return std::move(gifStream); });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -767,10 +744,17 @@ namespace Nz
|
||||
{
|
||||
ImageStreamLoader::Entry loaderEntry;
|
||||
loaderEntry.extensionSupport = CheckGIFExtension;
|
||||
loaderEntry.streamChecker = CheckGIF;
|
||||
loaderEntry.fileLoader = LoadGIFFile;
|
||||
loaderEntry.memoryLoader = LoadGIFMemory;
|
||||
loaderEntry.streamLoader = LoadGIFStream;
|
||||
loaderEntry.parameterFilter = [](const ImageStreamParams& parameters)
|
||||
{
|
||||
bool skip;
|
||||
if (parameters.custom.GetBooleanParameter("SkipBuiltinGIFLoader", &skip) && skip)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
return loaderEntry;
|
||||
}
|
||||
|
||||
@@ -23,38 +23,25 @@ namespace Nz
|
||||
{
|
||||
bool IsMD2Supported(const std::string_view& extension)
|
||||
{
|
||||
return (extension == "md2");
|
||||
return (extension == ".md2");
|
||||
}
|
||||
|
||||
Ternary CheckMD2(Stream& stream, const MeshParams& parameters)
|
||||
{
|
||||
bool skip;
|
||||
if (parameters.custom.GetBooleanParameter("SkipBuiltinMD2Loader", &skip) && skip)
|
||||
return Ternary::False;
|
||||
|
||||
UInt32 magic[2];
|
||||
if (stream.Read(&magic[0], 2*sizeof(UInt32)) == 2*sizeof(UInt32))
|
||||
{
|
||||
#ifdef NAZARA_BIG_ENDIAN
|
||||
SwapBytes(&magic[0], sizeof(UInt32));
|
||||
SwapBytes(&magic[1], sizeof(UInt32));
|
||||
#endif
|
||||
|
||||
if (magic[0] == md2Ident && magic[1] == 8)
|
||||
return Ternary::True;
|
||||
}
|
||||
|
||||
return Ternary::False;
|
||||
}
|
||||
|
||||
std::shared_ptr<Mesh> LoadMD2(Stream& stream, const MeshParams& parameters)
|
||||
Result<std::shared_ptr<Mesh>, ResourceLoadingError> LoadMD2(Stream& stream, const MeshParams& parameters)
|
||||
{
|
||||
MD2_Header header;
|
||||
if (stream.Read(&header, sizeof(MD2_Header)) != sizeof(MD2_Header))
|
||||
{
|
||||
NazaraError("Failed to read header");
|
||||
return nullptr;
|
||||
}
|
||||
return Err(ResourceLoadingError::Unrecognized);
|
||||
|
||||
#ifdef NAZARA_BIG_ENDIAN
|
||||
SwapBytes(&header.indent, sizeof(UInt32));
|
||||
SwapBytes(&header.version, sizeof(UInt32));
|
||||
#endif
|
||||
|
||||
if (header.ident != md2Ident)
|
||||
return Err(ResourceLoadingError::Unrecognized);
|
||||
|
||||
if (header.version != 8)
|
||||
return Err(ResourceLoadingError::Unsupported);
|
||||
|
||||
#ifdef NAZARA_BIG_ENDIAN
|
||||
SwapBytes(&header.skinwidth, sizeof(UInt32));
|
||||
@@ -77,7 +64,7 @@ namespace Nz
|
||||
if (stream.GetSize() < header.offset_end)
|
||||
{
|
||||
NazaraError("Incomplete MD2 file");
|
||||
return nullptr;
|
||||
return Err(ResourceLoadingError::DecodingError);
|
||||
}
|
||||
|
||||
// Since the engine no longer supports keyframe animations, let's make a static mesh
|
||||
@@ -85,7 +72,7 @@ namespace Nz
|
||||
if (!mesh->CreateStatic())
|
||||
{
|
||||
NazaraInternalError("Failed to create mesh");
|
||||
return nullptr;
|
||||
return Err(ResourceLoadingError::Internal);
|
||||
}
|
||||
|
||||
// Extract skins (texture name)
|
||||
@@ -269,8 +256,15 @@ namespace Nz
|
||||
{
|
||||
MeshLoader::Entry loader;
|
||||
loader.extensionSupport = IsMD2Supported;
|
||||
loader.streamChecker = CheckMD2;
|
||||
loader.streamLoader = LoadMD2;
|
||||
loader.parameterFilter = [](const MeshParams& parameters)
|
||||
{
|
||||
bool skip;
|
||||
if (parameters.custom.GetBooleanParameter("SkipBuiltinMD2Loader", &skip) && skip)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
return loader;
|
||||
}
|
||||
|
||||
@@ -14,28 +14,26 @@ namespace Nz
|
||||
{
|
||||
bool IsMD5AnimSupported(const std::string_view& extension)
|
||||
{
|
||||
return (extension == "md5anim");
|
||||
return extension == ".md5anim";
|
||||
}
|
||||
|
||||
Ternary CheckMD5Anim(Stream& stream, const AnimationParams& parameters)
|
||||
Result<std::shared_ptr<Animation>, ResourceLoadingError> LoadMD5Anim(Stream& stream, const AnimationParams& /*parameters*/)
|
||||
{
|
||||
bool skip;
|
||||
if (parameters.custom.GetBooleanParameter("SkipBuiltinMD5AnimLoader", &skip) && skip)
|
||||
return Ternary::False;
|
||||
// TODO: Use parameters
|
||||
|
||||
MD5AnimParser parser(stream);
|
||||
return parser.Check();
|
||||
}
|
||||
|
||||
std::shared_ptr<Animation> LoadMD5Anim(Stream& stream, const AnimationParams& /*parameters*/)
|
||||
{
|
||||
///TODO: Utiliser les paramètres
|
||||
MD5AnimParser parser(stream);
|
||||
UInt64 streamPos = stream.GetCursorPos();
|
||||
|
||||
if (!parser.Check())
|
||||
return Err(ResourceLoadingError::Unrecognized);
|
||||
|
||||
stream.SetCursorPos(streamPos);
|
||||
|
||||
if (!parser.Parse())
|
||||
{
|
||||
NazaraError("MD5Anim parser failed");
|
||||
return nullptr;
|
||||
return Err(ResourceLoadingError::DecodingError);
|
||||
}
|
||||
|
||||
const MD5AnimParser::Frame* frames = parser.GetFrames();
|
||||
@@ -99,8 +97,15 @@ namespace Nz
|
||||
{
|
||||
AnimationLoader::Entry loader;
|
||||
loader.extensionSupport = IsMD5AnimSupported;
|
||||
loader.streamChecker = CheckMD5Anim;
|
||||
loader.streamLoader = LoadMD5Anim;
|
||||
loader.parameterFilter = [](const AnimationParams& parameters)
|
||||
{
|
||||
bool skip;
|
||||
if (parameters.custom.GetBooleanParameter("SkipBuiltinMD5AnimLoader", &skip) && skip)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
return loader;
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace Nz
|
||||
m_stream.EnableTextMode(false);
|
||||
}
|
||||
|
||||
Ternary MD5AnimParser::Check()
|
||||
bool MD5AnimParser::Check()
|
||||
{
|
||||
if (Advance(false))
|
||||
{
|
||||
@@ -37,11 +37,11 @@ namespace Nz
|
||||
if (std::sscanf(&m_currentLine[0], " MD5Version %u", &version) == 1)
|
||||
{
|
||||
if (version == 10)
|
||||
return Ternary::True;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return Ternary::False;
|
||||
return false;
|
||||
}
|
||||
|
||||
UInt32 MD5AnimParser::GetAnimatedComponentCount() const
|
||||
|
||||
@@ -22,26 +22,24 @@ namespace Nz
|
||||
{
|
||||
bool IsMD5MeshSupported(const std::string_view& extension)
|
||||
{
|
||||
return (extension == "md5mesh");
|
||||
return (extension == ".md5mesh");
|
||||
}
|
||||
|
||||
Ternary CheckMD5Mesh(Stream& stream, const MeshParams& parameters)
|
||||
{
|
||||
bool skip;
|
||||
if (parameters.custom.GetBooleanParameter("SkipBuiltinMD5MeshLoader", &skip) && skip)
|
||||
return Ternary::False;
|
||||
|
||||
MD5MeshParser parser(stream);
|
||||
return parser.Check();
|
||||
}
|
||||
|
||||
std::shared_ptr<Mesh> LoadMD5Mesh(Stream& stream, const MeshParams& parameters)
|
||||
Result<std::shared_ptr<Mesh>, ResourceLoadingError> LoadMD5Mesh(Stream& stream, const MeshParams& parameters)
|
||||
{
|
||||
MD5MeshParser parser(stream);
|
||||
|
||||
UInt64 streamPos = stream.GetCursorPos();
|
||||
|
||||
if (!parser.Check())
|
||||
return Err(ResourceLoadingError::Unrecognized);
|
||||
|
||||
stream.SetCursorPos(streamPos);
|
||||
|
||||
if (!parser.Parse())
|
||||
{
|
||||
NazaraError("MD5Mesh parser failed");
|
||||
return nullptr;
|
||||
return Err(ResourceLoadingError::DecodingError);
|
||||
}
|
||||
|
||||
UInt32 maxWeightCount = 4;
|
||||
@@ -253,7 +251,7 @@ namespace Nz
|
||||
if (!mesh->CreateStatic()) // Ne devrait jamais échouer
|
||||
{
|
||||
NazaraInternalError("Failed to create mesh");
|
||||
return nullptr;
|
||||
return Err(ResourceLoadingError::Internal);
|
||||
}
|
||||
|
||||
mesh->SetMaterialCount(meshCount);
|
||||
@@ -360,8 +358,15 @@ namespace Nz
|
||||
{
|
||||
MeshLoader::Entry loader;
|
||||
loader.extensionSupport = IsMD5MeshSupported;
|
||||
loader.streamChecker = CheckMD5Mesh;
|
||||
loader.streamLoader = LoadMD5Mesh;
|
||||
loader.parameterFilter = [](const MeshParams& parameters)
|
||||
{
|
||||
bool skip;
|
||||
if (parameters.custom.GetBooleanParameter("SkipBuiltinMD5MeshLoader", &skip) && skip)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
return loader;
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace Nz
|
||||
m_stream.EnableTextMode(false);
|
||||
}
|
||||
|
||||
Ternary MD5MeshParser::Check()
|
||||
bool MD5MeshParser::Check()
|
||||
{
|
||||
if (Advance(false))
|
||||
{
|
||||
@@ -37,11 +37,11 @@ namespace Nz
|
||||
if (std::sscanf(&m_currentLine[0], " MD5Version %u", &version) == 1)
|
||||
{
|
||||
if (version == 10)
|
||||
return Ternary::True;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return Ternary::False;
|
||||
return false;
|
||||
}
|
||||
|
||||
const MD5MeshParser::Joint* MD5MeshParser::GetJoints() const
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
#include <unordered_map>
|
||||
#include <Nazara/Utility/Debug.hpp>
|
||||
|
||||
///TODO: N'avoir qu'un seul VertexBuffer communs à tous les meshes
|
||||
// TODO: Use only one index buffer / vertex buffer for all submeshes
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
@@ -24,22 +24,7 @@ namespace Nz
|
||||
{
|
||||
bool IsOBJSupported(const std::string_view& extension)
|
||||
{
|
||||
return (extension == "obj");
|
||||
}
|
||||
|
||||
Ternary CheckOBJ(Stream& stream, const MeshParams& parameters)
|
||||
{
|
||||
NazaraUnused(stream);
|
||||
|
||||
bool skip;
|
||||
if (parameters.custom.GetBooleanParameter("SkipBuiltinOBJLoader", &skip) && skip)
|
||||
return Ternary::False;
|
||||
|
||||
OBJParser parser;
|
||||
if (!parser.Check(stream))
|
||||
return Ternary::False;
|
||||
|
||||
return Ternary::Unknown;
|
||||
return (extension == ".obj");
|
||||
}
|
||||
|
||||
bool ParseMTL(Mesh& mesh, const std::filesystem::path& filePath, const std::string* materials, const OBJParser::Mesh* meshes, std::size_t meshCount)
|
||||
@@ -157,17 +142,25 @@ namespace Nz
|
||||
return true;
|
||||
}
|
||||
|
||||
std::shared_ptr<Mesh> LoadOBJ(Stream& stream, const MeshParams& parameters)
|
||||
Result<std::shared_ptr<Mesh>, ResourceLoadingError> LoadOBJ(Stream& stream, const MeshParams& parameters)
|
||||
{
|
||||
long long reservedVertexCount;
|
||||
if (!parameters.custom.GetIntegerParameter("NativeOBJLoader_VertexCount", &reservedVertexCount))
|
||||
reservedVertexCount = 100;
|
||||
|
||||
OBJParser parser;
|
||||
|
||||
UInt64 streamPos = stream.GetCursorPos();
|
||||
|
||||
if (!parser.Check(stream))
|
||||
return Err(ResourceLoadingError::Unrecognized);
|
||||
|
||||
stream.SetCursorPos(streamPos);
|
||||
|
||||
if (!parser.Parse(stream, reservedVertexCount))
|
||||
{
|
||||
NazaraError("OBJ parser failed");
|
||||
return nullptr;
|
||||
return Err(ResourceLoadingError::DecodingError);
|
||||
}
|
||||
|
||||
std::shared_ptr<Mesh> mesh = std::make_shared<Mesh>();
|
||||
@@ -181,8 +174,7 @@ namespace Nz
|
||||
const OBJParser::Mesh* meshes = parser.GetMeshes();
|
||||
std::size_t meshCount = parser.GetMeshCount();
|
||||
|
||||
NazaraAssert(materials != nullptr && positions != nullptr && normals != nullptr &&
|
||||
texCoords != nullptr && meshes != nullptr && meshCount > 0,
|
||||
NazaraAssert(materials != nullptr && positions != nullptr && normals != nullptr && texCoords != nullptr && meshes != nullptr && meshCount > 0,
|
||||
"Invalid OBJParser output");
|
||||
|
||||
// Triangulation temporary vector
|
||||
@@ -365,8 +357,15 @@ namespace Nz
|
||||
{
|
||||
MeshLoader::Entry loader;
|
||||
loader.extensionSupport = IsOBJSupported;
|
||||
loader.streamChecker = CheckOBJ;
|
||||
loader.streamLoader = LoadOBJ;
|
||||
loader.parameterFilter = [](const MeshParams& parameters)
|
||||
{
|
||||
bool skip;
|
||||
if (parameters.custom.GetBooleanParameter("SkipBuiltinOBJLoader", &skip) && skip)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
return loader;
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ namespace Nz
|
||||
|
||||
bool IsOBJSupportedSave(const std::string_view& extension)
|
||||
{
|
||||
return (extension == "obj");
|
||||
return (extension == ".obj");
|
||||
}
|
||||
|
||||
bool SaveOBJToStream(const Mesh& mesh, const std::string& format, Stream& stream, const MeshParams& parameters)
|
||||
|
||||
@@ -42,35 +42,17 @@ namespace Nz
|
||||
|
||||
bool IsPCXSupported(const std::string_view& extension)
|
||||
{
|
||||
return (extension == "pcx");
|
||||
return (extension == ".pcx");
|
||||
}
|
||||
|
||||
Ternary CheckPCX(Stream& stream, const ImageParams& parameters)
|
||||
Result<std::shared_ptr<Image>, ResourceLoadingError> LoadPCX(Stream& stream, const ImageParams& parameters)
|
||||
{
|
||||
bool skip;
|
||||
if (parameters.custom.GetBooleanParameter("SkipBuiltinPCXLoader", &skip) && skip)
|
||||
return Ternary::False;
|
||||
|
||||
UInt8 manufacturer;
|
||||
if (stream.Read(&manufacturer, 1) == 1)
|
||||
{
|
||||
if (manufacturer == 0x0a)
|
||||
return Ternary::True;
|
||||
}
|
||||
|
||||
return Ternary::False;
|
||||
}
|
||||
|
||||
std::shared_ptr<Image> LoadPCX(Stream& stream, const ImageParams& parameters)
|
||||
{
|
||||
NazaraUnused(parameters);
|
||||
|
||||
PCXHeader header;
|
||||
if (stream.Read(&header, sizeof(PCXHeader)) != sizeof(PCXHeader))
|
||||
{
|
||||
NazaraError("Failed to read header");
|
||||
return nullptr;
|
||||
}
|
||||
return Err(ResourceLoadingError::Unrecognized);
|
||||
|
||||
if (header.manufacturer != 0x0a)
|
||||
return Err(ResourceLoadingError::Unrecognized);
|
||||
|
||||
#ifdef NAZARA_BIG_ENDIAN
|
||||
// Les fichiers PCX sont en little endian
|
||||
@@ -95,7 +77,7 @@ namespace Nz
|
||||
if (!image->Create(ImageType::E2D, PixelFormat::RGB8, width, height, 1, (parameters.levelCount > 0) ? parameters.levelCount : 1))
|
||||
{
|
||||
NazaraError("Failed to create image");
|
||||
return nullptr;
|
||||
return Err(ResourceLoadingError::Internal);
|
||||
}
|
||||
|
||||
UInt8* pixels = image->GetPixels();
|
||||
@@ -120,7 +102,7 @@ namespace Nz
|
||||
if (!stream.Read(&rleValue, 1))
|
||||
{
|
||||
NazaraError("Failed to read stream (byte " + NumberToString(stream.GetCursorPos()) + ')');
|
||||
return nullptr;
|
||||
return Err(ResourceLoadingError::DecodingError);
|
||||
}
|
||||
|
||||
if (rleValue < 0xc0)
|
||||
@@ -131,7 +113,7 @@ namespace Nz
|
||||
if (!stream.Read(&rleValue, 1))
|
||||
{
|
||||
NazaraError("Failed to read stream (byte " + NumberToString(stream.GetCursorPos()) + ')');
|
||||
return nullptr;
|
||||
return Err(ResourceLoadingError::DecodingError);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -175,7 +157,7 @@ namespace Nz
|
||||
if (!stream.Read(&rleValue, 1))
|
||||
{
|
||||
NazaraError("Failed to read stream (byte " + NumberToString(stream.GetCursorPos()) + ')');
|
||||
return nullptr;
|
||||
return Err(ResourceLoadingError::DecodingError);
|
||||
}
|
||||
|
||||
if (rleValue < 0xc0)
|
||||
@@ -186,7 +168,7 @@ namespace Nz
|
||||
if (!stream.Read(&rleValue, 1))
|
||||
{
|
||||
NazaraError("Failed to read stream (byte " + NumberToString(stream.GetCursorPos()) + ')');
|
||||
return nullptr;
|
||||
return Err(ResourceLoadingError::DecodingError);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -226,21 +208,21 @@ namespace Nz
|
||||
if (!stream.Read(&magic, 1))
|
||||
{
|
||||
NazaraError("Failed to read stream (byte " + NumberToString(stream.GetCursorPos()) + ')');
|
||||
return nullptr;
|
||||
return Err(ResourceLoadingError::DecodingError);
|
||||
}
|
||||
|
||||
/* first byte must be equal to 0x0c (12) */
|
||||
if (magic != 0x0c)
|
||||
{
|
||||
NazaraError("Colormap's first byte must be 0x0c (0x" + NumberToString(magic, 16) + ')');
|
||||
return nullptr;
|
||||
return Err(ResourceLoadingError::DecodingError);
|
||||
}
|
||||
|
||||
/* read palette */
|
||||
if (stream.Read(palette, 768) != 768)
|
||||
{
|
||||
NazaraError("Failed to read palette");
|
||||
return nullptr;
|
||||
return Err(ResourceLoadingError::DecodingError);
|
||||
}
|
||||
|
||||
stream.SetCursorPos(curPos);
|
||||
@@ -259,7 +241,7 @@ namespace Nz
|
||||
if (!stream.Read(&rleValue, 1))
|
||||
{
|
||||
NazaraError("Failed to read stream (byte " + NumberToString(stream.GetCursorPos()) + ')');
|
||||
return nullptr;
|
||||
return Err(ResourceLoadingError::DecodingError);
|
||||
}
|
||||
|
||||
if (rleValue < 0xc0)
|
||||
@@ -270,7 +252,7 @@ namespace Nz
|
||||
if (!stream.Read(&rleValue, 1))
|
||||
{
|
||||
NazaraError("Failed to read stream (byte " + NumberToString(stream.GetCursorPos()) + ')');
|
||||
return nullptr;
|
||||
return Err(ResourceLoadingError::DecodingError);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -303,7 +285,7 @@ namespace Nz
|
||||
if (!stream.Read(&rleValue, 1))
|
||||
{
|
||||
NazaraError("Failed to read stream (byte " + NumberToString(stream.GetCursorPos()) + ')');
|
||||
return nullptr;
|
||||
return Err(ResourceLoadingError::DecodingError);
|
||||
}
|
||||
|
||||
if (rleValue < 0xc0)
|
||||
@@ -314,7 +296,7 @@ namespace Nz
|
||||
if (!stream.Read(&rleValue, 1))
|
||||
{
|
||||
NazaraError("Failed to read stream (byte " + NumberToString(stream.GetCursorPos()) + ')');
|
||||
return nullptr;
|
||||
return Err(ResourceLoadingError::DecodingError);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -330,7 +312,7 @@ namespace Nz
|
||||
|
||||
default:
|
||||
NazaraError("Unsupported " + NumberToString(bitCount) + " bitcount for pcx files");
|
||||
return nullptr;
|
||||
return Err(ResourceLoadingError::DecodingError);
|
||||
}
|
||||
|
||||
if (parameters.loadFormat != PixelFormat::Undefined)
|
||||
@@ -346,8 +328,15 @@ namespace Nz
|
||||
{
|
||||
ImageLoader::Entry loaderEntry;
|
||||
loaderEntry.extensionSupport = IsPCXSupported;
|
||||
loaderEntry.streamChecker = CheckPCX;
|
||||
loaderEntry.streamLoader = LoadPCX;
|
||||
loaderEntry.parameterFilter = [](const ImageParams& parameters)
|
||||
{
|
||||
bool skip;
|
||||
if (parameters.custom.GetBooleanParameter("SkipBuiltinPCXLoader", &skip) && skip)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
return loaderEntry;
|
||||
}
|
||||
|
||||
@@ -38,37 +38,27 @@ namespace Nz
|
||||
|
||||
static stbi_io_callbacks s_stbiCallbacks = { StbiRead, StbiSkip, StbiEof };
|
||||
|
||||
constexpr auto s_supportedExtensions = frozen::make_unordered_set<frozen::string>({ "bmp", "gif", "hdr", "jpg", "jpeg", "pic", "png", "ppm", "pgm", "psd", "tga" });
|
||||
constexpr auto s_supportedExtensions = frozen::make_unordered_set<frozen::string>({ ".bmp", ".gif", ".hdr", ".jpg", ".jpeg", ".pic", ".png", ".ppm", ".pgm", ".psd", ".tga" });
|
||||
|
||||
bool IsSTBSupported(const std::string_view& extension)
|
||||
{
|
||||
return s_supportedExtensions.find(extension) != s_supportedExtensions.end();
|
||||
}
|
||||
|
||||
Ternary CheckSTB(Stream& stream, const ImageParams& parameters)
|
||||
Result<std::shared_ptr<Image>, ResourceLoadingError> LoadSTB(Stream& stream, const ImageParams& parameters)
|
||||
{
|
||||
bool skip;
|
||||
if (parameters.custom.GetBooleanParameter("SkipBuiltinSTBLoader", &skip) && skip)
|
||||
return Ternary::False;
|
||||
|
||||
int width, height, bpp;
|
||||
if (stbi_info_from_callbacks(&s_stbiCallbacks, &stream, &width, &height, &bpp))
|
||||
return Ternary::True;
|
||||
else
|
||||
return Ternary::False;
|
||||
}
|
||||
if (!stbi_info_from_callbacks(&s_stbiCallbacks, &stream, &width, &height, &bpp))
|
||||
return Err(ResourceLoadingError::Unrecognized);
|
||||
|
||||
std::shared_ptr<Image> LoadSTB(Stream& stream, const ImageParams& parameters)
|
||||
{
|
||||
// Je charge tout en RGBA8 et je converti ensuite via la méthode Convert
|
||||
// Ceci à cause d'un bug de STB lorsqu'il s'agit de charger certaines images (ex: JPG) en "default"
|
||||
// Load everything as RGBA8 and then convert using the Image::Convert method
|
||||
// This is because of a STB bug when loading some JPG images with default settings
|
||||
|
||||
int width, height, bpp;
|
||||
UInt8* ptr = stbi_load_from_callbacks(&s_stbiCallbacks, &stream, &width, &height, &bpp, STBI_rgb_alpha);
|
||||
if (!ptr)
|
||||
{
|
||||
NazaraError("Failed to load image: " + std::string(stbi_failure_reason()));
|
||||
return {};
|
||||
return Err(ResourceLoadingError::Unrecognized);
|
||||
}
|
||||
|
||||
CallOnExit freeStbiImage([ptr]()
|
||||
@@ -80,7 +70,7 @@ namespace Nz
|
||||
if (!image->Create(ImageType::E2D, PixelFormat::RGBA8, width, height, 1, (parameters.levelCount > 0) ? parameters.levelCount : 1))
|
||||
{
|
||||
NazaraError("Failed to create image");
|
||||
return {};
|
||||
return Err(ResourceLoadingError::Internal);
|
||||
}
|
||||
|
||||
image->Update(ptr);
|
||||
@@ -92,7 +82,7 @@ namespace Nz
|
||||
if (!image->Convert(parameters.loadFormat))
|
||||
{
|
||||
NazaraError("Failed to convert image to required format");
|
||||
return {};
|
||||
return Err(ResourceLoadingError::Internal);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,8 +96,15 @@ namespace Nz
|
||||
{
|
||||
ImageLoader::Entry loaderEntry;
|
||||
loaderEntry.extensionSupport = IsSTBSupported;
|
||||
loaderEntry.streamChecker = CheckSTB;
|
||||
loaderEntry.streamLoader = LoadSTB;
|
||||
loaderEntry.parameterFilter = [](const ImageParams& parameters)
|
||||
{
|
||||
bool skip;
|
||||
if (parameters.custom.GetBooleanParameter("SkipBuiltinSTBLoader", &skip) && skip)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
return loaderEntry;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user