AkiraPixelWind/Assets/Scripts/Editor/AssetBundleBorwer/AssetBundleBuildTab.cs
2022-12-29 18:20:40 +08:00

494 lines
20 KiB
C#
Raw Blame History

using UnityEditor;
using UnityEngine;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using AssetBundleBrowser.AssetBundleDataSource;
namespace AssetBundleBrowser
{
[System.Serializable]
internal class AssetBundleBuildTab
{
const string k_BuildPrefPrefix = "ABBBuild:";
private string m_streamingPath = "Assets/StreamingAssets";
[SerializeField]
private bool m_AdvancedSettings;
[SerializeField]
private Vector2 m_ScrollPosition;
class ToggleData
{
internal ToggleData(bool s,
string title,
string tooltip,
List<string> onToggles,
BuildAssetBundleOptions opt = BuildAssetBundleOptions.None)
{
if (onToggles.Contains(title))
state = true;
else
state = s;
content = new GUIContent(title, tooltip);
option = opt;
}
//internal string prefsKey
//{ get { return k_BuildPrefPrefix + content.text; } }
internal bool state;
internal GUIContent content;
internal BuildAssetBundleOptions option;
}
private AssetBundleInspectTab m_InspectTab;
[SerializeField]
private BuildTabData m_UserData;
List<ToggleData> m_ToggleData;
ToggleData m_ForceRebuild;
ToggleData m_CopyToStreaming;
GUIContent m_TargetContent;
GUIContent m_CompressionContent;
internal enum CompressOptions
{
Uncompressed = 0,
StandardCompression,
ChunkBasedCompression,
}
GUIContent[] m_CompressionOptions =
{
new GUIContent("No Compression"),
new GUIContent("Standard Compression (LZMA)"),
new GUIContent("Chunk Based Compression (LZ4)")
};
int[] m_CompressionValues = { 0, 1, 2 };
internal AssetBundleBuildTab()
{
m_AdvancedSettings = false;
m_UserData = new BuildTabData();
m_UserData.m_OnToggles = new List<string>();
m_UserData.m_UseDefaultPath = true;
}
internal void OnDisable()
{
var dataPath = System.IO.Path.GetFullPath(".");
dataPath = dataPath.Replace("\\", "/");
dataPath += "/Library/AssetBundleBrowserBuild.dat";
BinaryFormatter bf = new BinaryFormatter();
FileStream file = File.Create(dataPath);
bf.Serialize(file, m_UserData);
file.Close();
}
internal void OnEnable(EditorWindow parent)
{
m_InspectTab = (parent as AssetBundleBrowserMain).m_InspectTab;
//LoadData...
var dataPath = System.IO.Path.GetFullPath(".");
dataPath = dataPath.Replace("\\", "/");
dataPath += "/Library/AssetBundleBrowserBuild.dat";
if (File.Exists(dataPath))
{
BinaryFormatter bf = new BinaryFormatter();
FileStream file = File.Open(dataPath, FileMode.Open);
var data = bf.Deserialize(file) as BuildTabData;
if (data != null)
m_UserData = data;
file.Close();
}
m_ToggleData = new List<ToggleData>();
m_ToggleData.Add(new ToggleData(
false,
"Exclude Type Information",
"Do not include type information within the asset bundle (don't write type tree).",
m_UserData.m_OnToggles,
BuildAssetBundleOptions.DisableWriteTypeTree));
m_ToggleData.Add(new ToggleData(
false,
"Force Rebuild",
"Force rebuild the asset bundles",
m_UserData.m_OnToggles,
BuildAssetBundleOptions.ForceRebuildAssetBundle));
m_ToggleData.Add(new ToggleData(
false,
"Ignore Type Tree Changes",
"Ignore the type tree changes when doing the incremental build check.",
m_UserData.m_OnToggles,
BuildAssetBundleOptions.IgnoreTypeTreeChanges));
m_ToggleData.Add(new ToggleData(
false,
"Append Hash",
"Append the hash to the assetBundle name.",
m_UserData.m_OnToggles,
BuildAssetBundleOptions.AppendHashToAssetBundleName));
m_ToggleData.Add(new ToggleData(
false,
"Strict Mode",
"Do not allow the build to succeed if any errors are reporting during it.",
m_UserData.m_OnToggles,
BuildAssetBundleOptions.StrictMode));
m_ToggleData.Add(new ToggleData(
false,
"Dry Run Build",
"Do a dry run build.",
m_UserData.m_OnToggles,
BuildAssetBundleOptions.DryRunBuild));
m_ForceRebuild = new ToggleData(
false,
"Clear Folders",
"Will wipe out all contents of build directory as well as StreamingAssets/AssetBundles if you are choosing to copy build there.",
m_UserData.m_OnToggles);
m_CopyToStreaming = new ToggleData(
false,
"Copy to StreamingAssets",
"After build completes, will copy all build content to " + m_streamingPath + " for use in stand-alone player.",
m_UserData.m_OnToggles);
m_TargetContent = new GUIContent("Build Target", "Choose target platform to build for.");
m_CompressionContent = new GUIContent("Compression", "Choose no compress, standard (LZMA), or chunk based (LZ4)");
if(m_UserData.m_UseDefaultPath)
{
ResetPathToDefault();
}
}
internal void OnGUI()
{
m_ScrollPosition = EditorGUILayout.BeginScrollView(m_ScrollPosition);
bool newState = false;
var centeredStyle = new GUIStyle(GUI.skin.GetStyle("Label"));
centeredStyle.alignment = TextAnchor.UpperCenter;
GUILayout.Label(new GUIContent("Example build setup"), centeredStyle);
//basic options
EditorGUILayout.Space();
GUILayout.BeginVertical();
// build target
using (new EditorGUI.DisabledScope (!AssetBundleModel.Model.DataSource.CanSpecifyBuildTarget)) {
ValidBuildTarget tgt = (ValidBuildTarget)EditorGUILayout.EnumPopup(m_TargetContent, m_UserData.m_BuildTarget);
if (tgt != m_UserData.m_BuildTarget)
{
m_UserData.m_BuildTarget = tgt;
if(m_UserData.m_UseDefaultPath)
{
m_UserData.m_OutputPath = "AssetBundles/";
m_UserData.m_OutputPath += m_UserData.m_BuildTarget.ToString();
//EditorUserBuildSettings.SetPlatformSettings(EditorUserBuildSettings.activeBuildTarget.ToString(), "AssetBundleOutputPath", m_OutputPath);
}
}
}
////output path
using (new EditorGUI.DisabledScope (!AssetBundleModel.Model.DataSource.CanSpecifyBuildOutputDirectory)) {
EditorGUILayout.Space();
GUILayout.BeginHorizontal();
var newPath = EditorGUILayout.TextField("Output Path", m_UserData.m_OutputPath);
if (!System.String.IsNullOrEmpty(newPath) && newPath != m_UserData.m_OutputPath)
{
m_UserData.m_UseDefaultPath = false;
m_UserData.m_OutputPath = newPath;
//EditorUserBuildSettings.SetPlatformSettings(EditorUserBuildSettings.activeBuildTarget.ToString(), "AssetBundleOutputPath", m_OutputPath);
}
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
GUILayout.FlexibleSpace();
if (GUILayout.Button("Browse", GUILayout.MaxWidth(75f)))
BrowseForFolder();
if (GUILayout.Button("Reset", GUILayout.MaxWidth(75f)))
ResetPathToDefault();
//if (string.IsNullOrEmpty(m_OutputPath))
// m_OutputPath = EditorUserBuildSettings.GetPlatformSettings(EditorUserBuildSettings.activeBuildTarget.ToString(), "AssetBundleOutputPath");
GUILayout.EndHorizontal();
EditorGUILayout.Space();
newState = GUILayout.Toggle(
m_ForceRebuild.state,
m_ForceRebuild.content);
if (newState != m_ForceRebuild.state)
{
if (newState)
m_UserData.m_OnToggles.Add(m_ForceRebuild.content.text);
else
m_UserData.m_OnToggles.Remove(m_ForceRebuild.content.text);
m_ForceRebuild.state = newState;
}
newState = GUILayout.Toggle(
m_CopyToStreaming.state,
m_CopyToStreaming.content);
if (newState != m_CopyToStreaming.state)
{
if (newState)
m_UserData.m_OnToggles.Add(m_CopyToStreaming.content.text);
else
m_UserData.m_OnToggles.Remove(m_CopyToStreaming.content.text);
m_CopyToStreaming.state = newState;
}
}
// advanced options
using (new EditorGUI.DisabledScope (!AssetBundleModel.Model.DataSource.CanSpecifyBuildOptions)) {
EditorGUILayout.Space();
m_AdvancedSettings = EditorGUILayout.Foldout(m_AdvancedSettings, "Advanced Settings");
if(m_AdvancedSettings)
{
var indent = EditorGUI.indentLevel;
EditorGUI.indentLevel = 1;
CompressOptions cmp = (CompressOptions)EditorGUILayout.IntPopup(
m_CompressionContent,
(int)m_UserData.m_Compression,
m_CompressionOptions,
m_CompressionValues);
if (cmp != m_UserData.m_Compression)
{
m_UserData.m_Compression = cmp;
}
foreach (var tog in m_ToggleData)
{
newState = EditorGUILayout.ToggleLeft(
tog.content,
tog.state);
if (newState != tog.state)
{
if (newState)
m_UserData.m_OnToggles.Add(tog.content.text);
else
m_UserData.m_OnToggles.Remove(tog.content.text);
tog.state = newState;
}
}
EditorGUILayout.Space();
EditorGUI.indentLevel = indent;
}
}
// build.
EditorGUILayout.Space();
if (GUILayout.Button("Build") )
{
EditorApplication.delayCall += ExecuteBuild;
}
GUILayout.EndVertical();
EditorGUILayout.EndScrollView();
}
private void ExecuteBuild()
{
if (AssetBundleModel.Model.DataSource.CanSpecifyBuildOutputDirectory) {
if (string.IsNullOrEmpty(m_UserData.m_OutputPath))
BrowseForFolder();
if (string.IsNullOrEmpty(m_UserData.m_OutputPath)) //in case they hit "cancel" on the open browser
{
Debug.LogError("AssetBundle Build: No valid output path for build.");
return;
}
if (m_ForceRebuild.state)
{
string message = "Do you want to delete all files in the directory " + m_UserData.m_OutputPath;
if (m_CopyToStreaming.state)
message += " and " + m_streamingPath;
message += "?";
if (EditorUtility.DisplayDialog("File delete confirmation", message, "Yes", "No"))
{
try
{
if (Directory.Exists(m_UserData.m_OutputPath))
Directory.Delete(m_UserData.m_OutputPath, true);
if (m_CopyToStreaming.state)
if (Directory.Exists(m_streamingPath))
Directory.Delete(m_streamingPath, true);
}
catch (System.Exception e)
{
Debug.LogException(e);
}
}
}
if (!Directory.Exists(m_UserData.m_OutputPath))
Directory.CreateDirectory(m_UserData.m_OutputPath);
}
BuildAssetBundleOptions opt = BuildAssetBundleOptions.None;
if (AssetBundleModel.Model.DataSource.CanSpecifyBuildOptions) {
if (m_UserData.m_Compression == CompressOptions.Uncompressed)
opt |= BuildAssetBundleOptions.UncompressedAssetBundle;
else if (m_UserData.m_Compression == CompressOptions.ChunkBasedCompression)
opt |= BuildAssetBundleOptions.ChunkBasedCompression;
foreach (var tog in m_ToggleData)
{
if (tog.state)
opt |= tog.option;
}
}
ABBuildInfo buildInfo = new ABBuildInfo();
buildInfo.outputDirectory = m_UserData.m_OutputPath;
buildInfo.options = opt;
buildInfo.buildTarget = (BuildTarget)m_UserData.m_BuildTarget;
buildInfo.onBuild = (assetBundleName) =>
{
if (m_InspectTab == null)
return;
m_InspectTab.AddBundleFolder(buildInfo.outputDirectory);
m_InspectTab.RefreshBundles();
};
AssetBundleModel.Model.DataSource.BuildAssetBundles (buildInfo);
AssetDatabase.Refresh(ImportAssetOptions.ForceUpdate);
if(m_CopyToStreaming.state)
DirectoryCopy(m_UserData.m_OutputPath, m_streamingPath);
//ǿ<>Ƹ<EFBFBD><C6B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD>Լ<EFBFBD><D4BC><EFBFBD>ͼ<EFBFBD><CDBC>Դ<EFBFBD>ļ<EFBFBD><C4BC><EFBFBD>
CopyConfigFiles();
CopyMapXmlFiles();
}
private void CopyConfigFiles()
{
//configs·<73><C2B7>
string configsPath = "Assets/GameAssets/LubanTables";
string destPath = $"{m_UserData.m_OutputPath}/Configs/DataTables";
DirectoryCopy(configsPath, destPath);
}
private void CopyMapXmlFiles()
{
string configsRootPath = "Assets/GameAssets/Maps";
string destPath = $"{m_UserData.m_OutputPath}/Configs/MapXml";
//<2F><>ȡ<EFBFBD><C8A1><EFBFBD>дμ<D0B4>Ŀ¼
foreach (string folderPath in Directory.GetDirectories(configsRootPath))
{
string mapFolder = $"{folderPath}/XML";
if (!Directory.Exists(mapFolder))
Debug.LogError($"{mapFolder} is not exists");
string mapId = Path.GetFileName(folderPath);
mapFolder = mapFolder.Replace("\\", "/");
DirectoryCopy(mapFolder, $"{destPath}/{mapId}");
}
}
private static void DirectoryCopy(string sourceDirName, string destDirName)
{
// If the destination directory doesn't exist, create it.
if (!Directory.Exists(destDirName))
{
Directory.CreateDirectory(destDirName);
}
foreach (string folderPath in Directory.GetDirectories(sourceDirName, "*", SearchOption.AllDirectories))
{
if (!Directory.Exists(folderPath.Replace(sourceDirName, destDirName)))
Directory.CreateDirectory(folderPath.Replace(sourceDirName, destDirName));
}
foreach (string filePath in Directory.GetFiles(sourceDirName, "*.*", SearchOption.AllDirectories))
{
var fileDirName = Path.GetDirectoryName(filePath).Replace("\\", "/");
var fileName = Path.GetFileName(filePath);
string newFilePath = Path.Combine(fileDirName.Replace(sourceDirName, destDirName), fileName);
if (fileName.EndsWith(".meta"))
continue;
File.Copy(filePath, newFilePath, true);
}
}
private void BrowseForFolder()
{
m_UserData.m_UseDefaultPath = false;
var newPath = EditorUtility.OpenFolderPanel("Bundle Folder", m_UserData.m_OutputPath, string.Empty);
if (!string.IsNullOrEmpty(newPath))
{
var gamePath = System.IO.Path.GetFullPath(".");
gamePath = gamePath.Replace("\\", "/");
if (newPath.StartsWith(gamePath) && newPath.Length > gamePath.Length)
newPath = newPath.Remove(0, gamePath.Length+1);
m_UserData.m_OutputPath = newPath;
//EditorUserBuildSettings.SetPlatformSettings(EditorUserBuildSettings.activeBuildTarget.ToString(), "AssetBundleOutputPath", m_OutputPath);
}
}
private void ResetPathToDefault()
{
m_UserData.m_UseDefaultPath = true;
m_UserData.m_OutputPath = "AssetBundles/";
m_UserData.m_OutputPath += m_UserData.m_BuildTarget.ToString();
//EditorUserBuildSettings.SetPlatformSettings(EditorUserBuildSettings.activeBuildTarget.ToString(), "AssetBundleOutputPath", m_OutputPath);
}
//Note: this is the provided BuildTarget enum with some entries removed as they are invalid in the dropdown
internal enum ValidBuildTarget
{
//NoTarget = -2, --doesn't make sense
//iPhone = -1, --deprecated
//BB10 = -1, --deprecated
//MetroPlayer = -1, --deprecated
StandaloneOSXUniversal = 2,
StandaloneOSXIntel = 4,
StandaloneWindows = 5,
WebPlayer = 6,
WebPlayerStreamed = 7,
iOS = 9,
PS3 = 10,
XBOX360 = 11,
Android = 13,
StandaloneLinux = 17,
StandaloneWindows64 = 19,
WebGL = 20,
WSAPlayer = 21,
StandaloneLinux64 = 24,
StandaloneLinuxUniversal = 25,
WP8Player = 26,
StandaloneOSXIntel64 = 27,
BlackBerry = 28,
Tizen = 29,
PSP2 = 30,
PS4 = 31,
PSM = 32,
XboxOne = 33,
SamsungTV = 34,
N3DS = 35,
WiiU = 36,
tvOS = 37,
Switch = 38
}
[System.Serializable]
internal class BuildTabData
{
internal List<string> m_OnToggles;
internal ValidBuildTarget m_BuildTarget = ValidBuildTarget.StandaloneWindows;
internal CompressOptions m_Compression = CompressOptions.StandardCompression;
internal string m_OutputPath = string.Empty;
internal bool m_UseDefaultPath = true;
}
}
}