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 // check if this is already a valid path 34 if (std.file.exists(path)) { 35 return path.c_str(); 36 } 37 auto base = string.init; 38 alias join_paths = std.path.buildNormalizedPath; 39 // check search paths first 40 foreach (search_path; paths) { 41 // if the combination path exists, then make this base 42 if (std.file.exists(join_paths(search_path, path))) { 43 base = search_path; 44 break; 45 } 46 } 47 return join_paths(base, path).c_str(); 48 } 49 50 /// loads a texture from disk 51 public raylib.Texture2D load_texture2d(string path) { 52 raylib.Texture2D tex; 53 auto cached = _tex_cache.get(path); 54 if (cached.isNull) { 55 auto image = raylib.LoadImage(get_path(path)); 56 tex = raylib.LoadTextureFromImage(image); 57 raylib.UnloadImage(image); 58 _tex_cache.put(path, tex); 59 } else { 60 tex = cached.get; 61 } 62 63 // copy image to VRAM 64 return tex; 65 } 66 67 /// loads a model from disk 68 public raylib.Model load_model(string path) { 69 raylib.Model mdl; 70 auto cached = _mdl_cache.get(path); 71 if (cached.isNull) { 72 mdl = raylib.LoadModel(get_path(path)); 73 _mdl_cache.put(path, mdl); 74 } else { 75 mdl = cached.get; 76 } 77 return mdl; 78 } 79 80 /// loads a shader from disk (vertex shader, fragment shader). 81 /// pass null to either arg to use the default 82 public raylib.Shader load_shader(string vs_path, string fs_path) { 83 raylib.Shader shd; 84 import std.digest.sha : sha1Of, toHexString; 85 86 auto path_hash = to!string(sha1Of(vs_path ~ fs_path).toHexString); 87 auto cached = _shd_cache.get(path_hash); 88 if (cached.isNull) { 89 auto vs = vs_path.length > 0 ? get_path(vs_path) : null; 90 auto fs = fs_path.length > 0 ? get_path(fs_path) : null; 91 shd = raylib.LoadShader(vs, fs); 92 _shd_cache.put(path_hash, shd); 93 } else { 94 shd = cached.get; 95 } 96 return shd; 97 } 98 99 /// releases all resources 100 public void destroy() { 101 // delete textures 102 _tex_cache.drop(); 103 // delete models 104 _mdl_cache.drop(); 105 // delete shaders 106 _shd_cache.drop(); 107 } 108 }