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 public raylib.ModelAnimation[] load_model_animations(string path) { 81 uint num_loaded_anims = 0; 82 raylib.ModelAnimation* loaded_anims = raylib.LoadModelAnimations(get_path(path), &num_loaded_anims); 83 auto anims = loaded_anims[0..num_loaded_anims]; // access array as slice 84 return anims; 85 } 86 87 /// loads a shader from disk (vertex shader, fragment shader). 88 /// pass null to either arg to use the default 89 public raylib.Shader load_shader(string vs_path, string fs_path) { 90 raylib.Shader shd; 91 import std.digest.sha : sha1Of, toHexString; 92 93 auto path_hash = to!string(sha1Of(vs_path ~ fs_path).toHexString); 94 auto cached = _shd_cache.get(path_hash); 95 if (cached.isNull) { 96 auto vs = vs_path.length > 0 ? get_path(vs_path) : null; 97 auto fs = fs_path.length > 0 ? get_path(fs_path) : null; 98 shd = raylib.LoadShader(vs, fs); 99 _shd_cache.put(path_hash, shd); 100 } else { 101 shd = cached.get; 102 } 103 return shd; 104 } 105 106 /// releases all resources 107 public void destroy() { 108 // delete textures 109 _tex_cache.drop(); 110 // delete models 111 _mdl_cache.drop(); 112 // delete shaders 113 _shd_cache.drop(); 114 } 115 }