LLM for Unity  v2.5.0
Create characters in Unity with LLMs!
Loading...
Searching...
No Matches
LLMBuilder.cs
Go to the documentation of this file.
1
3using UnityEditor;
4using UnityEngine;
5using System.IO;
6using System.Collections.Generic;
7
8#if UNITY_EDITOR
9namespace LLMUnity
10{
15 public class LLMBuilder : AssetPostprocessor
16 {
17 static List<StringPair> movedPairs = new List<StringPair>();
18 public static string BuildTempDir = Path.Combine(Application.temporaryCachePath, "LLMUnityBuild");
19 static string movedCache = Path.Combine(BuildTempDir, "moved.json");
20
21 [InitializeOnLoadMethod]
22 private static void InitializeOnLoad()
23 {
24 Reset();
25 }
26
27 public static string PluginDir(string platform, bool relative = false)
28 {
29 string pluginDir = Path.Combine("Plugins", platform, "LLMUnity");
30 if (!relative) pluginDir = Path.Combine(Application.dataPath, pluginDir);
31 return pluginDir;
32 }
33
34 public static string PluginLibraryDir(string platform, bool relative = false)
35 {
36 return Path.Combine(PluginDir(platform, relative), LLMUnitySetup.libraryName);
37 }
38
45 public static void HandleActionFileRecursive(string source, string target, ActionCallback actionCallback)
46 {
47 if (File.Exists(source))
48 {
49 actionCallback(source, target);
50 }
51 else if (Directory.Exists(source))
52 {
53 Directory.CreateDirectory(target);
54 List<string> filesAndDirs = new List<string>();
55 filesAndDirs.AddRange(Directory.GetFiles(source));
56 filesAndDirs.AddRange(Directory.GetDirectories(source));
57 foreach (string path in filesAndDirs)
58 {
59 HandleActionFileRecursive(path, Path.Combine(target, Path.GetFileName(path)), actionCallback);
60 }
61 }
62 }
63
69 public static void CopyWithOverwrite(string source, string target)
70 {
71 File.Copy(source, target, true);
72 }
73
79 public static void CopyPath(string source, string target)
80 {
82 }
83
89 public static void MovePath(string source, string target)
90 {
91 HandleActionFileRecursive(source, target, File.Move);
92 DeletePath(source);
93 }
94
99 public static bool DeletePath(string path)
100 {
101 string[] allowedDirs = new string[] { LLMUnitySetup.GetAssetPath(), BuildTempDir, PluginDir("Android"), PluginDir("iOS"), PluginDir("VisionOS")};
102 bool deleteOK = false;
103 foreach (string allowedDir in allowedDirs) deleteOK = deleteOK || LLMUnitySetup.IsSubPath(path, allowedDir);
104 if (!deleteOK)
105 {
106 LLMUnitySetup.LogError($"Safeguard: {path} will not be deleted because it may not be safe");
107 return false;
108 }
109 if (File.Exists(path)) File.Delete(path);
110 else if (Directory.Exists(path)) Directory.Delete(path, true);
111 return true;
112 }
113
114 static void AddMovedPair(string source, string target)
115 {
116 movedPairs.Add(new StringPair {source = source, target = target});
117 File.WriteAllText(movedCache, JsonUtility.ToJson(new ListStringPair { pairs = movedPairs }, true));
118 }
119
120 static void AddTargetPair(string target)
121 {
122 AddMovedPair("", target);
123 }
124
125 static bool MoveAction(string source, string target, bool addEntry = true)
126 {
127 ActionCallback moveCallback;
128 if (File.Exists(source)) moveCallback = File.Move;
129 else if (Directory.Exists(source)) moveCallback = MovePath;
130 else return false;
131
132 if (addEntry) AddMovedPair(source, target);
133 moveCallback(source, target);
134 return true;
135 }
136
137 static bool CopyAction(string source, string target, bool addEntry = true)
138 {
139 ActionCallback copyCallback;
140 if (File.Exists(source)) copyCallback = File.Copy;
141 else if (Directory.Exists(source)) copyCallback = CopyPath;
142 else return false;
143
144 if (addEntry) AddTargetPair(target);
145 copyCallback(source, target);
146 return true;
147 }
148
149 static void CopyActionAddMeta(string source, string target)
150 {
151 CopyAction(source, target);
152 AddTargetPair(target + ".meta");
153 }
154
155 static void AddActionAddMeta(string target)
156 {
157 AddTargetPair(target);
158 AddTargetPair(target + ".meta");
159 }
160
165 public static void BuildLibraryPlatforms(BuildTarget buildTarget)
166 {
167 string platform = "";
168 switch (buildTarget)
169 {
170 case BuildTarget.StandaloneWindows:
171 case BuildTarget.StandaloneWindows64:
172 platform = "windows";
173 break;
174 case BuildTarget.StandaloneLinux64:
175 platform = "linux";
176 break;
177 case BuildTarget.StandaloneOSX:
178 platform = "macos";
179 break;
180 case BuildTarget.Android:
181 platform = "android";
182 break;
183 case BuildTarget.iOS:
184 platform = "ios";
185 break;
186 case BuildTarget.VisionOS:
187 platform = "visionos";
188 break;
189 }
190
191 foreach (string source in Directory.GetDirectories(LLMUnitySetup.libraryPath))
192 {
193 string sourceName = Path.GetFileName(source);
194 bool move = !sourceName.StartsWith(platform);
195 move = move || (sourceName.Contains("cuda") && !sourceName.Contains("full") && LLMUnitySetup.FullLlamaLib);
196 move = move || (sourceName.Contains("cuda") && sourceName.Contains("full") && !LLMUnitySetup.FullLlamaLib);
197 if (move)
198 {
199 string target = Path.Combine(BuildTempDir, sourceName);
200 MoveAction(source, target);
201 MoveAction(source + ".meta", target + ".meta");
202 }
203 }
204
205 if (buildTarget == BuildTarget.Android || buildTarget == BuildTarget.iOS || buildTarget == BuildTarget.VisionOS)
206 {
207 string source = Path.Combine(LLMUnitySetup.libraryPath, platform);
208 string target = PluginLibraryDir(buildTarget.ToString());
209 string pluginDir = PluginDir(buildTarget.ToString());
210 MoveAction(source, target);
211 MoveAction(source + ".meta", target + ".meta");
212 AddActionAddMeta(pluginDir);
213 }
214 }
215
216 static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths, bool didDomainReload)
217 {
218 foreach (BuildTarget buildTarget in new BuildTarget[]{BuildTarget.iOS, BuildTarget.VisionOS})
219 {
220 string pathToPlugin = Path.Combine("Assets", PluginLibraryDir(buildTarget.ToString(), true), $"libundreamai_{buildTarget.ToString().ToLower()}.a");
221 for (int i = 0; i < movedAssets.Length; i++)
222 {
223 if (movedAssets[i] == pathToPlugin)
224 {
225 var importer = AssetImporter.GetAtPath(pathToPlugin) as PluginImporter;
226 if (importer != null && importer.isNativePlugin)
227 {
228 importer.SetCompatibleWithPlatform(buildTarget, true);
229 importer.SetPlatformData(buildTarget, "CPU", "ARM64");
230 AssetDatabase.ImportAsset(pathToPlugin);
231 }
232 }
233 }
234 }
235 }
236
240 public static void BuildModels()
241 {
242 LLMManager.Build(CopyActionAddMeta);
243 if (File.Exists(LLMUnitySetup.LLMManagerPath)) AddActionAddMeta(LLMUnitySetup.LLMManagerPath);
244 }
245
249 public static void Build(BuildTarget buildTarget)
250 {
251 DeletePath(BuildTempDir);
252 Directory.CreateDirectory(BuildTempDir);
253 BuildLibraryPlatforms(buildTarget);
254 BuildModels();
255 }
256
260 public static void Reset()
261 {
262 if (!File.Exists(movedCache)) return;
263 List<StringPair> movedPairs = JsonUtility.FromJson<ListStringPair>(File.ReadAllText(movedCache)).pairs;
264 if (movedPairs == null) return;
265
266 bool refresh = false;
267 foreach (var pair in movedPairs)
268 {
269 if (pair.source == "") refresh |= DeletePath(pair.target);
270 else refresh |= MoveAction(pair.target, pair.source, false);
271 }
272 if (refresh) AssetDatabase.Refresh();
273 DeletePath(movedCache);
274 }
275 }
276}
277#endif
Class implementing the LLMUnity builder.
Definition LLMBuilder.cs:16
static void Reset()
Resets the libraries back to their original state.
static void MovePath(string source, string target)
Moves a source file to a target file.
Definition LLMBuilder.cs:89
static bool DeletePath(string path)
Deletes a path after checking if we are allowed to.
Definition LLMBuilder.cs:99
static void BuildModels()
Bundles the model information.
static void BuildLibraryPlatforms(BuildTarget buildTarget)
Moves libraries in the correct place for building.
static void Build(BuildTarget buildTarget)
Bundles the models and libraries.
static void CopyPath(string source, string target)
Copies a source file to a target file.
Definition LLMBuilder.cs:79
static void HandleActionFileRecursive(string source, string target, ActionCallback actionCallback)
Performs an action for a file or a directory recursively.
Definition LLMBuilder.cs:45
static void CopyWithOverwrite(string source, string target)
Overwrites a target file based on the source file.
Definition LLMBuilder.cs:69
Class implementing the LLM model manager.
static void Build(ActionCallback copyCallback)
Saves the model manager to disk along with models that are not (or can't) be downloaded for the build...
Class implementing helper functions for setup and process management.
static string LLMManagerPath
Path of file with build information for runtime.
static string libraryPath
LlamaLib path.
static string libraryName
LlamaLib name.