1 /* 2 * BSD 3-Clause License 3 * 4 * Copyright (c) 2016, Mango-Engine Team 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions are met: 9 * 10 * * Redistributions of source code must retain the above copyright notice, this 11 * list of conditions and the following disclaimer. 12 * 13 * * Redistributions in binary form must reproduce the above copyright notice, 14 * this list of conditions and the following disclaimer in the documentation 15 * and/or other materials provided with the distribution. 16 * 17 * * Neither the name of the copyright holder nor the names of its 18 * contributors may be used to endorse or promote products derived from 19 * this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 28 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 module mango_engine.resource; 33 34 import mango_engine.game; 35 import mango_engine.world; 36 import mango_engine.util; 37 import mango_engine.graphics.texture; 38 import mango_engine.graphics.shader; 39 40 import std.conv; 41 import std.zip; 42 import std.file; 43 import std.json; 44 import std.array; 45 import std.algorithm; 46 import std.exception; 47 48 private void checkTextureJSON(ZipArchive archive, JSONValue root) @trusted { 49 enforce(root["file"].str in archive.directory, new MArchiveParseException("Invalid Archive! Texture file could not be found in archive!")); 50 enforce(root["useAlpha"].type == JSON_TYPE.TRUE || root["useAlpha"].type == JSON_TYPE.FALSE, new MArchiveParseException("Invalid Archive! useAlpha must be true or false!")); 51 } 52 53 class ResourceManager { 54 private shared GameManager _game; 55 56 private shared Texture[string] loadedTextures; 57 58 @property GameManager game() @trusted nothrow { return cast(GameManager) _game; } 59 60 this(GameManager game) @trusted nothrow { 61 this._game = cast(shared) game; 62 } 63 64 Texture loadTexture(in string location) @trusted { 65 enforce(exists(location), "File " ~ location ~ " does not exist!"); 66 enforce(location.endsWith(".marchive"), "File " ~ location ~ " is not a valid .marchive file!"); 67 68 auto zip = new ZipArchive(read(location)); 69 foreach(name, am; zip.directory) { 70 if(name == "texture.json") { 71 zip.expand(am); // Uncompress the JSON information 72 73 string data = cast(string) am.expandedData; // the contents of the JSON file 74 75 JSONValue root = parseJSON(data); 76 checkTextureJSON(zip, root); // Check the texture JSON for correct elements 77 78 string textureName = root["name"].str; 79 string textureFile = root["file"].str; 80 bool useAlpha; 81 switch(root["useAlpha"].type) { 82 case JSON_TYPE.TRUE: 83 useAlpha = true; 84 break; 85 case JSON_TYPE.FALSE: 86 useAlpha = false; 87 break; 88 default: 89 break; 90 } 91 92 enforce(!(textureName in loadedTextures), new Exception("Texture is already loaded!")); 93 94 zip.expand(zip.directory[textureFile]); // Uncompress the texture file 95 96 // The path in mango-engine's temp directory which will contain the uncompressed texture 97 auto uncompressedPath = getTempDirectoryPath() ~ PATH_SEPERATOR ~ "mango-engine" ~ PATH_SEPERATOR ~ "texture-" ~ split(location, ".")[0]; 98 99 write(uncompressedPath, zip.directory[textureFile].expandedData); // Write the uncompressed texture to disk 100 101 Texture texture = Texture.build(game, textureName, uncompressedPath, useAlpha); 102 103 loadedTextures[textureName] = cast(shared) texture; 104 105 return texture; 106 } 107 } 108 109 throw new MArchiveParseException("Invalid Archive! Failed to find texture.json!"); 110 } 111 112 Texture getLoadedTexture(in string name) @trusted { 113 enforce(name in loadedTextures, new Exception("The texture is not loaded!")); 114 115 return cast(Texture) loadedTextures[name]; 116 } 117 118 void unloadTexture(in string name) @trusted { 119 enforce(name in loadedTextures, new Exception("The texture is not loaded!")); 120 121 Texture t = cast(Texture) loadedTextures[name]; 122 t.cleanup(); 123 124 loadedTextures.remove(name); 125 } 126 127 bool isTextureLoaded(in string name) @safe { 128 return name in loadedTextures ? true : false; 129 } 130 } 131 132 class MArchiveParseException : Exception { 133 134 this(in string message) @safe nothrow { 135 super(message); 136 } 137 }