1 module unecht.core.assetDatabase;
2 
3 import std.uuid;
4 
5 import unecht.core.object;
6 import unecht.core.serialization.serializer;
7 
8 ///
9 struct UEAsset
10 {
11     UEObject obj;
12     string path;
13     string metaPath;
14 }
15 
16 ///
17 static struct UEAssetDatabase
18 {
19     static UEAsset[] assets;
20 
21     static immutable EXT_METAFILE = ".uem";
22     static immutable ASSETFOLDER = "/assets/";
23 
24     private static string assetPath() { 
25         import std.path:dirName;
26         import std.file:thisExePath;
27 
28         return dirName(thisExePath()) ~ ASSETFOLDER; 
29     }
30 
31     ///
32     static void refresh()
33     {
34         refresh(assetPath());
35     }
36 
37     ///
38     static void refresh(string path)
39     {
40         import std.file:DirEntry,dirEntries,SpanMode,exists;
41         import std.path:relativePath;
42 
43         if(!exists(path))
44             return;
45 
46         foreach (DirEntry e; dirEntries(path, SpanMode.breadth))
47         {
48             auto relPath = relativePath(e.name, path);
49 
50             if(!containsPath(relPath))
51             {
52                 parseAssetFile(relPath);
53             }
54         }
55     }
56 
57     static UUID[] getAllIds()
58     {
59         UUID[] res;
60         res.length = assets.length;
61         foreach(i,asset; assets)
62             res[i] = asset.obj.instanceId;
63 
64         return res;
65     }
66 
67     ///
68     static bool containsPath(string path)
69     {
70         import std.algorithm;
71         return countUntil!"a.path == b"(assets,path) != -1;
72     }
73 
74     ///
75     static void parseAssetFile(string path)
76     {
77         import std.path:extension;
78 
79         auto ext = extension(path);
80 
81         import unecht.core.logger;
82         log.infof("parse: '%s' (%s)",path, ext);
83 
84         //TODO: solve different extension using a dictonary of assetimporters
85         if(ext == ".png")
86         {
87             loadTextureAsset(path);
88         }
89     }
90 
91     ///
92     static UEObject getAsset(string path)
93     {
94         foreach(asset; assets)
95         {
96             if(asset.path == path)
97                 return asset.obj;
98         }
99 
100         return null;
101     }
102 
103     ///
104     static string getAssetName(UEObject object)
105     {
106         foreach(asset; assets)
107         {
108             if(asset.obj == object)
109                 return asset.path;
110         }
111 
112         return "";
113     }
114 
115     ///
116     static void loadTextureAsset(string path)
117     {
118         import std.file:exists;
119         import unecht.core.assets.texture;
120 
121         UETexture2D tex;
122         immutable assetFile = assetPath ~ path;
123         immutable metaFilePath = assetFile ~ EXT_METAFILE;
124       
125         if(exists(metaFilePath))
126         {
127             tex = deserializeMetaFile!UETexture2D(metaFilePath);
128         }
129         else
130         {
131             tex = new UETexture2D();
132             serializeMetaFile(tex, metaFilePath);
133         }
134 
135         tex.loadFromFile(assetFile);
136 
137         addAsset(tex, path, metaFilePath);
138     }
139 
140     static void updateAssetMetafile(UEObject obj)
141     {
142         foreach(asset; assets)
143         {
144             if(asset.obj is obj)
145             {
146                 serializeMetaFile(obj, asset.metaPath);
147             }
148         }
149     }
150 
151     ///
152     static void addAsset(UEObject obj, string path, string metaPath)
153     {
154         assets ~= UEAsset(obj, path, metaPath);
155     }
156 
157     ///
158     private static void serializeMetaFile(UEObject obj, string path)
159     {
160         import std.file;
161 
162         UESerializer s;
163         obj.serialize(s);
164 
165         auto serializedStr = s.toString();
166 
167         write(path, serializedStr);
168 
169         import unecht.core.logger;
170         log.infof("written uem: (%s) -> \n%s",path,serializedStr);
171     }
172 
173     ///
174     private static auto deserializeMetaFile(T)(string path)
175     {
176         import std.file;
177         string fileContent = cast(string)read(path);
178 
179         import unecht.core.logger;
180         log.infof("uem read: (%s)",path);
181 
182         UEDeserializer d = UEDeserializer(fileContent);
183         return d.deserializeFirst!T();
184     }
185 }