Skip to content

Commit

Permalink
New pak format and update to 2018.4.29 (#51)
Browse files Browse the repository at this point in the history
* - new videopak format that adds metadata and icon and compresses all files into a single archive

* - workaround to get Klak to work with scripting runtime 4.x

* - resave project with new recommended unity version, 2018.4.29 LTS

* - switch to scripting runtime version 4.x

* - update git ignore

* - validate pak name and icon before building

* - update api comparability level to .NET standard 2.0

* - after calling BuildAssetBundles() for Android, the editor was left in an undefined platform state. Workaround is to build OSX lastly.

* - strip VFX Manager asset

Co-authored-by: Jonas Åberg <[email protected]>
  • Loading branch information
hoodihoon and Jonas Åberg authored Mar 30, 2021
1 parent 34faf4b commit b8fa6a0
Show file tree
Hide file tree
Showing 12 changed files with 306 additions and 144 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
/[Oo]bj/
/[Bb]uild/
/[Bb]uilds/
/[Ll]ogs/
/Assets/AssetStoreTools*

# Visual Studio 2015 cache directory
Expand Down Expand Up @@ -34,4 +35,4 @@ sysinfo.txt
*.unitypackage

# Mac
.DS_Store
.DS_Store
2 changes: 1 addition & 1 deletion Assets/Bezier/Editor/SVG/SVGParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public GameObject Parse(string svgStr, bool stripGroups = false)
// Ignore links to external resources.
XmlReaderSettings settings = new XmlReaderSettings();
settings.XmlResolver = null;
settings.ProhibitDtd = false;
settings.DtdProcessing = DtdProcessing.Parse;

GameObject go = new GameObject("SVG");
RectTransform svgElement = go.AddComponent<RectTransform>();
Expand Down
6 changes: 6 additions & 0 deletions Assets/Klak/Wiring/Editor/Patcher/Graph.cs
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,12 @@ public override bool CanConnect(Graphs.Slot fromSlot, Graphs.Slot toSlot)
{
// If the outlet is bang, any inlet can be connected.
if (fromSlot.dataType == null) return true;

// TE: workaround for not being able to use System.Single as inlets with scripting runtime 4.0
// System.Single is replaced with UnityEngine.WrapMode, check Node.cs:138
if ((fromSlot.dataType == typeof(System.Single)) && toSlot.dataType == typeof(UnityEngine.WrapMode))
return true;

// Apply simple type matching.
return fromSlot.dataType == toSlot.dataType;
}
Expand Down
10 changes: 9 additions & 1 deletion Assets/Klak/Wiring/Editor/Patcher/Node.cs
Original file line number Diff line number Diff line change
Expand Up @@ -131,8 +131,16 @@ void PopulateSlots()
var attrs = prop.GetCustomAttributes(typeof(Wiring.InletAttribute), true);
if (attrs.Length == 0) continue;

var propType = prop.PropertyType;

// TE: workaround for not being able to use System.Single as inlets with scripting runtime 4.0
// System.Single is replaced with UnityEngine.WrapMode. Using WrapMode is arbitrary, just something
// that doesn't cause an assert deep in the graph system.
if (prop.PropertyType == typeof(System.Single))
propType = typeof(UnityEngine.WrapMode);

// Register the setter method as an input slot.
var slot = AddInputSlot("set_" + prop.Name, prop.PropertyType);
var slot = AddInputSlot("set_" + prop.Name, propType);

// Apply the standard nicifying rule.
slot.title = ObjectNames.NicifyVariableName(prop.Name);
Expand Down
184 changes: 156 additions & 28 deletions Assets/Videolab/Videopak/Editor/BuildVideopaks.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,40 +2,168 @@
using UnityEditor;
using System.IO;

public class BuildVideopaks
public class BuildVideopakWindow : EditorWindow
{
[MenuItem ("Assets/Build Videopaks")]
static void BuildAll()
private static VideopakSettings _settings;
int _selectedAssetBundle = 0;
string _outputLog = "";
static string _lastOutputPath = "";

RuntimePlatform[] platforms = { RuntimePlatform.IPhonePlayer, RuntimePlatform.Android, RuntimePlatform.OSXPlayer };
BuildTarget[] targets = { BuildTarget.iOS, BuildTarget.Android, BuildTarget.StandaloneOSX };
string[] platformNames = { "iOS", "Android", "OSX" };

[MenuItem("Assets/Build Videopaks")]
public static void ShowWindow()
{
EditorWindow.GetWindow(typeof(BuildVideopakWindow));
}

public void InitSettings()
{
_settings = null;

var allFound = AssetDatabase.FindAssets("t: VideopakSettings");
if (allFound.Length > 0)
{
var path = AssetDatabase.GUIDToAssetPath(allFound[0]);
_settings = AssetDatabase.LoadAssetAtPath<VideopakSettings>(path);
//Debug.Log("found object " + path + " " + _settings);
}

if (_settings == null)
{
_settings = ScriptableObject.CreateInstance<VideopakSettings>();
_settings.pakName = "videopak";
_settings.author = "user";
AssetDatabase.CreateAsset(_settings, AssetDatabase.GenerateUniqueAssetPath("Assets/VideopakSettings.asset"));
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
}
}

void BuildAssetBundle(string bundleName)
{
string rootDir = EditorUtility.SaveFolderPanel("Select output directory", "", "");
string targetFile = EditorUtility.SaveFilePanel("Select output file", _lastOutputPath, bundleName + ".zpak", "zpak");

if (string.IsNullOrEmpty(rootDir))
if (string.IsNullOrEmpty(targetFile))
return;

foreach (string bundleName in AssetDatabase.GetAllAssetBundleNames())
_lastOutputPath = Path.GetDirectoryName(targetFile);
_outputLog = "";

AssetBundleBuild buildInfo = new AssetBundleBuild();
buildInfo.assetBundleName = bundleName;
buildInfo.assetNames = AssetDatabase.GetAssetPathsFromAssetBundle(bundleName);
AssetBundleBuild[] buildMap = { buildInfo };

PakManifest manifest = new PakManifest(_settings.pakName, _settings.author);
manifest.version = 1;
manifest.unityVersion = Application.unityVersion;

string tmpPath = Path.Combine(FileUtil.GetUniqueTempPathInProject(), bundleName);
Directory.CreateDirectory(tmpPath);

if (_settings.icon != null)
{
// TODO: verify that it's actually a png
string iconPath = Path.Combine(Application.dataPath, "../", AssetDatabase.GetAssetPath(_settings.icon));
File.Copy(iconPath, Path.Combine(tmpPath, "icon.png"));
}

string jsonPath = Path.Combine(tmpPath, "videopak.json");
string json = JsonUtility.ToJson(manifest, true);
File.WriteAllText(jsonPath, json);

for (int i = 0; i < platforms.Length; i++)
{
_outputLog += string.Format("building {0}..\n", platformNames[i]);

string platformStr = VideopakManager.GetPlatformString(platforms[i]);
string platformDir = Path.Combine(tmpPath, platformStr);
Directory.CreateDirectory(platformDir);
BuildPipeline.BuildAssetBundles(platformDir, buildMap, BuildAssetBundleOptions.None, targets[i]);
}

_outputLog += string.Format("compressing..\n");

VideopakManager.CompressPak(tmpPath, targetFile);

_outputLog += string.Format("build succeeded\n\n");
}

private bool ValidatePakName(string pakName)
{
if (string.IsNullOrEmpty(pakName))
return false;

return true;
}

private bool ValidateIcon(Texture2D icon)
{
if (icon == null)
return true;

string ext = Path.GetExtension(AssetDatabase.GetAssetPath(_settings.icon));

return (ext.ToLower() == ".png");
}

void OnGUI()
{
if (_settings == null)
InitSettings();

GUILayout.Label("Settings", EditorStyles.boldLabel);

EditorGUILayout.Space();

var bundleNames = AssetDatabase.GetAllAssetBundleNames();
_selectedAssetBundle = EditorGUILayout.Popup("Choose AssetBundle", _selectedAssetBundle, bundleNames);

EditorGUI.BeginDisabledGroup(bundleNames.Length <= 0);
_settings.pakName = EditorGUILayout.TextField("Name", _settings.pakName);
_settings.author = EditorGUILayout.TextField("Author", _settings.author);
_settings.icon = EditorGUILayout.ObjectField("Icon", _settings.icon, typeof(Texture2D), false) as Texture2D;

EditorUtility.SetDirty(_settings);

EditorGUI.EndDisabledGroup();

EditorGUILayout.Space();

EditorGUILayout.BeginHorizontal();

if (GUILayout.Button("Build"))
{
AssetBundleBuild buildInfo = new AssetBundleBuild();
buildInfo.assetBundleName = bundleName;
buildInfo.assetNames = AssetDatabase.GetAssetPathsFromAssetBundle(bundleName);
AssetBundleBuild[] buildMap = new AssetBundleBuild[] { buildInfo };

string pakDir = rootDir + "/" + bundleName + "/";

string iosDir = pakDir + VideopakManager.GetPlatformString(RuntimePlatform.IPhonePlayer);
Directory.CreateDirectory(iosDir);
BuildPipeline.BuildAssetBundles(iosDir, buildMap, BuildAssetBundleOptions.None, BuildTarget.iOS);

string androidDir = pakDir + VideopakManager.GetPlatformString(RuntimePlatform.Android);
Directory.CreateDirectory(androidDir);
BuildPipeline.BuildAssetBundles(androidDir, buildMap, BuildAssetBundleOptions.None, BuildTarget.Android);

string osxDir = pakDir + VideopakManager.GetPlatformString(RuntimePlatform.OSXPlayer);
Directory.CreateDirectory(osxDir);
#if UNITY_2017_3_OR_NEWER
BuildPipeline.BuildAssetBundles(osxDir, buildMap, BuildAssetBundleOptions.None, BuildTarget.StandaloneOSX);
#else
BuildPipeline.BuildAssetBundles(osxDir, buildMap, BuildAssetBundleOptions.None, BuildTarget.StandaloneOSXUniversal);
#endif

if (_selectedAssetBundle >= bundleNames.Length)
{
_outputLog = "No AssetBundle selected. Aborting..";
}
else if (!ValidatePakName(_settings.pakName))
{
_outputLog = "Invalid pak name. Aborting..";
}
else if (!ValidateIcon(_settings.icon))
{
_outputLog = "Icon is not a png file. Aborting..";
}
else
{
BuildAssetBundle(bundleNames[_selectedAssetBundle]);
GUIUtility.ExitGUI();
}
}

EditorGUILayout.EndHorizontal();

EditorGUILayout.Space();

GUILayout.Label("Output:", EditorStyles.boldLabel);
EditorGUILayout.SelectableLabel(_outputLog, EditorStyles.textArea, GUILayout.ExpandHeight(true));

EditorGUILayout.Space();
}
}
11 changes: 11 additions & 0 deletions Assets/Videolab/Videopak/Editor/VideopakSettings.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using UnityEngine;

public class VideopakSettings : ScriptableObject
{
[HideInInspector]
public string pakName;
[HideInInspector]
public string author;
[HideInInspector]
public Texture2D icon;
}
12 changes: 12 additions & 0 deletions Assets/Videolab/Videopak/Editor/VideopakSettings.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

85 changes: 44 additions & 41 deletions Assets/Videolab/Videopak/VideopakManager.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,17 @@
using UnityEngine;
using UnityEngine.SceneManagement;
using System.IO;
using System.IO.Compression;

public class PakManifest
{
public PakManifest(string _name, string _author) { name = _name; author = _author; }
public string name;
public string token;
public string author;
public string unityVersion;
public int version;
public bool encryption;
}

public class VideopakManager
{
Expand Down Expand Up @@ -31,56 +42,48 @@ public static string GetPlatformString(RuntimePlatform platform)
return null;
}

public static void LoadPak(string pakRoot)
public static void CompressPak(string dir, string zipPath)
{
Unload();

string platform = GetPlatformString(Application.platform);
if (platform == null)
{
Debug.Log("[VideopakManager] Unsupported platform");
return;
}

string pakName = Path.GetFileName(pakRoot);
string path = pakRoot + "/" + platform + "/" + pakName;
#if !UNITY_ANDROID
if (!File.Exists(path))
{
Debug.Log("[VideopakManager] Missing platform payload " + path);
return;
}
#endif
if (File.Exists(zipPath))
File.Delete(zipPath);
ZipFile.CreateFromDirectory(dir, zipPath, System.IO.Compression.CompressionLevel.Fastest, true);
Debug.Log("Compress " + dir + " => " + zipPath);
}

AssetBundle bundle = AssetBundle.LoadFromFile(path);
if (bundle == null)
{
Debug.Log("[VideopakManager] Failed to load videopak " + path);
return;
}
public static void ExtractPak(string zipPath, string dir)
{
if (Directory.Exists(dir))
Directory.Delete(dir, true);
Directory.CreateDirectory(dir);

var scenePaths = bundle.GetAllScenePaths();
if (scenePaths.Length == 0)
{
Debug.Log("[VideopakManager] No scene to load");
return;
}
ZipFile.ExtractToDirectory(zipPath, dir);

SceneManager.LoadScene(scenePaths[0], LoadSceneMode.Additive);
Debug.Log("Extract " + zipPath + " => " + dir);
}

Instance._bundle = bundle;
public static PakManifest ReadManifest(string jsonPath)
{
if (!File.Exists(jsonPath))
return new PakManifest("unknown", "unknown");
string json = File.ReadAllText(jsonPath);
return JsonUtility.FromJson<PakManifest>(json);
}

public static void Unload()
public static void WriteManifest(PakManifest manifest, string jsonPath)
{
AssetBundle bundle = Instance._bundle;
string json = JsonUtility.ToJson(manifest, true);
File.WriteAllText(jsonPath, json);
}

if (bundle != null)
public static string FindPakFolder(string rootFolder)
{
var directories = Directory.GetDirectories(rootFolder);
foreach (var dir in directories)
{
var scenePaths = bundle.GetAllScenePaths();
SceneManager.UnloadScene(scenePaths[0]);

bundle.Unload(true);
if (Path.GetFileName(dir).StartsWith("__", System.StringComparison.InvariantCultureIgnoreCase))
continue;
return dir;
}
return "";
}
}
1 change: 1 addition & 0 deletions Packages/manifest.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"dependencies": {
"com.unity.collab-proxy": "1.2.15",
"com.unity.modules.ai": "1.0.0",
"com.unity.modules.animation": "1.0.0",
"com.unity.modules.assetbundle": "1.0.0",
Expand Down
Loading

0 comments on commit b8fa6a0

Please sign in to comment.