diff --git a/Navmesher/Navmesher.vcxproj b/Navmesher/Navmesher.vcxproj
index 08d21a6..7dba576 100644
--- a/Navmesher/Navmesher.vcxproj
+++ b/Navmesher/Navmesher.vcxproj
@@ -140,6 +140,7 @@
+
diff --git a/Navmesher/Navmesher.vcxproj.filters b/Navmesher/Navmesher.vcxproj.filters
index b8424dd..732cb89 100644
--- a/Navmesher/Navmesher.vcxproj.filters
+++ b/Navmesher/Navmesher.vcxproj.filters
@@ -32,5 +32,8 @@
Header Files
+
+ Header Files
+
\ No newline at end of file
diff --git a/Navmesher/esx_reader.cpp b/Navmesher/esx_reader.cpp
index f278348..edd8db5 100644
--- a/Navmesher/esx_reader.cpp
+++ b/Navmesher/esx_reader.cpp
@@ -1,4 +1,9 @@
-#include "esx_reader.hpp"
+#include "esx_reader_impl.hpp"
using namespace esxr;
+[[nodiscard]] Header esxr::read_header(std::istream &in)
+{
+ return read_header_impl(in);
+}
+
diff --git a/Navmesher/esx_reader.hpp b/Navmesher/esx_reader.hpp
index 0f7400f..245848a 100644
--- a/Navmesher/esx_reader.hpp
+++ b/Navmesher/esx_reader.hpp
@@ -21,14 +21,6 @@ namespace esxr {
class GroupNode;
class RecordNode;
-//
-// Constants
-//
-
-static constexpr auto esx_endianness = std::endian::little;
-static constexpr std::streamsize header_size = 24;
-static constexpr bool same_endianness = std::endian::native == esx_endianness;
-
//
// Enumerations
//
@@ -136,21 +128,6 @@ struct RecordHeader {
uint16_t unknown;
};
-//
-// Concepts
-//
-
-template
-concept packed = sizeof(T) == N;
-
-template
-concept packed_header = packed(header_size)>;
-
-template
-concept directly_readable_header = packed_header && same_endianness;
-
-constexpr bool directly_readable = directly_readable_header && directly_readable_header && directly_readable_header;
-
//
// Classes
//
@@ -181,37 +158,7 @@ private:
[[nodiscard]] std::optional flag_to_description(Flag flag) noexcept;
[[nodiscard]] std::optional refr_flag_to_description(RefrFlag refr_flag) noexcept;
-
-// Convert a compatible C string to a FourCC (e.g. "LITR")
-constexpr FourCC fourcc_from_cstr(const char(&a)[5]) noexcept
-{
- char temp[4] = { a[0], a[1], a[2], a[3] };
- return std::bit_cast(temp);
-}
-
-template requires directly_readable
-[[nodiscard]] Header read_header(std::istream &in)
-{
- // read in header
- UnknownHeader unknown_header{};
- auto char_ptr = reinterpret_cast(&unknown_header);
- in.read(char_ptr, header_size);
- auto type_opt = fourcc_to_record_type(unknown_header.type);
-
- // failed to read header
- if (in.fail())
- throw std::runtime_error("Could not read header from given input stream.")
-
- // invalid type value
- if (!type_opt)
- throw std::runtime_error("Invalid header type while reading esx file.");
-
- auto type = type_opt.value();
- if (type == RecordType::GRUP)
- return { std::bit_cast(unknown_header) };
- else
- return { std::bit_cast(unknown_header) };
-}
+[[nodiscard]] Header read_header(std::istream &in);
}
diff --git a/Navmesher/esx_reader_impl.hpp b/Navmesher/esx_reader_impl.hpp
new file mode 100644
index 0000000..24ba0cc
--- /dev/null
+++ b/Navmesher/esx_reader_impl.hpp
@@ -0,0 +1,63 @@
+#ifndef ESX_READER_IMPL_HPP
+#define ESX_READER_IMPL_HPP
+
+#include "esx_reader.hpp"
+
+namespace esxr {
+
+//
+// Constants and Concepts
+//
+
+static constexpr auto esx_endianness = std::endian::little;
+static constexpr std::streamsize header_size = 24;
+static constexpr bool same_endianness = std::endian::native == esx_endianness;
+
+template
+concept packed = sizeof(T) == N;
+
+template
+concept packed_header = packed(header_size)>;
+
+template
+concept directly_readable_header = packed_header && same_endianness;
+
+constexpr bool directly_readable = directly_readable_header && directly_readable_header && directly_readable_header;
+
+//
+// Template functions
+//
+
+template requires directly_readable
+[[nodiscard]] Header read_header_impl(std::istream &in)
+{
+ // read in header
+ UnknownHeader unknown_header{};
+ auto char_ptr = reinterpret_cast(&unknown_header);
+ in.read(char_ptr, header_size);
+ auto type_opt = fourcc_to_record_type(unknown_header.type);
+
+ // failed to read header
+ if (in.fail())
+ throw std::runtime_error("Could not read header from given input stream.");
+
+ // invalid type value
+ if (!type_opt)
+ throw std::runtime_error("Invalid header type while reading esx file.");
+
+ auto type = type_opt.value();
+ if (type == RecordType::GRUP)
+ return { std::bit_cast(unknown_header) };
+ else
+ return { std::bit_cast(unknown_header) };
+}
+
+template requires (!directly_readable)
+[[nodiscard]] Header read_header_impl(std::istream &in)
+{
+ static_assert(directly_readable, "Not implemented.");
+}
+
+}
+
+#endif /* ESX_READER_IMPL_HPP */
\ No newline at end of file
diff --git a/Navmesher/esx_reader_lut.cpp b/Navmesher/esx_reader_lut.cpp
index 60dcd08..1b84bdc 100644
--- a/Navmesher/esx_reader_lut.cpp
+++ b/Navmesher/esx_reader_lut.cpp
@@ -15,6 +15,13 @@ static constexpr std::pair group_type_name_map_buil
{GroupType::CellTemporaryChildren , "Cell Temporary Children" },
};
+// Convert a compatible C string to a FourCC (e.g. "LITR")
+static consteval FourCC fourcc_from_cstr(const char(&a)[5]) noexcept
+{
+ char temp[4] = { a[0], a[1], a[2], a[3] };
+ return std::bit_cast(temp);
+}
+
static constexpr std::pair record_type_fourcc_map_builtin[] {
{RecordType::AACT, fourcc_from_cstr("AACT")},
{RecordType::ACHR, fourcc_from_cstr("ACHR")},