diff --git a/CHANGELOG.md b/CHANGELOG.md index a26cf07..c378a2b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,30 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 +## [7.0.0] - 2023-10-03 + +### Added + +- Double-click settings assets to assign them as the active settings in the SuperUnityBuild window. (by [@RobProductions](https://github.com/RobProductions)) +- Customize app build name. (by [@RobProductions](https://github.com/RobProductions)) +- Customize `BuildConstants` file path. (by [@RobProductions](https://github.com/RobProductions)) + +### Changed + +- **Breaking change:** Namespaced generated `BuildConstants` class and enums, added `BuildConstants.scriptingBackend` constant. +- Remove redundant `dataDirNameFormat` variable from Build Platforms. +- Renamed 'Per-Platform' Build Action type to 'Per-Build' to reflect when they are run. +- Enhanced support for string token usage in Build Action configurations. Per-Build actions have gained support for `$BASEPATH` and `$BUILDPATH`, whilst Single Run actions can now use `$VERSION`, `$BUILD`, `$YEAR`, `$MONTH`, `$DAY` and `$TIME`, with the time-based tokens corresponding to the time at which the action was run. +- Scene list UI overhaul. (by [@RobProductions](https://github.com/RobProductions)) +- Release list UI overhaul. (by [@RobProductions](https://github.com/RobProductions)) +- Streamline UI colors. (by [@RobProductions](https://github.com/RobProductions)) +- Replaced the 'Open SuperUnityBuild' button shown in the Inspector for settings assets with new 'Open in SuperUnityBuild' button to assign them as the active settings in the SuperUnityBuild window. (by [@RobProductions](https://github.com/RobProductions)) + +### Fixed + +- Remove dependency on .NET Standard 2.1. (by [@RobProductions](https://github.com/RobProductions)) +- Fix scripting backend not being restored after build. (by [@RobProductions](https://github.com/RobProductions)) + ## [6.0.1] - 2023-05-26 ### Fixed @@ -235,7 +259,8 @@ This release includes all changes from 1.0.0 pre-releases ([1.0.0-pre.1](#100-pr - Fixed issue in Linux build name moving `binaryName` to `BuildArchitecture`. [PR #41](https://github.com/superunitybuild/buildtool/pull/41) - Fixed an issue where custom defines were overwrite when build was finished. [Issue #36](https://github.com/superunitybuild/buildtool/issues/36) -[unreleased]: https://github.com/superunitybuild/buildtool/compare/v6.0.1...HEAD +[unreleased]: https://github.com/superunitybuild/buildtool/compare/v7.0.0...HEAD +[7.0.0]: https://github.com/superunitybuild/buildtool/compare/v6.0.1...v7.0.0 [6.0.1]: https://github.com/superunitybuild/buildtool/compare/v6.0.0...v6.0.1 [6.0.0]: https://github.com/superunitybuild/buildtool/compare/v5.0.4...v6.0.0 [5.0.4]: https://github.com/superunitybuild/buildtool/compare/v5.0.3...v5.0.4 diff --git a/Editor/Build/Action/BuildAction.cs b/Editor/Build/Action/BuildAction.cs index 1b1f085..ad305e6 100644 --- a/Editor/Build/Action/BuildAction.cs +++ b/Editor/Build/Action/BuildAction.cs @@ -10,10 +10,10 @@ public class BuildAction : ScriptableObject // This really should be an abstract public enum ActionType { SingleRun, - PerPlatform + PerBuild } - public ActionType actionType = ActionType.PerPlatform; + public ActionType actionType = ActionType.PerBuild; public string actionName = string.Empty; public string note = string.Empty; public bool actionEnabled = true; @@ -40,6 +40,24 @@ public virtual void PerBuildExecute( { } + public static string ResolveExecuteTokens(string prototype) + { + DateTime runTime = DateTime.Now; + + prototype = TokensUtility.ResolveBuildTimeTokens(prototype, runTime); + prototype = TokensUtility.ResolveBuildVersionTokens(prototype); + + return prototype; + } + + public static string ResolvePerBuildExecuteTokens(string prototype, BuildReleaseType releaseType, BuildPlatform platform, BuildArchitecture architecture, BuildScriptingBackend scriptingBackend, BuildDistribution distribution, DateTime buildTime, string buildPath) + { + prototype = TokensUtility.ResolveBuildOutputTokens(prototype, buildPath); + prototype = TokensUtility.ResolveBuildConfigurationTokens(prototype, releaseType, platform, architecture, scriptingBackend, distribution, buildTime); + + return prototype; + } + public void Draw(SerializedObject obj) { DrawProperties(obj); @@ -57,7 +75,7 @@ public void Draw(SerializedObject obj) else if (isPreBuildAction || isPostBuildAction) actionType = ActionType.SingleRun; else if (isPreBuildPerPlatformAction || isPostBuildPerPlatformAction) - actionType = ActionType.PerPlatform; + actionType = ActionType.PerBuild; if (actionTypeSelectable) actionType = (ActionType)EditorGUILayout.EnumPopup("Action Type", actionType); @@ -67,8 +85,8 @@ public void Draw(SerializedObject obj) EditorGUILayout.PropertyField(obj.FindProperty("note")); - // Only Per-Platform actions can be filtered - if (actionType == ActionType.PerPlatform) + // Only Per-Build actions can be filtered + if (actionType == ActionType.PerBuild) EditorGUILayout.PropertyField(obj.FindProperty("filter"), GUILayout.Height(0)); obj.ApplyModifiedProperties(); diff --git a/Editor/Build/Action/UI/BuildActionListDrawer.cs b/Editor/Build/Action/UI/BuildActionListDrawer.cs index 6639cf1..f22dc32 100644 --- a/Editor/Build/Action/UI/BuildActionListDrawer.cs +++ b/Editor/Build/Action/UI/BuildActionListDrawer.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using UnityEditor; using UnityEngine; diff --git a/Editor/Build/BuildProject.cs b/Editor/Build/BuildProject.cs index 05020ae..e2e8c05 100644 --- a/Editor/Build/BuildProject.cs +++ b/Editor/Build/BuildProject.cs @@ -37,6 +37,13 @@ public static void BuildSingle(string keyChain, BuildOptions options) PerformBuild(buildConfigs, options); } + /// + /// Special user function that runs ConfigureEnvironment on the selected build. + /// Unlike BuildPlayer(), this does not revert previous settings such as PlayerPrefs + /// and instead directly matches the environment and generates BuildConstants. + /// + /// + /// public static void ConfigureEditor(string configKey, BuildOptions options = BuildOptions.None) { DateTime configureTime = DateTime.Now; @@ -53,9 +60,10 @@ public static void ConfigureEditor(string configKey, BuildOptions options = Buil // Parse build config BuildSettings.projectConfigurations.ParseKeychain(configKey, out BuildReleaseType releaseType, out BuildPlatform platform, out BuildArchitecture architecture, out BuildScriptingBackend scriptingBackend, out BuildDistribution distribution); + string constantsFileLocation = BuildSettings.basicSettings.constantsFileLocation; // Configure environment - ConfigureEnvironment(releaseType, platform, architecture, scriptingBackend, distribution, configureTime); + ConfigureEnvironment(releaseType, platform, architecture, scriptingBackend, distribution, configureTime, constantsFileLocation); // Run pre-build actions that have opted in to configuring the Editor BuildAction[] buildActions = BuildSettings.preBuildActions.buildActions.Where(item => item.configureEditor).ToArray(); @@ -70,32 +78,32 @@ public static void ConfigureEditor(string configKey, BuildOptions options = Buil ); } - public static string GenerateDefaultDefines(BuildReleaseType releaseType, BuildPlatform buildPlatform, BuildArchitecture arch, + public static string GenerateDefaultDefines(BuildReleaseType releaseType, BuildPlatform platform, BuildArchitecture arch, BuildScriptingBackend scriptingBackend, BuildDistribution dist) { List defines = new List(); if (releaseType != null) - defines.Add($"{BUILD_TYPE}{SanitizeDefine(releaseType.typeName)}"); + defines.Add($"{BUILD_TYPE}{releaseType.typeName.SanitizeDefine()}"); - if (buildPlatform != null) - defines.Add($"{BUILD_PLATFORM}{SanitizeDefine(buildPlatform.platformName)}"); + if (platform != null) + defines.Add($"{BUILD_PLATFORM}{platform.platformName.SanitizeDefine()}"); if (arch != null) - defines.Add($"{BUILD_ARCH}{SanitizeDefine(arch.name)}"); + defines.Add($"{BUILD_ARCH}{arch.name.SanitizeDefine()}"); if (scriptingBackend != null) - defines.Add($"{BUILD_BACKEND}{SanitizeDefine(scriptingBackend.name)}"); + defines.Add($"{BUILD_BACKEND}{scriptingBackend.name.SanitizeDefine()}"); if (dist != null) - defines.Add($"{BUILD_DIST}{SanitizeDefine(dist.distributionName)}"); + defines.Add($"{BUILD_DIST}{dist.distributionName.SanitizeDefine()}"); if (releaseType != null && !string.IsNullOrEmpty(releaseType.customDefines)) { string[] customDefines = releaseType.customDefines.Split(';', ','); for (int i = 0; i < customDefines.Length; i++) { - defines.Add(SanitizeDefine(customDefines[i])); + defines.Add(customDefines[i].SanitizeDefine()); } } @@ -152,18 +160,22 @@ public static string StripBuildDefines(string defineString) public static string GenerateVersionString(ProductParameters productParameters, DateTime buildTime) { - string prototypeString = productParameters.versionTemplate; - StringBuilder sb = new StringBuilder(prototypeString); + // Increment build number + ++productParameters.buildCounter; + + // Build version string + string prototype = TokensUtility.ResolveBuildNumberToken(productParameters.versionTemplate); + prototype = TokensUtility.ResolveBuildTimeTokens(prototype, buildTime); + + StringBuilder sb = new StringBuilder(prototype); // Regex = (?:\$DAYSSINCE\(")([^"]*)(?:"\)) - Match match = Regex.Match(prototypeString, "(?:\\$DAYSSINCE\\(\")([^\"]*)(?:\"\\))"); + Match match = Regex.Match(prototype, "(?:\\$DAYSSINCE\\(\")([^\"]*)(?:\"\\))"); while (match.Success) { - int daysSince = 0; - if (DateTime.TryParse(match.Groups[1].Value, out DateTime parsedTime)) - { - daysSince = buildTime.Subtract(parsedTime).Days; - } + int daysSince = (DateTime.TryParse(match.Groups[1].Value, out DateTime parsedTime)) ? + buildTime.Subtract(parsedTime).Days : + 0; sb.Replace(match.Captures[0].Value, daysSince.ToString()); match = match.NextMatch(); @@ -174,100 +186,42 @@ public static string GenerateVersionString(ProductParameters productParameters, sb.Replace("$SECONDS", (buildTime.TimeOfDay.TotalSeconds / 15f).ToString("F0")); - sb.Replace("$YEAR", buildTime.ToString("yyyy")); - sb.Replace("$MONTH", buildTime.ToString("MM")); - sb.Replace("$DAY", buildTime.ToString("dd")); - sb.Replace("$TIME", buildTime.ToString("hhmmss")); + string version = sb.ToString(); - sb.Replace("$BUILD", (++productParameters.buildCounter).ToString()); - - string retVal = sb.ToString(); - productParameters.buildVersion = retVal; - PlayerSettings.bundleVersion = retVal; + productParameters.buildVersion = version; + PlayerSettings.bundleVersion = version; // Increment build numbers for supported platforms PlayerSettings.Android.bundleVersionCode = PlayerSettings.Android.bundleVersionCode + 1; PlayerSettings.iOS.buildNumber = $"{int.Parse(PlayerSettings.iOS.buildNumber) + 1}"; PlayerSettings.macOS.buildNumber = $"{int.Parse(PlayerSettings.macOS.buildNumber) + 1}"; - return retVal; + return version; } - public static string GenerateBuildPath(string prototype, BuildReleaseType releaseType, BuildPlatform buildPlatform, BuildArchitecture arch, + public static string GenerateBuildPath(string prototype, BuildReleaseType releaseType, BuildPlatform platform, BuildArchitecture arch, BuildScriptingBackend scriptingBackend, BuildDistribution dist, DateTime buildTime) { - string resolvedProto = ResolvePath(prototype, releaseType, buildPlatform, arch, scriptingBackend, dist, buildTime); - string buildPath = Path.Combine(BuildSettings.basicSettings.baseBuildFolder, resolvedProto); + string resolvedPath = TokensUtility.ResolveBuildConfigurationTokens(prototype, releaseType, platform, arch, scriptingBackend, dist, buildTime); + string buildPath = Path.Combine(BuildSettings.basicSettings.baseBuildFolder, resolvedPath); buildPath = Path.GetFullPath(buildPath).TrimEnd('\\').TrimEnd('/'); return buildPath; } - public static string ResolvePath(string prototype, BuildReleaseType releaseType, BuildPlatform buildPlatform, BuildArchitecture arch, - BuildScriptingBackend scriptingBackend, BuildDistribution dist, DateTime buildTime) - { - StringBuilder sb = new StringBuilder(prototype); - - sb.Replace("$YEAR", buildTime.ToString("yyyy")); - sb.Replace("$MONTH", buildTime.ToString("MM")); - sb.Replace("$DAY", buildTime.ToString("dd")); - sb.Replace("$TIME", buildTime.ToString("hhmmss")); - - string variants = ""; - if (buildPlatform.variants != null && buildPlatform.variants.Length > 0) - variants = buildPlatform.variantKey.Replace(",", ", "); - - sb.Replace("$RELEASE_TYPE", SanitizeFolderName(releaseType.typeName)); - sb.Replace("$PLATFORM", SanitizeFolderName(buildPlatform.platformName)); - sb.Replace("$ARCHITECTURE", SanitizeFolderName(arch.name)); - sb.Replace("$VARIANTS", SanitizeFolderName(variants)); - sb.Replace("$DISTRIBUTION", SanitizeFolderName(dist != null ? dist.distributionName : "")); - sb.Replace("$VERSION", SanitizeFolderName(BuildSettings.productParameters.buildVersion)); - sb.Replace("$BUILD", BuildSettings.productParameters.buildCounter.ToString()); - sb.Replace("$PRODUCT_NAME", SanitizeFolderName(releaseType.productName)); - sb.Replace("$SCRIPTING_BACKEND", SanitizeFolderName(scriptingBackend.name)); - - return sb.ToString(); - } - - // TODO: Convert sanitize string methods into extensions. - public static string SanitizeCodeString(string str) - { - str = Regex.Replace(str, "[^a-zA-Z0-9_]", "_", RegexOptions.Compiled); - - if (char.IsDigit(str[0])) - str = "_" + str; - - return str; - } - - public static string SanitizeDefine(string input) - { - return SanitizeCodeString(input.ToUpper().Replace(" ", "")); - } - - public static string SanitizeFolderName(string folderName) - { - string invalidChars = Regex.Escape(new string(Path.GetInvalidFileNameChars()) + new string(Path.GetInvalidPathChars())); - string invalidRegStr = string.Format(@"[{0}]", invalidChars); - - return Regex.Replace(folderName, invalidRegStr, ""); - } - - public static string SanitizeFileName(string fileName) - { - string invalidChars = Regex.Escape(new string(Path.GetInvalidFileNameChars())); - string invalidRegStr = string.Format(@"([{0}]*\.+$)|([{0}]+)", invalidChars); - - return Regex.Replace(fileName, invalidRegStr, "_"); - } - public static void SetEditorBuildSettingsScenes(BuildReleaseType releaseType) { // Create EditorBuildSettingsScene instances from release type scene list - List editorBuildSettingsScenes = releaseType.sceneList.GetSceneFileList() - .Select(path => new EditorBuildSettingsScene(path, true)) - .ToList(); + List editorBuildSettingsScenes = new List(); + + var releaseScenes = releaseType.sceneList.releaseScenes; + for (int i = 0; i < releaseScenes.Count; i++) + { + var thisScene = releaseScenes[i]; + editorBuildSettingsScenes.Add( + new EditorBuildSettingsScene(releaseType.sceneList.SceneGUIDToPath(thisScene.fileGUID), + thisScene.sceneActive)); + } // Set the Build Settings scene list EditorBuildSettings.scenes = editorBuildSettingsScenes.ToArray(); @@ -278,7 +232,7 @@ public static void SetEditorBuildSettingsScenes(BuildReleaseType releaseType) #region Private Methods private static void ConfigureEnvironment(BuildReleaseType releaseType, BuildPlatform platform, BuildArchitecture architecture, - BuildScriptingBackend scriptingBackend, BuildDistribution distribution, DateTime buildTime) + BuildScriptingBackend scriptingBackend, BuildDistribution distribution, DateTime buildTime, string constantsFileLocation) { // Switch to target build platform EditorUserBuildSettings.SwitchActiveBuildTarget(platform.targetGroup, architecture.target); @@ -304,7 +258,8 @@ private static void ConfigureEnvironment(BuildReleaseType releaseType, BuildPlat platform.ApplyVariant(); // Generate BuildConstants - BuildConstantsGenerator.Generate(buildTime, BuildSettings.productParameters.buildVersion, releaseType, platform, architecture, distribution); + BuildConstantsGenerator.Generate(buildTime, constantsFileLocation, BuildSettings.productParameters.buildVersion, + releaseType, platform, scriptingBackend, architecture, distribution); // Refresh scene list to make sure nothing has been deleted or moved releaseType.sceneList.Refresh(); @@ -363,9 +318,11 @@ private static void PerformBuild(string[] buildConfigs, BuildOptions options = B // Parse build config and perform build. string notification = string.Format("Building ({0}/{1}): ", i + 1, buildConfigs.Length); + string constantsFileLocation = BuildSettings.basicSettings.constantsFileLocation; BuildSettings.projectConfigurations.ParseKeychain(configKey, out BuildReleaseType releaseType, out BuildPlatform platform, out BuildArchitecture arch, out BuildScriptingBackend scriptingBackend, out BuildDistribution dist); - bool success = BuildPlayer(notification, releaseType, platform, arch, scriptingBackend, dist, buildTime, options, configKey); + bool success = BuildPlayer(notification, releaseType, platform, arch, scriptingBackend, dist, buildTime, options, + constantsFileLocation, configKey); if (success) ++successCount; @@ -424,25 +381,34 @@ private static void PerformBuild(string[] buildConfigs, BuildOptions options = B } private static bool BuildPlayer(string notification, BuildReleaseType releaseType, BuildPlatform platform, BuildArchitecture architecture, - BuildScriptingBackend scriptingBackend, BuildDistribution distribution, DateTime buildTime, BuildOptions options, string configKey) + BuildScriptingBackend scriptingBackend, BuildDistribution distribution, DateTime buildTime, BuildOptions options, + string constantsFileLocation, string configKey) { bool success = true; if (options == BuildOptions.None) + { options = releaseType.buildOptions; + } // Save current environment settings string preBuildDefines = PlayerSettings.GetScriptingDefineSymbolsForGroup(platform.targetGroup); string preBuildCompanyName = PlayerSettings.companyName; string preBuildProductName = PlayerSettings.productName; string preBuildBundleIdentifier = PlayerSettings.GetApplicationIdentifier(platform.targetGroup); + ScriptingImplementation preBuildImplementation = PlayerSettings.GetScriptingBackend(platform.targetGroup); // Configure environment settings to match the build configuration - ConfigureEnvironment(releaseType, platform, architecture, scriptingBackend, distribution, buildTime); + ConfigureEnvironment(releaseType, platform, architecture, scriptingBackend, distribution, buildTime, constantsFileLocation); // Generate build path string buildPath = GenerateBuildPath(BuildSettings.basicSettings.buildPath, releaseType, platform, architecture, scriptingBackend, distribution, buildTime); - string binName = string.Format(architecture.binaryNameFormat, SanitizeFileName(releaseType.productName)); + string finalBuildName = releaseType.productName; + if(!releaseType.syncAppNameWithProduct) + { + finalBuildName = releaseType.appBuildName; + } + string binName = string.Format(architecture.binaryNameFormat, finalBuildName.SanitizeFileName()); // Pre-build actions PerformPreBuild(releaseType, platform, architecture, scriptingBackend, distribution, buildTime, ref options, configKey, buildPath); @@ -462,12 +428,14 @@ private static bool BuildPlayer(string notification, BuildReleaseType releaseTyp { locationPathName = Path.Combine(buildPath, binName), options = options, - scenes = releaseType.sceneList.GetSceneFileList(), + scenes = releaseType.sceneList.GetActiveSceneFileList(), target = architecture.target }); if (buildReport.summary.result == BuildResult.Failed) + { error = buildReport.summary.totalErrors + " occurred."; + } if (!string.IsNullOrEmpty(error)) { @@ -487,6 +455,7 @@ private static bool BuildPlayer(string notification, BuildReleaseType releaseTyp PlayerSettings.companyName = preBuildCompanyName; PlayerSettings.productName = preBuildProductName; PlayerSettings.SetApplicationIdentifier(platform.targetGroup, preBuildBundleIdentifier); + PlayerSettings.SetScriptingBackend(platform.targetGroup, preBuildImplementation); return success; } @@ -600,7 +569,7 @@ private static void PerformBuildActions( // Check if execute method has been overriden. MethodInfo m = action.GetType().GetMethod("PerBuildExecute"); - if (m.GetBaseDefinition().DeclaringType != m.DeclaringType && action.actionType == BuildAction.ActionType.PerPlatform) + if (m.GetBaseDefinition().DeclaringType != m.DeclaringType && action.actionType == BuildAction.ActionType.PerBuild) { // Check build filter and execute if true. if (action.filter == null || action.filter.Evaluate(releaseType, platform, architecture, distribution, configKey) && action.actionEnabled) diff --git a/Editor/Build/Platform/BuildAndroid.cs b/Editor/Build/Platform/BuildAndroid.cs index 7b5916f..5c25850 100644 --- a/Editor/Build/Platform/BuildAndroid.cs +++ b/Editor/Build/Platform/BuildAndroid.cs @@ -16,7 +16,6 @@ public class BuildAndroid : BuildPlatform {BinaryType.SplitAPK, "{0}"}, {BinaryType.AAB, "{0}.aab"}, }; - private const string _dataDirNameFormat = "{0}_Data"; private const BuildTargetGroup _targetGroup = BuildTargetGroup.Android; private const string _apkExpansionFilesTypeVariantId = "APK Expansion Type"; @@ -60,7 +59,6 @@ public BuildAndroid() public override void Init() { platformName = _name; - dataDirNameFormat = _dataDirNameFormat; targetGroup = _targetGroup; if (architectures == null || architectures.Length == 0) @@ -95,7 +93,7 @@ public override void Init() variants = new BuildVariant[] { new BuildVariant(_deviceTypeVariantId, EnumNamesToArray() .Skip(1) - .SkipLast(1) + .SkipLast() .ToArray(), 0, true), new BuildVariant(_textureCompressionVariantId, EnumNamesToArray(), 0), diff --git a/Editor/Build/Platform/BuildIOS.cs b/Editor/Build/Platform/BuildIOS.cs index 130f4c3..316446e 100644 --- a/Editor/Build/Platform/BuildIOS.cs +++ b/Editor/Build/Platform/BuildIOS.cs @@ -10,7 +10,6 @@ public class BuildIOS : BuildPlatform private const string _name = "iOS"; private const string _binaryNameFormat = ""; - private const string _dataDirNameFormat = "{0}_Data"; private const BuildTargetGroup _targetGroup = BuildTargetGroup.iOS; private const string _deviceTypeVariantId = "Device Type"; @@ -28,7 +27,6 @@ public BuildIOS() public override void Init() { platformName = _name; - dataDirNameFormat = _dataDirNameFormat; targetGroup = _targetGroup; if (architectures == null || architectures.Length == 0) diff --git a/Editor/Build/Platform/BuildLinux.cs b/Editor/Build/Platform/BuildLinux.cs index a876028..42acdc1 100644 --- a/Editor/Build/Platform/BuildLinux.cs +++ b/Editor/Build/Platform/BuildLinux.cs @@ -9,7 +9,6 @@ public class BuildLinux : BuildPlatform #region Constants private const string _name = "Linux"; - private const string _dataDirNameFormat = "{0}_Data"; private const BuildTargetGroup _targetGroup = BuildTargetGroup.Standalone; #endregion @@ -23,7 +22,6 @@ public BuildLinux() public override void Init() { platformName = _name; - dataDirNameFormat = _dataDirNameFormat; targetGroup = _targetGroup; if (architectures == null || architectures.Length == 0) diff --git a/Editor/Build/Platform/BuildOSX.cs b/Editor/Build/Platform/BuildOSX.cs index 5a1af10..2979d83 100644 --- a/Editor/Build/Platform/BuildOSX.cs +++ b/Editor/Build/Platform/BuildOSX.cs @@ -14,7 +14,6 @@ public class BuildOSX : BuildPlatform {BuildOutputType.App, "{0}.app"}, {BuildOutputType.XcodeProject, "{0}"}, }; - private const string _dataDirNameFormat = "{0}.app/Contents"; private const BuildTargetGroup _targetGroup = BuildTargetGroup.Standalone; private const string _buildOutputTypeVariantId = "Build Output"; @@ -46,7 +45,6 @@ public BuildOSX() public override void Init() { platformName = _name; - dataDirNameFormat = _dataDirNameFormat; targetGroup = _targetGroup; if (architectures == null || architectures.Length == 0) diff --git a/Editor/Build/Platform/BuildPC.cs b/Editor/Build/Platform/BuildPC.cs index 37d4d16..d22b2b4 100644 --- a/Editor/Build/Platform/BuildPC.cs +++ b/Editor/Build/Platform/BuildPC.cs @@ -14,7 +14,6 @@ public class BuildPC : BuildPlatform {BuildOutputType.App, "{0}.exe"}, {BuildOutputType.VisualStudioSolution, "{0}.sln"}, }; - private const string _dataDirNameFormat = "{0}_Data"; private const BuildTargetGroup _targetGroup = BuildTargetGroup.Standalone; private const string _buildOutputTypeVariantId = "Build Output"; @@ -36,7 +35,6 @@ public BuildPC() public override void Init() { platformName = _name; - dataDirNameFormat = _dataDirNameFormat; targetGroup = _targetGroup; if (architectures == null || architectures.Length == 0) diff --git a/Editor/Build/Platform/BuildPlatform.cs b/Editor/Build/Platform/BuildPlatform.cs index fd4e92c..54b0c9e 100644 --- a/Editor/Build/Platform/BuildPlatform.cs +++ b/Editor/Build/Platform/BuildPlatform.cs @@ -16,7 +16,6 @@ public class BuildPlatform : ScriptableObject public BuildScriptingBackend[] scriptingBackends = new BuildScriptingBackend[0]; public string platformName; - public string dataDirNameFormat; public BuildTargetGroup targetGroup; public virtual void Init() @@ -192,7 +191,7 @@ public void Draw(SerializedObject obj) GUILayout.BeginHorizontal(); distEnabled.boolValue = GUILayout.Toggle(distEnabled.boolValue, GUIContent.none, GUILayout.ExpandWidth(false)); - distName.stringValue = BuildProject.SanitizeFolderName(GUILayout.TextField(distName.stringValue)); + distName.stringValue = GUILayout.TextField(distName.stringValue.SanitizeFolderName()); if (UnityBuildGUIUtility.DeleteButton()) distList.SafeDeleteArrayElementAtIndex(i); diff --git a/Editor/Build/Platform/BuildUWP.cs b/Editor/Build/Platform/BuildUWP.cs index d9ddced..87eabb8 100644 --- a/Editor/Build/Platform/BuildUWP.cs +++ b/Editor/Build/Platform/BuildUWP.cs @@ -11,7 +11,6 @@ public class BuildUWP : BuildPlatform private const string _name = "UWP"; private const string _binaryNameFormat = ""; - private const string _dataDirNameFormat = "{0}_Data"; private const BuildTargetGroup _targetGroup = BuildTargetGroup.WSA; private const string _architectureVariantId = "Architecture"; @@ -30,7 +29,6 @@ public BuildUWP() public override void Init() { platformName = _name; - dataDirNameFormat = _dataDirNameFormat; targetGroup = _targetGroup; if (architectures == null || architectures.Length == 0) diff --git a/Editor/Build/Platform/BuildVariant.cs b/Editor/Build/Platform/BuildVariant.cs index 488f90e..7f4c082 100644 --- a/Editor/Build/Platform/BuildVariant.cs +++ b/Editor/Build/Platform/BuildVariant.cs @@ -24,7 +24,7 @@ public string variantKey { get { - return isFlag ? string.Join('+', flags) : values[selectedIndex]; + return isFlag ? string.Join("+", flags) : values[selectedIndex]; } } @@ -64,7 +64,7 @@ List ConvertFlagsToSelectedIndexList(int number) public override string ToString() { - return isFlag ? string.Join('+', flags) : values[selectedIndex]; + return isFlag ? string.Join("+", flags) : values[selectedIndex]; } } } diff --git a/Editor/Build/Platform/BuildWebGL.cs b/Editor/Build/Platform/BuildWebGL.cs index 1ab278b..347736b 100644 --- a/Editor/Build/Platform/BuildWebGL.cs +++ b/Editor/Build/Platform/BuildWebGL.cs @@ -10,7 +10,6 @@ public class BuildWebGL : BuildPlatform private const string _name = "WebGL"; private const string _binaryNameFormat = "{0}"; - private const string _dataDirNameFormat = "{0}_Data"; private const BuildTargetGroup _targetGroup = BuildTargetGroup.WebGL; #endregion @@ -24,7 +23,6 @@ public BuildWebGL() public override void Init() { platformName = _name; - dataDirNameFormat = _dataDirNameFormat; targetGroup = _targetGroup; if (architectures == null || architectures.Length == 0) diff --git a/Editor/Build/Platform/UI/BuildPlatformDrawer.cs b/Editor/Build/Platform/UI/BuildPlatformDrawer.cs index 602c41c..8280787 100644 --- a/Editor/Build/Platform/UI/BuildPlatformDrawer.cs +++ b/Editor/Build/Platform/UI/BuildPlatformDrawer.cs @@ -79,7 +79,7 @@ public override void OnGUI(Rect position, SerializedProperty property, GUIConten GUILayout.BeginHorizontal(); distEnabled.boolValue = GUILayout.Toggle(distEnabled.boolValue, GUIContent.none, GUILayout.ExpandWidth(false)); - distName.stringValue = BuildProject.SanitizeFolderName(GUILayout.TextField(distName.stringValue)); + distName.stringValue = GUILayout.TextField(distName.stringValue.SanitizeFolderName()); if (UnityBuildGUIUtility.DeleteButton()) distList.SafeDeleteArrayElementAtIndex(i); diff --git a/Editor/Build/Platform/UI/BuildPlatformListDrawer.cs b/Editor/Build/Platform/UI/BuildPlatformListDrawer.cs index 4313ef7..5f5c972 100644 --- a/Editor/Build/Platform/UI/BuildPlatformListDrawer.cs +++ b/Editor/Build/Platform/UI/BuildPlatformListDrawer.cs @@ -80,19 +80,19 @@ private void DrawPlatforms(SerializedProperty property) { SerializedProperty listEntry = list.GetArrayElementAtIndex(i); - BuildPlatform buildPlatform = listEntry.objectReferenceValue as BuildPlatform; - if (buildPlatform == null) + BuildPlatform platform = listEntry.objectReferenceValue as BuildPlatform; + if (platform == null) { list.SafeDeleteArrayElementAtIndex(i); --i; continue; } - SerializedObject serializedBuildPlatform = new SerializedObject(buildPlatform); + SerializedObject serializedBuildPlatform = new SerializedObject(platform); EditorGUILayout.BeginHorizontal(); bool show = listEntry.isExpanded; - string tooltip = buildPlatform.ToString(); + string tooltip = platform.ToString(); string text = UnityBuildGUIUtility.ToLabel(tooltip); UnityBuildGUIUtility.DropdownHeader(new GUIContent(text, tooltip), ref show, false, GUILayout.ExpandWidth(true)); @@ -101,10 +101,10 @@ private void DrawPlatforms(SerializedProperty property) if (UnityBuildGUIUtility.DeleteButton()) { - List buildPlatforms = BuildSettings.platformList.platforms; + List platforms = BuildSettings.platformList.platforms; // Destroy underlying object - ScriptableObject.DestroyImmediate(buildPlatforms[i], true); + ScriptableObject.DestroyImmediate(platforms[i], true); AssetDatabaseUtility.ImportAsset(AssetDatabase.GetAssetPath(BuildSettings.instance)); // Remove object reference from list @@ -114,10 +114,10 @@ private void DrawPlatforms(SerializedProperty property) EditorGUILayout.EndHorizontal(); - if (show && buildPlatform.enabled) + if (show && platform.enabled) { EditorGUILayout.BeginVertical(UnityBuildGUIUtility.dropdownContentStyle); - buildPlatform.Draw(serializedBuildPlatform); + platform.Draw(serializedBuildPlatform); EditorGUILayout.EndVertical(); } } diff --git a/Editor/Build/Settings/BaseSettings.cs b/Editor/Build/Settings/BaseSettings.cs index 2678261..c5e0737 100644 --- a/Editor/Build/Settings/BaseSettings.cs +++ b/Editor/Build/Settings/BaseSettings.cs @@ -1,4 +1,4 @@ -using System.IO; +using System.IO; using UnityEditor; using UnityEngine; @@ -19,20 +19,22 @@ protected static T CreateAsset(string assetName) where T : BaseSettings defaultAssetPath; string assetPath = File.Exists(prefsAssetPath) ? prefsAssetPath : defaultAssetPath; - T instance = AssetDatabase.LoadAssetAtPath(assetPath) as T; + T instance = AssetDatabase.LoadAssetAtPath(assetPath); if (instance == null) { + //Create the default settings file Debug.Log($"SuperUnityBuild: Creating settings file: {defaultAssetPath}"); instance = CreateInstance(); instance.name = assetName; - AssetDatabaseUtility.EnsureDirectoriesExist(); + AssetDatabaseUtility.EnsureDefaultDirectoriesExist(); AssetDatabase.CreateAsset(instance, defaultAssetPath); } return instance; } + } } diff --git a/Editor/Build/Settings/BasicSettings.cs b/Editor/Build/Settings/BasicSettings.cs index 6440799..4113d5a 100644 --- a/Editor/Build/Settings/BasicSettings.cs +++ b/Editor/Build/Settings/BasicSettings.cs @@ -1,4 +1,5 @@ -using System; +using System; +using System.IO; using UnityEngine; namespace SuperUnityBuild.BuildTool @@ -8,7 +9,11 @@ public class BasicSettings { [FilePath(true, true, "Choose location for build output")] public string baseBuildFolder = "Builds"; - [Tooltip("Recognized tokens for the build path: $YEAR, $MONTH, $DAY, $TIME, $RELEASE_TYPE, $PLATFORM, $ARCHITECTURE, $VARIANTS, $DISTRIBUTION, $VERSION, $BUILD, $PRODUCT_NAME, $SCRIPTING_BACKEND")] public string buildPath = "$VERSION/$RELEASE_TYPE/$PLATFORM/$ARCHITECTURE/$SCRIPTING_BACKEND"; + [Tooltip("Recognized tokens for the build path: $YEAR, $MONTH, $DAY, $TIME, $RELEASE_TYPE, $PLATFORM, $ARCHITECTURE, $VARIANTS, $DISTRIBUTION, $VERSION, $BUILD, $PRODUCT_NAME, $SCRIPTING_BACKEND")] + public string buildPath = "$VERSION/$RELEASE_TYPE/$PLATFORM/$ARCHITECTURE/$SCRIPTING_BACKEND"; public bool openFolderPostBuild = true; + [Tooltip("The folder path for the " + BuildConstantsGenerator.FileName + " file which will be generated on build. Use the Configure Editor Environment button on a selected configuration to generate it now.")] + [FilePath(true, true, "Choose folder location for the " + BuildConstantsGenerator.FileName + " file")] + public string constantsFileLocation = Path.Combine(Constants.AssetsDirectoryName, Constants.RootDirectoryName); } } diff --git a/Editor/Build/Settings/BuildReleaseType.cs b/Editor/Build/Settings/BuildReleaseType.cs index 3a2c9ba..0df3c7b 100644 --- a/Editor/Build/Settings/BuildReleaseType.cs +++ b/Editor/Build/Settings/BuildReleaseType.cs @@ -13,6 +13,9 @@ public class BuildReleaseType public string companyName = string.Empty; public string productName = string.Empty; + public bool syncAppNameWithProduct = true; + public string appBuildName = string.Empty; + public BuildOptions buildOptions; public string customDefines = string.Empty; diff --git a/Editor/Build/Settings/BuildSettings.cs b/Editor/Build/Settings/BuildSettings.cs index dca3b4f..2362864 100644 --- a/Editor/Build/Settings/BuildSettings.cs +++ b/Editor/Build/Settings/BuildSettings.cs @@ -1,5 +1,6 @@ -using System; +using System; using UnityEditor; +using UnityEditor.Callbacks; using UnityEngine; namespace SuperUnityBuild.BuildTool @@ -17,7 +18,9 @@ public static BuildSettings instance get { if (_instance == null) + { _instance = CreateAsset(Constants.DefaultSettingsFileName); + } return _instance; } @@ -73,5 +76,48 @@ public static void Init() public static BuildActionList postBuildActions { get => instance._postBuildActions; } #endregion + + #region Events + + [OnOpenAssetAttribute(1)] + public static bool HandleOpenAsset(int instanceID, int line) + { + var assetPath = AssetDatabase.GetAssetPath(instanceID); + if(assetPath == null) + { + //Asset did not exist + return false; + } + var asset = AssetDatabase.LoadAssetAtPath(assetPath); + if(asset == null) + { + //Not the right type + return false; + } + + asset.OpenInUnityBuildWindow(); + + return true; + } + + public void OpenInUnityBuildWindow() + { + //Show the window using the same process as pressing the menu button + UnityBuildWindow.ShowWindow(); + var thisWindow = EditorWindow.GetWindow(); + if (thisWindow != null) + { + //If the window exists + + //Set this as the current BuildSettings to be used + BuildSettings.instance = this; + + //Tell the window to use the new settings + thisWindow.RefreshSelectedBuildSettings(); + } + + } + + #endregion } } diff --git a/Editor/Build/Settings/SceneList.cs b/Editor/Build/Settings/SceneList.cs index 778c01e..a2f4244 100644 --- a/Editor/Build/Settings/SceneList.cs +++ b/Editor/Build/Settings/SceneList.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.IO; using UnityEditor; @@ -8,7 +8,7 @@ namespace SuperUnityBuild.BuildTool [Serializable] public class SceneList { - public List enabledScenes = new List(); + public List releaseScenes = new List(); public SceneList() { @@ -17,34 +17,53 @@ public SceneList() public void Refresh() { // Verify that all scenes in list still exist. - for (int i = 0; i < enabledScenes.Count; i++) + for (int i = 0; i < releaseScenes.Count; i++) { - string sceneGUID = enabledScenes[i].fileGUID; + string sceneGUID = releaseScenes[i].fileGUID; string sceneFilepath = AssetDatabase.GUIDToAssetPath(sceneGUID); if (string.IsNullOrEmpty(sceneFilepath) || !File.Exists(sceneFilepath)) { - enabledScenes.RemoveAt(i); + releaseScenes.RemoveAt(i); --i; } } } - public string[] GetSceneFileList() + public string[] GetActiveSceneFileList() { List scenes = new List(); - for (int i = 0; i < enabledScenes.Count; i++) + for (int i = 0; i < releaseScenes.Count; i++) { - scenes.Add(AssetDatabase.GUIDToAssetPath(enabledScenes[i].fileGUID)); + var thisScene = releaseScenes[i]; + if(!thisScene.sceneActive) + { + //Don't return inactive scenes + continue; + } + scenes.Add(SceneGUIDToPath(thisScene.fileGUID)); } return scenes.ToArray(); } + public string SceneGUIDToPath(string guid) + { + return AssetDatabase.GUIDToAssetPath(guid); + } + [Serializable] public class Scene { + /// + /// File location of the scene starting from Project Root + /// public string fileGUID = string.Empty; + /// + /// Whether the scene should be included in the final build. + /// A user could leave this toggle in order to easily add/remove it later. + /// + public bool sceneActive = true; } } } diff --git a/Editor/Build/Settings/UI/BasicSettingsDrawer.cs b/Editor/Build/Settings/UI/BasicSettingsDrawer.cs index 16f4bdc..43c68ff 100644 --- a/Editor/Build/Settings/UI/BasicSettingsDrawer.cs +++ b/Editor/Build/Settings/UI/BasicSettingsDrawer.cs @@ -1,4 +1,4 @@ -using System.IO; +using System.IO; using UnityEditor; using UnityEngine; @@ -61,6 +61,11 @@ public override void OnGUI(Rect position, SerializedProperty property, GUIConten System.Diagnostics.Process.Start(path); } + GUILayout.Space(20); + GUILayout.Label("Build Constants Options", UnityBuildGUIUtility.midHeaderStyle); + + EditorGUILayout.PropertyField(property.FindPropertyRelative("constantsFileLocation")); + property.serializedObject.ApplyModifiedProperties(); EditorGUILayout.EndVertical(); diff --git a/Editor/Build/Settings/UI/BuildReleaseTypeDrawer.cs b/Editor/Build/Settings/UI/BuildReleaseTypeDrawer.cs index b473fc7..20d41c9 100644 --- a/Editor/Build/Settings/UI/BuildReleaseTypeDrawer.cs +++ b/Editor/Build/Settings/UI/BuildReleaseTypeDrawer.cs @@ -18,10 +18,28 @@ public override void OnGUI(Rect position, SerializedProperty property, GUIConten // Event.current.character = '\0'; //} + EditorGUILayout.BeginHorizontal(); bool show = property.isExpanded; UnityBuildGUIUtility.DropdownHeader(property.FindPropertyRelative("typeName").stringValue, ref show, false); property.isExpanded = show; + if (UnityBuildGUIUtility.DeleteButton()) + { + BuildReleaseType[] types = BuildSettings.releaseTypeList.releaseTypes; + for (int i = 0; i < types.Length; i++) + { + if (types[i].typeName == property.FindPropertyRelative("typeName").stringValue) + { + ArrayUtility.RemoveAt(ref BuildSettings.releaseTypeList.releaseTypes, i); + GUIUtility.keyboardControl = 0; + break; + } + } + show = false; + } + + EditorGUILayout.EndHorizontal(); + if (show) { EditorGUILayout.BeginVertical(UnityBuildGUIUtility.dropdownContentStyle); @@ -32,12 +50,23 @@ public override void OnGUI(Rect position, SerializedProperty property, GUIConten EditorGUILayout.BeginHorizontal(); EditorGUILayout.PrefixLabel("Type Name"); - typeName.stringValue = BuildProject.SanitizeFolderName(GUILayout.TextArea(typeName.stringValue)); + typeName.stringValue = GUILayout.TextArea(typeName.stringValue.SanitizeFolderName()); EditorGUILayout.EndHorizontal(); + var productNameProperty = property.FindPropertyRelative("productName"); EditorGUILayout.PropertyField(property.FindPropertyRelative("bundleIdentifier")); - EditorGUILayout.PropertyField(property.FindPropertyRelative("productName")); + EditorGUILayout.PropertyField(productNameProperty); EditorGUILayout.PropertyField(property.FindPropertyRelative("companyName")); + var syncAppNameProperty = property.FindPropertyRelative("syncAppNameWithProduct"); + var appBuildNameProperty = property.FindPropertyRelative("appBuildName"); + EditorGUILayout.PropertyField(syncAppNameProperty, new GUIContent("Sync App Build Name")); + EditorGUI.BeginDisabledGroup(syncAppNameProperty.boolValue); + if(syncAppNameProperty.boolValue) + { + appBuildNameProperty.stringValue = productNameProperty.stringValue; + } + EditorGUILayout.PropertyField(appBuildNameProperty); + EditorGUI.EndDisabledGroup(); GUILayout.Space(20); GUILayout.Label("Build Options", UnityBuildGUIUtility.midHeaderStyle); @@ -69,20 +98,6 @@ public override void OnGUI(Rect position, SerializedProperty property, GUIConten EditorGUILayout.PropertyField(property.FindPropertyRelative("sceneList")); - if (GUILayout.Button("Delete", GUILayout.ExpandWidth(true))) - { - BuildReleaseType[] types = BuildSettings.releaseTypeList.releaseTypes; - for (int i = 0; i < types.Length; i++) - { - if (types[i].typeName == property.FindPropertyRelative("typeName").stringValue) - { - ArrayUtility.RemoveAt(ref BuildSettings.releaseTypeList.releaseTypes, i); - GUIUtility.keyboardControl = 0; - break; - } - } - } - property.serializedObject.ApplyModifiedProperties(); EditorGUILayout.EndVertical(); diff --git a/Editor/Build/Settings/UI/BuildReleaseTypeListDrawer.cs b/Editor/Build/Settings/UI/BuildReleaseTypeListDrawer.cs index ce1e3b4..4e147fa 100644 --- a/Editor/Build/Settings/UI/BuildReleaseTypeListDrawer.cs +++ b/Editor/Build/Settings/UI/BuildReleaseTypeListDrawer.cs @@ -1,4 +1,4 @@ -using UnityEditor; +using UnityEditor; using UnityEngine; namespace SuperUnityBuild.BuildTool @@ -47,6 +47,8 @@ public override void OnGUI(Rect position, SerializedProperty property, GUIConten addedEntry.FindPropertyRelative("productName").stringValue = Application.productName; addedEntry.FindPropertyRelative("bundleIdentifier").stringValue = Application.identifier; addedEntry.FindPropertyRelative("companyName").stringValue = Application.companyName; + addedEntry.FindPropertyRelative("appBuildName").stringValue = Application.productName; + addedEntry.FindPropertyRelative("syncAppNameWithProduct").boolValue = true; list.serializedObject.ApplyModifiedProperties(); diff --git a/Editor/Build/Settings/UI/BuildSettingsEditor.cs b/Editor/Build/Settings/UI/BuildSettingsEditor.cs index c4bbc31..d0f11a8 100644 --- a/Editor/Build/Settings/UI/BuildSettingsEditor.cs +++ b/Editor/Build/Settings/UI/BuildSettingsEditor.cs @@ -1,4 +1,4 @@ -using UnityEditor; +using UnityEditor; using UnityEngine; namespace SuperUnityBuild.BuildTool @@ -8,13 +8,15 @@ public class BuildSettingsEditor : Editor { public override void OnInspectorGUI() { - Color defaultBackgroundColor = GUI.backgroundColor; - GUI.backgroundColor = Color.green; - - if (GUILayout.Button("Open SuperUnityBuild", GUILayout.ExpandWidth(true), GUILayout.MinHeight(30))) - UnityBuildWindow.ShowWindow(); - - GUI.backgroundColor = defaultBackgroundColor; + if (GUILayout.Button("Open in SuperUnityBuild", GUILayout.ExpandWidth(true), GUILayout.MinHeight(30))) + { + BuildSettings targetObj = (BuildSettings)this.target; + if(targetObj != null) + { + //Open this asset in the UnityBuildWindow + targetObj.OpenInUnityBuildWindow(); + } + } } } } diff --git a/Editor/Build/Settings/UI/ProjectConfigurationsDrawer.cs b/Editor/Build/Settings/UI/ProjectConfigurationsDrawer.cs index f1350ab..49099f5 100644 --- a/Editor/Build/Settings/UI/ProjectConfigurationsDrawer.cs +++ b/Editor/Build/Settings/UI/ProjectConfigurationsDrawer.cs @@ -1,4 +1,4 @@ -using UnityEditor; +using UnityEditor; using UnityEngine; namespace SuperUnityBuild.BuildTool @@ -89,7 +89,7 @@ public override void OnGUI(Rect position, SerializedProperty property, GUIConten GUILayout.Space(5); EditorGUILayout.BeginHorizontal(); show = showBuildInfo.isExpanded; - UnityBuildGUIUtility.DropdownHeader("Build Info", ref show, false, GUILayout.ExpandWidth(true)); + UnityBuildGUIUtility.DropdownHeader("Selected Build Info", ref show, false, GUILayout.ExpandWidth(true)); showBuildInfo.isExpanded = show; EditorGUILayout.EndHorizontal(); @@ -158,13 +158,12 @@ public override void OnGUI(Rect position, SerializedProperty property, GUIConten } GUILayout.Space(20); - GUI.backgroundColor = Color.green; - if (GUILayout.Button("Build", GUILayout.ExpandWidth(true))) + if (UnityBuildGUIUtility.BuildButton("Build")) { EditorApplication.delayCall += () => BuildProject.BuildSingle(selectedKeyChain.stringValue, buildOptions); } - if (GUILayout.Button("Build and Run", GUILayout.ExpandWidth(true))) + if (UnityBuildGUIUtility.BuildButton("Build and Run")) { buildOptions |= BuildOptions.AutoRunPlayer; BuildOptions finalBuildOptions = buildOptions; @@ -173,7 +172,7 @@ public override void OnGUI(Rect position, SerializedProperty property, GUIConten } EditorGUI.BeginDisabledGroup((buildOptions & BuildOptions.Development) != BuildOptions.Development); - if (GUILayout.Button("Build and Run with Profiler", GUILayout.ExpandWidth(true))) + if (UnityBuildGUIUtility.BuildButton("Build and Run with Profiler")) { buildOptions |= BuildOptions.AutoRunPlayer; buildOptions |= BuildOptions.ConnectWithProfiler; @@ -182,7 +181,6 @@ public override void OnGUI(Rect position, SerializedProperty property, GUIConten BuildProject.BuildSingle(selectedKeyChain.stringValue, finalBuildOptions); } EditorGUI.EndDisabledGroup(); - GUI.backgroundColor = defaultBackgroundColor; if (GUILayout.Button(new GUIContent("Configure Editor Environment", "Switches platform, refreshes BuildConstants, applies scripting defines and variant settings and sets Build Settings scene list to match the selected build configuration"), GUILayout.ExpandWidth(true))) { diff --git a/Editor/Build/Settings/UI/SceneListDrawer.cs b/Editor/Build/Settings/UI/SceneListDrawer.cs index 854740b..cdf895a 100644 --- a/Editor/Build/Settings/UI/SceneListDrawer.cs +++ b/Editor/Build/Settings/UI/SceneListDrawer.cs @@ -1,4 +1,4 @@ -using System.IO; +using System.IO; using UnityEditor; using UnityEngine; @@ -30,7 +30,7 @@ public override void OnGUI(Rect position, SerializedProperty property, GUIConten rt.sceneList.Refresh(); } - list = property.FindPropertyRelative("enabledScenes"); + list = property.FindPropertyRelative("releaseScenes"); if (show) { @@ -40,18 +40,40 @@ public override void OnGUI(Rect position, SerializedProperty property, GUIConten string fileGUID; string filePath; string sceneName = "N/A"; + SerializedProperty sceneActiveProperty; + int activeCount = 0; + bool foundFirst = false; + + //Find the first scene to label as the start for this release if (list.arraySize > 0) { - platformProperty = list.GetArrayElementAtIndex(0); - fileGUID = platformProperty.FindPropertyRelative("fileGUID").stringValue; - filePath = AssetDatabase.GUIDToAssetPath(fileGUID); - sceneName = Path.GetFileNameWithoutExtension(filePath); + for(int i = 0; i < list.arraySize; i++) + { + platformProperty = list.GetArrayElementAtIndex(i); + sceneActiveProperty = platformProperty.FindPropertyRelative("sceneActive"); + if(!sceneActiveProperty.boolValue) + { + //Skip this while searching for first + continue; + } + activeCount++; + + if(!foundFirst) + { + foundFirst = true; + + fileGUID = platformProperty.FindPropertyRelative("fileGUID").stringValue; + filePath = AssetDatabase.GUIDToAssetPath(fileGUID); + sceneName = Path.GetFileNameWithoutExtension(filePath); + } + } } EditorGUILayout.BeginHorizontal(); show = list.isExpanded; - UnityBuildGUIUtility.DropdownHeader(string.Format("Scenes ({0}) (First Scene: {1})", list.arraySize, sceneName), ref show, false, GUILayout.ExpandWidth(true)); + UnityBuildGUIUtility.DropdownHeader(string.Format("Scenes ({0}, Active: {1}) (First Scene: {2})", list.arraySize, activeCount, sceneName), + ref show, false, GUILayout.ExpandWidth(true)); list.isExpanded = show; EditorGUILayout.EndHorizontal(); @@ -64,18 +86,36 @@ public override void OnGUI(Rect position, SerializedProperty property, GUIConten fileGUID = platformProperty.FindPropertyRelative("fileGUID").stringValue; filePath = AssetDatabase.GUIDToAssetPath(fileGUID); sceneName = Path.GetFileNameWithoutExtension(filePath); + sceneActiveProperty = platformProperty.FindPropertyRelative("sceneActive"); + + //Top actions + name + + //Vertical padding + EditorGUILayout.Space(4f); EditorGUILayout.BeginHorizontal(); - EditorGUILayout.TextArea($"{sceneName} ({filePath})"); + + sceneActiveProperty.boolValue = UnityBuildGUIUtility.SceneActiveToggle(sceneActiveProperty.boolValue); + UnityBuildGUIUtility.SceneNameLabel(sceneName); UnityBuildGUIUtility.ReorderArrayControls(list, i); if (UnityBuildGUIUtility.DeleteButton()) + { list.SafeDeleteArrayElementAtIndex(i); + } - property.serializedObject.ApplyModifiedProperties(); + EditorGUILayout.EndHorizontal(); + + //Bottom info label + + EditorGUILayout.BeginHorizontal(); + + UnityBuildGUIUtility.SceneInfoLabel(filePath); EditorGUILayout.EndHorizontal(); + + property.serializedObject.ApplyModifiedProperties(); } } @@ -113,8 +153,8 @@ public override void OnGUI(Rect position, SerializedProperty property, GUIConten break; } - if (GUILayout.Button("Clear Scene List", GUILayout.ExpandWidth(true))) - list.ClearArray(); + if (GUILayout.Button("Add Current Scene", GUILayout.ExpandWidth(true))) + GetSceneFilesFromBuildSettings(); if (GUILayout.Button("Add Scene Files from Build Settings", GUILayout.ExpandWidth(true))) GetSceneFilesFromBuildSettings(); @@ -125,6 +165,9 @@ public override void OnGUI(Rect position, SerializedProperty property, GUIConten if (GUILayout.Button("Set First Scene by File", GUILayout.ExpandWidth(true))) SetFirstSceneByFile(); + if (GUILayout.Button("Clear Scene List", GUILayout.ExpandWidth(true))) + list.ClearArray(); + list.serializedObject.ApplyModifiedProperties(); property.serializedObject.ApplyModifiedProperties(); @@ -180,7 +223,9 @@ private void GetSceneFilesFromBuildSettings() for (int i = 0; i < scenes.Length; i++) { - AddScene(AssetDatabase.AssetPathToGUID(scenes[i].path)); + var thisBuildScene = scenes[i]; + //Pass the enabled status from the build window + AddScene(AssetDatabase.AssetPathToGUID(thisBuildScene.path), thisBuildScene.enabled); } } @@ -210,15 +255,17 @@ private void SetFirstSceneByFile() list.InsertArrayElementAtIndex(0); list.GetArrayElementAtIndex(0).FindPropertyRelative("fileGUID").stringValue = objGUID; + list.GetArrayElementAtIndex(0).FindPropertyRelative("sceneActive").boolValue = true; } - private void AddScene(string objGUID) + private void AddScene(string objGUID, bool defaultActive = true) { if (!string.IsNullOrEmpty(objGUID) && !CheckForDuplicate(objGUID)) { int addedIndex = list.arraySize; list.InsertArrayElementAtIndex(addedIndex); list.GetArrayElementAtIndex(addedIndex).FindPropertyRelative("fileGUID").stringValue = objGUID; + list.GetArrayElementAtIndex(addedIndex).FindPropertyRelative("sceneActive").boolValue = defaultActive; } } } diff --git a/Editor/Build/UI/UnityBuildGUIUtility.cs b/Editor/Build/UI/UnityBuildGUIUtility.cs index b016f1c..1aaebc0 100644 --- a/Editor/Build/UI/UnityBuildGUIUtility.cs +++ b/Editor/Build/UI/UnityBuildGUIUtility.cs @@ -32,9 +32,14 @@ public static UnityBuildGUIUtility instance private GUIStyle _popupStyle; private GUIStyle _mainTitleStyle; private GUIStyle _dragDropArea; + private GUIStyle _buildButtonStyle; + private GUIStyle _sceneNameLabelStyle; + private GUIStyle _sceneInfoLabelStyle; + private GUIStyle _sceneActiveToggleStyle; private Color32 _defaultBackgroundColor = GUI.backgroundColor; private Color32 _mainHeaderColor = new Color32(180, 180, 255, 255); + private Color32 _buildButtonColor = new Color32(102, 230, 102, 255); private GUIContent helpButtonContent; @@ -56,8 +61,8 @@ private UnityBuildGUIUtility() _helpButtonStyle.alignment = TextAnchor.MiddleCenter; _helpButtonStyle.fontStyle = FontStyle.Normal; _helpButtonStyle.margin = new RectOffset(0, 5, 0, 0); - _helpButtonStyle.fixedWidth = 30; _helpButtonStyle.wordWrap = false; + _helpButtonStyle.fixedWidth = 35; _midHeaderStyle = new GUIStyle(EditorStyles.helpBox); _midHeaderStyle.fontStyle = FontStyle.Bold; @@ -76,6 +81,25 @@ private UnityBuildGUIUtility() _dragDropArea.stretchWidth = true; _dragDropArea.alignment = TextAnchor.MiddleCenter; _dragDropArea.normal.textColor = GUI.skin.textField.normal.textColor; + + _buildButtonStyle = new GUIStyle(GUI.skin.button); + //_buildButtonStyle.normal.textColor = Color.black; + //_buildButtonStyle.hover.textColor = new Color32(0, 0, 0, 200); + + _sceneNameLabelStyle = new GUIStyle(EditorStyles.largeLabel); + _sceneNameLabelStyle.margin = new RectOffset(0, 0, 0, 0); + _sceneNameLabelStyle.padding = new RectOffset(5, 0, 0, 0); + _sceneNameLabelStyle.alignment = TextAnchor.MiddleLeft; + _sceneNameLabelStyle.wordWrap = false; + _sceneNameLabelStyle.fixedWidth = 0; + + _sceneInfoLabelStyle = new GUIStyle(EditorStyles.centeredGreyMiniLabel); + _sceneInfoLabelStyle.alignment = TextAnchor.MiddleLeft; + + _sceneActiveToggleStyle = new GUIStyle(EditorStyles.toggle); + _sceneActiveToggleStyle.padding = new RectOffset(0, 0, 0, 0); + _sceneActiveToggleStyle.margin = new RectOffset(0, 0, 0, 0); + _sceneActiveToggleStyle.fixedWidth = 0; helpButtonContent = new GUIContent("?", "Help"); } @@ -110,7 +134,28 @@ public static void DropdownHeader(GUIContent content, ref bool showDropdown, boo public static void HelpButton(string anchor = "") { if (GUILayout.Button(_instance.helpButtonContent, helpButtonStyle)) + { OpenHelp(anchor); + } + } + + public static bool BuildButton(string text, int minHeight = 0) + { + GUI.backgroundColor = instance._buildButtonColor; + + bool buttonPress; + if(minHeight > 0) + { + buttonPress = GUILayout.Button(text, instance._buildButtonStyle, GUILayout.ExpandWidth(true), GUILayout.MinHeight(minHeight)); + } + else + { + buttonPress = GUILayout.Button(text, instance._buildButtonStyle, GUILayout.ExpandWidth(true)); + } + + GUI.backgroundColor = instance._defaultBackgroundColor; + + return buttonPress; } public static bool MoveUpButton() @@ -149,6 +194,22 @@ public static void ReorderArrayControls(SerializedProperty array, int i) if (moveIndex != -1) array.MoveArrayElement(i, moveIndex); + + } + + public static void SceneNameLabel(string sceneName) + { + EditorGUILayout.LabelField(new GUIContent($"{sceneName}"), instance._sceneNameLabelStyle, GUILayout.ExpandWidth(true)); + } + + public static void SceneInfoLabel(string sceneInfo) + { + EditorGUILayout.LabelField(new GUIContent($"{sceneInfo}"), instance._sceneInfoLabelStyle); + } + + public static bool SceneActiveToggle(bool toggleOn) + { + return EditorGUILayout.Toggle(toggleOn, instance._sceneActiveToggleStyle, GUILayout.Width(15)); } public static string ToLabel(string input, int maxLength = 60) diff --git a/Editor/Build/UI/UnityBuildWindow.cs b/Editor/Build/UI/UnityBuildWindow.cs index 14a1467..9753c01 100644 --- a/Editor/Build/UI/UnityBuildWindow.cs +++ b/Editor/Build/UI/UnityBuildWindow.cs @@ -89,12 +89,23 @@ protected void OnGUI() #endregion - #region Private Methods + #region Public Methods + + public void RefreshSelectedBuildSettings() + { + currentBuildSettings = BuildSettings.instance; + settings = null; + } + + #endregion + #region Private Methods private void Init() { if (go == null) + { go = new SerializedObject(this); + } // Add field to switch the BuildSettings asset EditorGUILayout.BeginVertical(EditorStyles.inspectorFullWidthMargins); @@ -106,7 +117,7 @@ private void Init() // Override a 'None' selection for the BuildSettings asset if (currentBuildSettings == null) { - currentBuildSettings = BuildSettings.instance; + RefreshSelectedBuildSettings(); } if (currentBuildSettings != BuildSettings.instance) @@ -116,7 +127,9 @@ private void Init() } if (settings == null) + { settings = new SerializedObject(BuildSettings.instance); + } BuildSettings.Init(); } @@ -152,12 +165,12 @@ private void DrawBuildButtons() EditorGUILayout.BeginVertical(EditorStyles.inspectorFullWidthMargins); EditorGUI.BeginDisabledGroup(totalBuildCount < 1); - GUI.backgroundColor = Color.green; - if (GUILayout.Button($"Perform All Enabled Builds ({totalBuildCount} Builds)", GUILayout.ExpandWidth(true), GUILayout.MinHeight(30))) + if (UnityBuildGUIUtility.BuildButton($"Perform All Enabled Builds ({totalBuildCount} Builds)", 30)) + { EditorApplication.delayCall += BuildProject.BuildAll; + } - GUI.backgroundColor = UnityBuildGUIUtility.defaultBackgroundColor; EditorGUI.EndDisabledGroup(); EditorGUILayout.EndVertical(); } diff --git a/Editor/BuildConstantsGenerator.cs b/Editor/BuildConstantsGenerator.cs index 79483d5..98e86dd 100644 --- a/Editor/BuildConstantsGenerator.cs +++ b/Editor/BuildConstantsGenerator.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.IO; using System.Text.RegularExpressions; @@ -11,19 +11,24 @@ public static class BuildConstantsGenerator { public const string NONE = "None"; - private const string FileName = "BuildConstants.cs"; - private static readonly string DefaultFilePath = Path.Combine(Constants.RootDirectoryName, FileName); + public const string FileName = "BuildConstants.cs"; public static string FindFile() { string[] fileSearchResults = Directory.GetFiles(Application.dataPath, FileName, SearchOption.AllDirectories); string filePath = null; + char[] separatorChars = new char[] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar }; for (int i = 0; i < fileSearchResults.Length; i++) { - if (fileSearchResults[i].EndsWith(DefaultFilePath)) + var thisFilePath = fileSearchResults[i]; + var thisFilePathSplit = thisFilePath.Split(separatorChars); + if (thisFilePathSplit.Length > 0) { - filePath = fileSearchResults[i]; - break; + if (thisFilePathSplit[thisFilePathSplit.Length - 1].Equals(FileName)) + { + filePath = thisFilePath; + break; + } } } @@ -32,45 +37,60 @@ public static string FindFile() public static void Generate( DateTime buildTime, + string filePath = "", string currentVersion = "", BuildReleaseType currentReleaseType = null, BuildPlatform currentBuildPlatform = null, + BuildScriptingBackend currentScriptingBackend = null, BuildArchitecture currentBuildArchitecture = null, BuildDistribution currentBuildDistribution = null) { // Find the BuildConstants file. string currentFilePath = FindFile(); - string filePath = !string.IsNullOrEmpty(currentFilePath) ? currentFilePath : Path.Combine(Constants.AssetsDirectoryName, DefaultFilePath); + string finalFileLocation; + if (string.IsNullOrEmpty(currentFilePath)) + { + finalFileLocation = Path.Combine(filePath, FileName); + } + else + { + finalFileLocation = currentFilePath; + } // Generate strings string versionString = currentVersion; string releaseTypeString = currentReleaseType == null ? NONE : SanitizeString(currentReleaseType.typeName); string platformString = currentBuildPlatform == null ? NONE : SanitizeString(currentBuildPlatform.platformName); - string archString = currentBuildArchitecture == null ? NONE : SanitizeString(currentBuildArchitecture.name); + string scriptingBackendString = currentScriptingBackend == null ? NONE : SanitizeString(currentScriptingBackend.name); + string architectureString = currentBuildArchitecture == null ? NONE : SanitizeString(currentBuildArchitecture.name); string distributionString = currentBuildDistribution == null ? NONE : SanitizeString(currentBuildDistribution.distributionName); - if (File.Exists(filePath)) + if (File.Exists(finalFileLocation)) { // Delete existing version. - File.Delete(filePath); + File.Delete(finalFileLocation); } else { - // Ensure default path exists if generating for the first time. - AssetDatabaseUtility.EnsureDirectoriesExist(); + // Ensure desired path exists if generating for the first time. + var fileInfo = new FileInfo(finalFileLocation); + if (!fileInfo.Directory.Exists) + { + Directory.CreateDirectory(fileInfo.Directory.FullName); + } } // Create a buffer that we'll use to check for any duplicated names. List enumBuffer = new List(); - using (StreamWriter writer = new StreamWriter(filePath)) + using (StreamWriter writer = new StreamWriter(finalFileLocation)) { - // Start of file and class. + // Start of file writer.WriteLine("using System;"); writer.WriteLine(""); writer.WriteLine("// This file is auto-generated. Do not modify or move this file."); writer.WriteLine(); - writer.WriteLine("public static class BuildConstants"); + writer.WriteLine("namespace SuperUnityBuild.Generated"); writer.WriteLine("{"); // Write ReleaseType enum. @@ -118,6 +138,35 @@ public static void Generate( if (!enumBuffer.Contains(platformString)) platformString = NONE; + // Write Scripting Backend enum. + enumBuffer.Clear(); + writer.WriteLine(" public enum ScriptingBackend"); + writer.WriteLine(" {"); + writer.WriteLine(" {0},", NONE); + enumBuffer.Add(NONE); + foreach (BuildPlatform platform in BuildSettings.platformList.platforms) + { + if (platform.enabled) + { + foreach (BuildScriptingBackend scriptingBackend in platform.scriptingBackends) + { + string addedString = SanitizeString(scriptingBackend.name); + + if (scriptingBackend.enabled && !enumBuffer.Contains(addedString)) + { + enumBuffer.Add(addedString); + writer.WriteLine(" {0},", addedString); + } + } + } + } + writer.WriteLine(" }"); + writer.WriteLine(); + + // Validate Scripting Backend string. + if (!enumBuffer.Contains(scriptingBackendString)) + scriptingBackendString = NONE; + // Write Architecture enum. enumBuffer.Clear(); writer.WriteLine(" public enum Architecture"); @@ -144,8 +193,8 @@ public static void Generate( writer.WriteLine(); // Validate Architecture string. - if (!enumBuffer.Contains(archString)) - archString = NONE; + if (!enumBuffer.Contains(architectureString)) + architectureString = NONE; // Write Distribution enum. enumBuffer.Clear(); @@ -176,15 +225,21 @@ public static void Generate( if (!enumBuffer.Contains(distributionString)) distributionString = NONE; + // Start of class. + writer.WriteLine(" public static class BuildConstants"); + writer.WriteLine(" {"); + // Write current values. - writer.WriteLine(" public static readonly DateTime buildDate = new DateTime({0});", buildTime.Ticks); - writer.WriteLine(" public const string version = \"{0}\";", versionString); - writer.WriteLine(" public const ReleaseType releaseType = ReleaseType.{0};", releaseTypeString); - writer.WriteLine(" public const Platform platform = Platform.{0};", platformString); - writer.WriteLine(" public const Architecture architecture = Architecture.{0};", archString); - writer.WriteLine(" public const Distribution distribution = Distribution.{0};", distributionString); + writer.WriteLine(" public static readonly DateTime buildDate = new DateTime({0});", buildTime.Ticks); + writer.WriteLine(" public const string version = \"{0}\";", versionString); + writer.WriteLine(" public const ReleaseType releaseType = ReleaseType.{0};", releaseTypeString); + writer.WriteLine(" public const Platform platform = Platform.{0};", platformString); + writer.WriteLine(" public const ScriptingBackend scriptingBackend = ScriptingBackend.{0};", scriptingBackendString); + writer.WriteLine(" public const Architecture architecture = Architecture.{0};", architectureString); + writer.WriteLine(" public const Distribution distribution = Distribution.{0};", distributionString); // End of class. + writer.WriteLine(" }"); writer.WriteLine("}"); writer.WriteLine(); } diff --git a/Editor/Generic/AssetDatabaseUtility.cs b/Editor/Generic/AssetDatabaseUtility.cs index 4e81c61..4cd6755 100644 --- a/Editor/Generic/AssetDatabaseUtility.cs +++ b/Editor/Generic/AssetDatabaseUtility.cs @@ -18,7 +18,7 @@ public static void ImportAsset(string path, ImportAssetOptions options = ImportA AssetDatabase.ImportAsset(path, options); } - public static void EnsureDirectoriesExist() + public static void EnsureDefaultDirectoriesExist() { string assetsRoot = Path.Combine(Constants.AssetsDirectoryName, Constants.RootDirectoryName); string editorRoot = Path.Combine(assetsRoot, Constants.EditorDirectoryName); diff --git a/Editor/Generic/ExtensionMethods.cs b/Editor/Generic/ExtensionMethods.cs index 62d0a2e..61283d8 100644 --- a/Editor/Generic/ExtensionMethods.cs +++ b/Editor/Generic/ExtensionMethods.cs @@ -1,18 +1,52 @@ +using System.Collections.Generic; +using System.IO; +using System.Text.RegularExpressions; using UnityEditor; namespace SuperUnityBuild.BuildTool { public static class ExtensionMethods { + public static string SanitizeCodeString(this string str) + { + str = Regex.Replace(str, "[^a-zA-Z0-9_]", "_", RegexOptions.Compiled); + + if (char.IsDigit(str[0])) + str = "_" + str; + + return str; + } + + public static string SanitizeDefine(this string input) + { + return input.ToUpper().Replace(" ", "").SanitizeCodeString(); + } + + public static string SanitizeFolderName(this string folderName) + { + string invalidChars = Regex.Escape(new string(Path.GetInvalidFileNameChars()) + new string(Path.GetInvalidPathChars())); + string invalidRegStr = string.Format(@"[{0}]", invalidChars); + + return Regex.Replace(folderName, invalidRegStr, ""); + } + + public static string SanitizeFileName(this string fileName) + { + string invalidChars = Regex.Escape(new string(Path.GetInvalidFileNameChars())); + string invalidRegStr = string.Format(@"([{0}]*\.+$)|([{0}]+)", invalidChars); + + return Regex.Replace(fileName, invalidRegStr, "_"); + } + public static string Truncate(this string value, int maxLength, string suffix = "", char[] trimChars = null) { trimChars = trimChars ?? new char[] { ' ' }; - if(string.IsNullOrEmpty(value) || value.Length <= maxLength) + if (string.IsNullOrEmpty(value) || value.Length <= maxLength) { return value; } - if(maxLength <= 0) + if (maxLength <= 0) { return suffix; } @@ -37,5 +71,20 @@ public static void SafeDeleteArrayElementAtIndex(this SerializedProperty value, if (value.arraySize == oldLength) value.DeleteArrayElementAtIndex(i); } + + // Provided by Jon Skeet in https://stackoverflow.com/questions/969091/c-skiplast-implementation + public static IEnumerable SkipLast(this IEnumerable source) + { + T previous = default(T); + bool first = true; + foreach (T element in source) + { + if (!first) + yield return previous; + + previous = element; + first = false; + } + } } } diff --git a/Editor/Generic/TokensUtility.cs b/Editor/Generic/TokensUtility.cs new file mode 100644 index 0000000..6c96144 --- /dev/null +++ b/Editor/Generic/TokensUtility.cs @@ -0,0 +1,70 @@ +using System; +using System.Text; + +namespace SuperUnityBuild.BuildTool +{ + public static class TokensUtility + { + public static string ResolveBuildConfigurationTokens(string prototype, BuildReleaseType releaseType, BuildPlatform platform, BuildArchitecture architecture, BuildScriptingBackend scriptingBackend, BuildDistribution distribution, DateTime? buildTime) + { + prototype = ResolveBuildVersionTokens(prototype); + + if (buildTime != null) + prototype = ResolveBuildTimeTokens(prototype, (DateTime)buildTime); + + StringBuilder sb = new StringBuilder(prototype); + + string variants = ""; + if (platform.variants != null && platform.variants.Length > 0) + variants = platform.variantKey.Replace(",", ", "); + + sb.Replace("$RELEASE_TYPE", releaseType?.typeName.SanitizeFolderName()); + sb.Replace("$PLATFORM", platform?.platformName.SanitizeFolderName()); + sb.Replace("$ARCHITECTURE", architecture?.name.SanitizeFolderName()); + sb.Replace("$VARIANTS", variants.SanitizeFolderName()); + sb.Replace("$DISTRIBUTION", distribution?.distributionName.SanitizeFolderName()); + sb.Replace("$PRODUCT_NAME", releaseType?.productName.SanitizeFolderName()); + sb.Replace("$SCRIPTING_BACKEND", scriptingBackend?.name.SanitizeFolderName()); + + return sb.ToString(); + } + + public static string ResolveBuildNumberToken(string prototype) + { + return (prototype ?? "") + .Replace("$BUILD", BuildSettings.productParameters.buildCounter.ToString()); + } + + public static string ResolveBuildOutputTokens(string prototype, string buildPath) + { + return (prototype ?? "") + .Replace("$BUILDPATH", buildPath) + .Replace("$BASEPATH", BuildSettings.basicSettings.baseBuildFolder); + } + + public static string ResolveBuildTimeTokens(string prototype, DateTime buildTime) + { + return (prototype ?? "") + .Replace("$YEAR", buildTime.ToString("yyyy")) + .Replace("$MONTH", buildTime.ToString("MM")) + .Replace("$DAY", buildTime.ToString("dd")) + .Replace("$TIME", buildTime.ToString("hhmmss")); + } + + public static string ResolveBuildVersionToken(string prototype) + { + return (prototype ?? "") + .Replace("$VERSION", BuildSettings.productParameters.buildVersion.SanitizeFolderName()); + } + + public static string ResolveBuildVersionTokens(string prototype) + { + prototype = prototype ?? ""; + + prototype = ResolveBuildVersionToken(prototype); + prototype = ResolveBuildNumberToken(prototype); + + return prototype; + } + } +} diff --git a/Editor/Generic/TokensUtility.cs.meta b/Editor/Generic/TokensUtility.cs.meta new file mode 100644 index 0000000..622fe98 --- /dev/null +++ b/Editor/Generic/TokensUtility.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2435c1b6b2b634e4c957863d4e929771 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/Notifications/UI/BuildNotificationListDrawer.cs b/Editor/Notifications/UI/BuildNotificationListDrawer.cs index ea38367..52b6536 100644 --- a/Editor/Notifications/UI/BuildNotificationListDrawer.cs +++ b/Editor/Notifications/UI/BuildNotificationListDrawer.cs @@ -1,4 +1,4 @@ -using UnityEditor; +using UnityEditor; using UnityEngine; namespace SuperUnityBuild.BuildTool @@ -13,6 +13,7 @@ public class BuildNotificationListDrawer : PropertyDrawer private SerializedProperty notificationsList; private GUIContent clearButtonContent = new GUIContent("X", "Clear"); + private Color32 logHeaderColor = new Color32(100, 200, 240, 255); public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { @@ -151,7 +152,7 @@ private void DrawNotifications() Color defaultBackgroundColor = GUI.backgroundColor; EditorGUILayout.BeginHorizontal(); - GUI.backgroundColor = Color.cyan; + GUI.backgroundColor = logHeaderColor; UnityBuildGUIUtility.DropdownHeader( $"Log ({warningCount})", ref show, true, diff --git a/package.json b/package.json index a905a20..3f581ae 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "com.github.superunitybuild.buildtool", "displayName": "SuperUnityBuild", - "version": "6.0.1", + "version": "7.0.0", "unity": "2020.3", "description": "SuperUnityBuild is a Unity utility that automates the process of generating builds. It's easy and quick enough to use on small apps, but it's also powerful and extensible enough to be extremely useful on larger projects. The key to this flexibility lies in SuperUnityBuild's configurable degrees of granularity and its BuildActions framework which allows additional operations to be added into the build process.", "changelogUrl": "CHANGELOG.md",