Tanoda
PackageDefinition.cs
Go to the documentation of this file.
1/******************************************************************************
2 * Copyright (C) Ultraleap, Inc. 2011-2020. *
3 * *
4 * Use subject to the terms of the Apache License 2.0 available at *
5 * http://www.apache.org/licenses/LICENSE-2.0, or another agreement *
6 * between Ultraleap and you, your company or other organization. *
7 ******************************************************************************/
8
9using UnityEngine;
10#if UNITY_EDITOR
11using UnityEditor;
12#endif
13using System;
14using System.IO;
15using System.Linq;
16using System.Collections.Generic;
17using System.Diagnostics;
18
19namespace Leap.Unity.Packaging {
20
21 [CreateAssetMenu(fileName = "Package", menuName = "Package Definition", order = 202)]
23 private const string DEFAULT_PACKAGE_NAME = "Package.asset";
24
25 [Tooltip("All files within each folder will be included in this package when built.")]
26 [SerializeField]
27 protected string[] _dependantFolders = new string[0];
28
29 [SerializeField]
30 protected string[] _ignoredFolders = new string[0];
31
32 [Tooltip("All files specified in this list will be included in this package when built.")]
33 [SerializeField]
34 protected string[] _dependantFiles = new string[0];
35
36 [SerializeField]
37 protected string[] _ignoredFiles = new string[0];
38
39 [Tooltip("All files specified in each package will be included in this package when built.")]
40 [SerializeField]
42
44 _definitionName = "Package";
45 }
46
47#if UNITY_EDITOR
48 public static PackageDefinition[] FindAll() {
49 return AssetDatabase.FindAssets("t:PackageDefinition").
50 Select(guid => AssetDatabase.GUIDToAssetPath(guid)).
51 Select(path => AssetDatabase.LoadAssetAtPath<PackageDefinition>(path)).
52 OrderBy(def => def.DefinitionName).
53 ToArray();
54 }
55
56 public static void BuildPackage(string packageGUID) {
57 string assetPath = AssetDatabase.GUIDToAssetPath(packageGUID);
58 var packageDef = AssetDatabase.LoadAssetAtPath<PackageDefinition>(assetPath);
59
60 if (packageDef != null) {
61 packageDef.BuildPackage(interactive: true);
62 }
63 }
64
70 public void BuildPackage(bool interactive) {
71 string exportFolder;
72 if (!TryGetPackageExportFolder(out exportFolder, promptIfNotDefined: true)) {
73 UnityEngine.Debug.LogWarning("Did not build package " + DefinitionName + " because no path was defined.");
74 return;
75 }
76
77 string exportPath = Path.Combine(exportFolder, DefinitionName + ".unitypackage");
78
79 HashSet<string> assets = new HashSet<string>();
80
81 HashSet<PackageDefinition> totalPackages = new HashSet<PackageDefinition>();
82 totalPackages.Add(this);
83 buildPackageSet(totalPackages);
84
85 foreach (var package in totalPackages) {
86
87 //Check for missing files. Any dependant file that is missing is an error and build cannot continue!
88 var missingFiles = package._dependantFiles.Distinct().Where(path => !File.Exists(path));
89 if (missingFiles.Any()) {
90 string message = "Could not build package [" + package.DefinitionName + "] because the following dependant files were not found:\n";
91 foreach (var missingFile in missingFiles) {
92 message += "\n" + missingFile;
93 }
94
95 EditorUtility.DisplayDialog("Build Failed: Missing file", message, "Ok");
96 return;
97 }
98
99 assets.UnionWith(package._dependantFiles);
100
101 //package exporter expands directories, we do it manually so that we can filter later
102 //on a file-by-file basis
103 foreach (var folder in package._dependantFolders) {
104 foreach (var subFile in Directory.GetFiles(folder, "*", SearchOption.AllDirectories)) {
105 assets.Add(subFile);
106 }
107 }
108 }
109
110 //Build a set of paths to package definitions
111 //We want to be able to exclude paths from the export that are paths to package definitions
112 var packagePaths = new HashSet<string>(FindAll().Select(package => Path.GetFullPath(AssetDatabase.GetAssetPath(package))));
113
114 //Filter paths to:
115 // - paths that point to existing files
116 // - paths that do not point to package definitions
117 // - paths that do not point to meta files (let the exporter take care of that)
118 // - paths that are not ignored
119 // - paths that are not in an ignored folder
120 var filteredAssets = assets.Where(path => File.Exists(path)).
121 Where(path => !packagePaths.Contains(Path.GetFullPath(path))).
122 Where(path => Path.GetExtension(path) != ".meta").
123 Where(path => !_ignoredFiles.Select(Path.GetFullPath).Contains(Path.GetFullPath(path))).
124 Where(path => _ignoredFolders.All(folder => !Path.GetFullPath(path).Contains(Path.GetFullPath(folder)))).
125 ToArray();
126
127 ExportPackageOptions options = ExportPackageOptions.Recurse;
128 if (interactive) {
129 options |= ExportPackageOptions.Interactive;
130 }
131
132 AssetDatabase.ExportPackage(filteredAssets, exportPath, options);
133 }
134
138 public void BuildAllChildPackages() {
139 List<PackageDefinition> childPackages = GetChildPackages();
140 childPackages.Add(this);
141
142 buildPackages(childPackages.ToArray());
143 }
144
145 private void buildPackageSet(HashSet<PackageDefinition> packages) {
146 if (_dependantPackages == null) return;
147
148 for (int i = 0; i < _dependantPackages.Length; i++) {
149 PackageDefinition package = _dependantPackages[i];
150 if (package == null) {
151 continue;
152 }
153
154 if (!packages.Contains(package)) {
155 packages.Add(package);
156 package.buildPackageSet(packages);
157 }
158 }
159 }
160
164 public List<PackageDefinition> GetChildPackages() {
165 List<PackageDefinition> children = new List<PackageDefinition>();
166 var allPackages = FindAll();
167
168 //Just search through all existing package definitions and check their dependancies
169 HashSet<PackageDefinition> packages = new HashSet<PackageDefinition>();
170 foreach (var package in allPackages) {
171 package.buildPackageSet(packages);
172 if (packages.Contains(this)) {
173 children.Add(package);
174 }
175 packages.Clear();
176 }
177
178 return children;
179 }
180
181 private static void buildPackages(PackageDefinition[] packages) {
182 string validPath = null;
183 try {
184 for (int i = 0; i < packages.Length; i++) {
185 var package = packages[i];
186
187 if (EditorUtility.DisplayCancelableProgressBar("Building Packages", "Building " + package.DefinitionName + "...", i / (float)packages.Length)) {
188 break;
189 }
190 try {
191 package.BuildPackage(interactive: false);
192 package.TryGetPackageExportFolder(out validPath, promptIfNotDefined: false);
193 } catch (Exception e) {
194 UnityEngine.Debug.LogError("Exception thrown while trying to build package " + package.DefinitionName);
195 UnityEngine.Debug.LogException(e);
196 }
197 }
198 } finally {
199 EditorUtility.ClearProgressBar();
200
201 if (validPath != null) {
202 Process.Start(validPath);
203 }
204 }
205 }
206
207 [MenuItem("Build/All Packages", priority = 0)]
208 private static void buildAllPackages() {
209 buildPackages(FindAll());
210 }
211
212 [MenuItem("Build/All Packages", priority = 0, validate = true)]
213 private static bool validateBuildAllPackages() {
214 return FindAll().Length > 0;
215 }
216#endif
217 }
218}