dlib/assets.d

321 lines
4.5 KiB
D

module dlib.assets;
import dlib.aliases;
import dlib.util;
import dlib.alloc;
import std.file;
import std.stdio;
import std.exception;
File Asset_File;
FileHeader Asset_Header;
AssetInfo[] Asset_Info;
u8[][] Asset_Data;
const u32 FILE_VERSION = 2;
const u32 MODEL_VERSION = 1;
enum AssetType : u32
{
None,
ModelM3D,
Shader,
Texture,
}
alias AT = AssetType;
struct FileHeader
{
u32 magic;
u32 file_version;
u64 asset_count;
u64 asset_info_offset;
}
struct ModelHeader
{
u32 magic;
u32 model_version;
u64 vertex_count;
u64 vertex_offset;
u64 index_count;
u64 index_offset;
u64 material_count;
u64 material_offset;
u64 texture_count;
u64 texture_offset;
}
struct Vertex
{
Vec4 color;
Vec4 tangent;
Vec3 pos;
Vec3 normal;
Vec2 uv;
}
struct ModelData
{
Vertex[] vertices;
u32[] indices;
Material[] materials;
TextureInfo[] textures;
}
struct Material
{
Vec4 ambient;
Vec4 albedo;
Vec4 specular;
u32 albedo_texture;
u32 ambient_texture;
u32 specular_texture;
u32 alpha_texture;
b32 albedo_has_texture;
b32 ambient_has_texture;
b32 specular_has_texture;
b32 alpha_has_texture;
f32 shininess = 0.0;
f32 alpha = 0.0;
}
struct TextureInfo
{
string name;
u32 id;
}
struct TextureHeader
{
u64 str_length;
u64 str_offset;
u32 texture_id;
}
struct ModelMeta
{
u64 index_count;
}
struct TexData
{
void* data;
TexMeta meta;
}
struct TexMeta
{
u32 w;
u32 h;
u32 ch;
}
struct AssetInfo
{
u64 hash;
u64 offset;
u64 length;
AssetType type;
}
bool Asset_Pack_Opened = false;
debug
{
bool g_DIR_SET = false;
void
SetDir()
{
if (exists("assets"))
{
chdir("./assets");
}
else if (exists("Gears") || exists("Gears.exe"))
{
chdir("../assets");
}
else
{
assert(false, "Unable to set directory");
}
g_DIR_SET = true;
}
u8[]
LoadAssetData(Arena* arena, string name)
{
if (!g_DIR_SET)
{
SetDir();
}
File f;
try
{
f = File(name, "rb");
}
catch (ErrnoException e)
{
assert(false, "Unable to open file");
}
u8[] mem = AllocArray!(u8)(arena, f.size());
return f.rawRead(mem);
}
}
else
{
void
OpenAssetPack()
{
if (!Asset_Pack_Opened)
{
bool success = true;
string file_path = exists("build/assets.sgp") ? "build/assets.sgp" : "assets.sgp";
// TODO: replace this with something that doesn't throw an exception and figure out if this is the best way to handle thing (probably isnt)
try
{
Asset_File = File(file_path, "rb");
}
catch (ErrnoException e)
{
Logf("OpenAssetPack failure: Unable to open file %s", file_path);
assert(false, "Unable to open asset pack file");
}
FileHeader[1] header_arr;
Asset_File.rawRead(header_arr);
Asset_Header = header_arr[0];
Asset_Info = AllocArray!(AssetInfo)(Asset_Header.asset_count);
Asset_Data = AllocArray!(u8[])(Asset_Header.asset_count);
assert(Asset_Header.file_version == FILE_VERSION, "OpenAssetPack failure: file version incorrect");
Asset_File.seek(Asset_Header.asset_info_offset);
Asset_File.rawRead(Asset_Info);
}
}
pragma(inline): void
CheckAssetPack()
{
if (!Asset_Pack_Opened)
{
OpenAssetPack();
}
}
AssetInfo
GetAssetInfo(string name)
{
CheckAssetPack();
u64 hash = Hash(name);
AssetInfo asset_info;
foreach(i, info; Asset_Info)
{
if (info.hash == hash)
{
asset_info = info;
break;
}
}
assert(asset_info.hash != 0, "GetAssetInfo failure: unable to find matching asset");
return asset_info;
}
u8[]
LoadAssetData(Arena* arena, string name)
{
CheckAssetPack();
u64 hash = Hash(name);
u8[] data = null;
foreach(i, info; Asset_Info)
{
if (info.hash == hash)
{
data = AllocArray!(u8)(arena, info.length);
Asset_File.seek(info.offset);
Asset_File.rawRead(data);
assert(data != null && data.length == info.length, "LoadAssetData failure: Asset data loaded incorrectly");
break;
}
}
return data;
}
u8[]
LoadAssetData(string name)
{
CheckAssetPack();
u64 hash = Hash(name);
u8[] data = null;
foreach(i, info; Asset_Info)
{
if (info.hash == hash)
{
if (Asset_Data[i].ptr == null)
{
Asset_Data[i] = AllocArray!(u8)(info.length);
Asset_File.seek(info.offset);
Asset_File.rawRead(Asset_Data[i]);
assert(Asset_Data[i] != null && Asset_Data[i].length == info.length, "LoadAssetData failure: Asset data loaded incorrectly.");
}
data = Asset_Data[i];
break;
}
}
return data;
}
void
UnloadAssetData(string name)
{
u64 hash = Hash(name);
foreach(i, info; Asset_Info)
{
if (info.hash == hash)
{
if (Asset_Data[i] != null)
{
FreeArray(Asset_Data[i]);
break;
}
}
}
}
}