1 module re.content; 2 3 import re.util.cache; 4 import re.util.interop; 5 import std.string; 6 import std.file; 7 import std.conv; 8 import std.path; 9 import std.stdio; 10 static import raylib; 11 12 /// manages external content loading 13 class ContentManager { 14 alias TexCache = KeyedCache!(raylib.Texture2D); 15 private TexCache _tex_cache; 16 alias ModelCache = KeyedCache!(raylib.Model); 17 private ModelCache _mdl_cache; 18 alias ShaderCache = KeyedCache!(raylib.Shader); 19 private ShaderCache _shd_cache; 20 21 /// search paths for content 22 public string[] paths; 23 24 /// initializes the content manager 25 this() { 26 // setup 27 _tex_cache = TexCache((tex) { raylib.UnloadTexture(tex); }); 28 _mdl_cache = ModelCache((mdl) { raylib.UnloadModel(mdl); }); 29 _shd_cache = ShaderCache((shd) { raylib.UnloadShader(shd); }); 30 } 31 32 private const char* get_path(string path) { 33 auto base = string.init; 34 alias join_paths = std.path.buildNormalizedPath; 35 // check search paths first 36 foreach (search_path; paths) { 37 // if the combination path exists, then make this base 38 if (std.file.exists(join_paths(search_path, path))) { 39 base = search_path; 40 break; 41 } 42 } 43 return join_paths(base, path).c_str(); 44 } 45 46 /// loads a texture from disk 47 public raylib.Texture2D load_texture2d(string path) { 48 raylib.Texture2D tex; 49 auto cached = _tex_cache.get(path); 50 if (cached.isNull) { 51 auto image = raylib.LoadImage(get_path(path)); 52 tex = raylib.LoadTextureFromImage(image); 53 raylib.UnloadImage(image); 54 _tex_cache.put(path, tex); 55 } else { 56 tex = cached.get; 57 } 58 59 // copy image to VRAM 60 return tex; 61 } 62 63 /// loads a model from disk 64 public raylib.Model load_model(string path) { 65 raylib.Model mdl; 66 auto cached = _mdl_cache.get(path); 67 if (cached.isNull) { 68 mdl = raylib.LoadModel(get_path(path)); 69 _mdl_cache.put(path, mdl); 70 } else { 71 mdl = cached.get; 72 } 73 return mdl; 74 } 75 76 /// loads a shader from disk (vertex shader, fragment shader). 77 /// pass null to either arg to use the default 78 public raylib.Shader load_shader(string vs_path, string fs_path) { 79 raylib.Shader shd; 80 import std.digest.sha : sha1Of, toHexString; 81 82 auto path_hash = to!string(sha1Of(vs_path ~ fs_path).toHexString); 83 auto cached = _shd_cache.get(path_hash); 84 if (cached.isNull) { 85 auto vs = vs_path.length > 0 ? get_path(vs_path) : null; 86 auto fs = fs_path.length > 0 ? get_path(fs_path) : null; 87 shd = raylib.LoadShader(vs, fs); 88 _shd_cache.put(path_hash, shd); 89 } else { 90 shd = cached.get; 91 } 92 return shd; 93 } 94 95 /// releases all resources 96 public void destroy() { 97 // delete textures 98 _tex_cache.drop(); 99 // delete models 100 _mdl_cache.drop(); 101 // delete shaders 102 _shd_cache.drop(); 103 } 104 }