1 module rpui.resources.icons; 2 3 import std.path; 4 5 import rpui.math; 6 import gapi.texture; 7 8 import rpui.resources.images; 9 10 import rpdl.tree; 11 import rpui.math; 12 import rpui.paths; 13 14 struct Icon { 15 string group; 16 string name; 17 Texture2DCoords texCoord; 18 } 19 20 struct IconsConfig { 21 string name; 22 string textureFileName; 23 bool themed; /// If themed, then icon texture must placed in theme resources folder. 24 vec2 size; /// Size of one icon. 25 vec2 start; /// Start offset of all icons. 26 vec2 gaps; /// Spacing beetwen icons. 27 } 28 29 /** 30 * This class uses RPDL files for icons repository, for each icons have group 31 * where declared default config such as size of icon, gaps etc. 32 */ 33 final class IconsRes { 34 const Paths paths; 35 36 /** 37 * Create icons resources, this constructor get `imagesRes` as argument 38 * for getting textures for icons. 39 */ 40 this(ImagesRes imagesRes) { 41 assert(imagesRes !is null); 42 this.imagesRes = imagesRes; 43 this.paths = createPathes(); 44 } 45 46 /// Get texture instance for particular group icons. 47 Texture2D getTextureForIcons(in string group) { 48 const config = iconsConfig[group]; 49 50 if (config.themed) { 51 return this.imagesRes.getTextureForUiTheme(buildPath("icons", config.textureFileName)); 52 } else { 53 return this.imagesRes.getTexture(buildPath("icons", config.textureFileName)); 54 } 55 } 56 57 /// Get texture instance for particular icon. 58 Texture2D getTextureForIcons(in Icon icon) { 59 return getTextureForIcons(icon.group); 60 } 61 62 /// Retrieve icon information from group by icon name. 63 Icon getIcon(in string group, in string name) { 64 auto texCoord = Texture2DCoords(); 65 66 const config = iconsConfig[group]; 67 68 // Minus vec2(1, 1) due to icons indexing starting from 1 69 const iconIndexes = iconsData[group].data.getVec2f("Icons." ~ name) - vec2(1, 1); 70 const offsetWithGaps = vec2( 71 iconIndexes.x * (config.size.x + config.gaps.x), 72 iconIndexes.y * (config.size.y + config.gaps.y) 73 ); 74 75 texCoord.offset = config.start + offsetWithGaps; 76 texCoord.size = config.size; 77 texCoord = normilizeTexture2DCoords(texCoord, getTextureForIcons(group)); 78 79 return Icon(group, name, texCoord); 80 } 81 82 /// Retrieve icon config from group. 83 IconsConfig getIconsConfig(in string group) { 84 assert(group in iconsConfig, "Unknown icons group '" ~ group ~ "'"); 85 return iconsConfig[group]; 86 } 87 88 /** 89 * Add new icons group, file with icons declarations must placed in 90 * res/ui/icons folder. 91 */ 92 void addIcons(in string group, in string fileName) { 93 const path = buildPath(paths.resources, "ui", "icons"); 94 iconsData[group] = new RpdlTree(path); 95 iconsData[group].load(fileName); 96 iconsConfig[group] = IconsConfig(); 97 98 with (iconsConfig[group]) { 99 auto groupData = iconsData[group].data; 100 101 name = group; 102 textureFileName = groupData.getString("Config.icons.0"); 103 themed = groupData.optBoolean("Config.themed.0", false); 104 size = groupData.getVec2f("Config.size"); 105 start = groupData.getVec2f("Config.start"); 106 gaps = groupData.getVec2f("Config.gaps"); 107 } 108 } 109 110 private: 111 ImagesRes imagesRes; 112 RpdlTree[string] iconsData; 113 IconsConfig[string] iconsConfig; 114 }