diff --git a/.icon.png b/.icon.png new file mode 100644 index 0000000..88f2743 Binary files /dev/null and b/.icon.png differ diff --git a/Editor.meta b/Editor.meta new file mode 100644 index 0000000..30af494 --- /dev/null +++ b/Editor.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 912e27614f99c43c8b578eb05715154e +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/GameWorkstore.Automation.Editor.asmdef b/Editor/GameWorkstore.Automation.Editor.asmdef new file mode 100644 index 0000000..577bc8e --- /dev/null +++ b/Editor/GameWorkstore.Automation.Editor.asmdef @@ -0,0 +1,19 @@ +{ + "name": "GameWorkstore.Automation.Editor", + "rootNamespace": "", + "references": [ + "GUID:381921da55d39454f9a6ce7095941507", + "GUID:c32d36751e998d74999be5c29b033d6e" + ], + "includePlatforms": [ + "Editor" + ], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [], + "noEngineReferences": false +} \ No newline at end of file diff --git a/Editor/GameWorkstore.Automation.Editor.asmdef.meta b/Editor/GameWorkstore.Automation.Editor.asmdef.meta new file mode 100644 index 0000000..ffdec95 --- /dev/null +++ b/Editor/GameWorkstore.Automation.Editor.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 3cdd0d62d23b14208b6051d57e61275c +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/VersionWriter.cs b/Editor/VersionWriter.cs new file mode 100644 index 0000000..dfd1758 --- /dev/null +++ b/Editor/VersionWriter.cs @@ -0,0 +1,86 @@ +#if UNITY_EDITOR +using System.IO; +using UnityEditor; +using UnityEditor.Build; +using UnityEditor.Build.Reporting; +using UnityEditor.Callbacks; +using UnityEngine; + +namespace GameWorkstore.Automation +{ + public class VersionWriter : IPreprocessBuildWithReport + { + public const string FileName = "GameVersion.cs"; + + public int callbackOrder => 0; + + public void OnPreprocessBuild(BuildReport report) + { + var buildScript = BuildClass.GetBuildScript(); + WriteVersion(buildScript); + } + + [DidReloadScripts] + public static void WriteVersion() + { + var buildScript = BuildClass.GetBuildScript(); + WriteVersion(buildScript); + } + + public static void WriteVersion(BuildScript script) + { + if (script == null) return; + if (!script.GameVersionWriterConfig.Enabled) return; + + var content = + "namespace " + script.GameVersionWriterConfig.Namespace + "\r\n" + + "{\r\n"+ + "\tpublic static class GameVersion\r\n" + + "\t{\r\n" + + "\t"+ FormatVar("IosBundleVersion", PlayerSettings.iOS.buildNumber) + "\r\n" + + "\t" + FormatVar("AndroidBundleVersion", PlayerSettings.iOS.buildNumber) + "\r\n" + + "\t}\r\n" + + "}"; + + var directoryPath = GetDirectory(script); + if (!Directory.Exists(directoryPath)) + { + Directory.CreateDirectory(directoryPath); + } + + var filePath = GetFilePath(script); + + var currentText = string.Empty; + if (File.Exists(filePath)) + { + currentText = File.ReadAllText(filePath); + } + + if (currentText == content) return; + Debug.Log("Updated GameVersion.cs"); + + File.WriteAllText(filePath, content); + AssetDatabase.Refresh(); + } + + private static string FormatVar(string varName, string varValue) + { + return "\tpublic const string " + varName + " = \"" + varValue + "\";"; + } + + public static string GetFilePath(BuildScript script) + { + return Path.Combine(GetDirectory(script), FileName); + } + + public static string GetDirectory(BuildScript script) + { + if (script.GameVersionWriterConfig.Path.StartsWith("/")) + { + return Path.Combine(Application.dataPath, script.GameVersionWriterConfig.Path.Substring(1)); + } + return Path.Combine(Application.dataPath, script.GameVersionWriterConfig.Path); + } + } +} +#endif \ No newline at end of file diff --git a/Editor/VersionWriter.cs.meta b/Editor/VersionWriter.cs.meta new file mode 100644 index 0000000..c787f71 --- /dev/null +++ b/Editor/VersionWriter.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ec5483dc403e242ed9c909bce2d9a11a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..39802bc --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 Game Workstore + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/LICENSE.meta b/LICENSE.meta new file mode 100644 index 0000000..eaa3e58 --- /dev/null +++ b/LICENSE.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 582f9c21e14153c46a1221654bf7a7e2 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/README.md b/README.md new file mode 100644 index 0000000..3af1b8c --- /dev/null +++ b/README.md @@ -0,0 +1,44 @@ +# Automation +Automate your projects with this powerful tool with many build options! + +# How to install + +At package.json, add these 2 lines of code: +```json +"com.gameworkstore.automation": "git://github.com/GameWorkstore/automation.git" +"com.gameworkstore.patterns": "git://github.com/GameWorkstore/patterns.git" +``` + +And wait for unity to download and compile the package. + +for update package for a newer version, install UpmGitExtension and update on [ Window > Package Manager ]! +> https://github.com/mob-sakai/UpmGitExtension + +# Automate Builds + +On a windows .bat file, you invoke unity to build your game as the example below: +```bat +set CODEVERSION=23 +set VERSION=1.0.%CODEVERSION% +call %UNITYPATH% -executeMethod BuildClass.BuildAndroid -projectPath %WORKSPACE% -gameversion %VERSION% -bundleversion %CODEVERSION% +``` + +You can also use Jenkins to attribute BUILD_NUMBER to CODEVERSION +```bat +set CODEVERSION=%BUILD_NUMBER% +``` + +or you can sum with a static number +```bat +set /a "CODEVERSION=%BUILD_NUMBER%+0" +``` + +# Contributions + +If you are using this library and want to submit a change, go ahead! Overall, this project accepts contributions if: +- Is a bug fix; +- Or, is a generalization of a well-known issue; +- Or is performance improvement; +- Or is an improvement to already supported feature. + +Also, you can donate to allow us to drink coffee while we improve it for you! \ No newline at end of file diff --git a/README.md.meta b/README.md.meta new file mode 100644 index 0000000..fa05934 --- /dev/null +++ b/README.md.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 1359b2c9f83fc4490a5a4ffdc8d0c091 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime.meta b/Runtime.meta new file mode 100644 index 0000000..e87ac16 --- /dev/null +++ b/Runtime.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: efb21c3644a9d3547a472fca3f6acd4f +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/BuildClass.cs b/Runtime/BuildClass.cs new file mode 100644 index 0000000..01349b8 --- /dev/null +++ b/Runtime/BuildClass.cs @@ -0,0 +1,510 @@ +using GameWorkstore.Patterns; +using System.IO; +using UnityEditor; +using UnityEditor.Build.Reporting; +using UnityEngine; + +namespace GameWorkstore.Automation +{ + public static class BuildClass + { + public static void BuildAndroid() + { + var buildScript = GetBuildScript(); + if (!Validate(buildScript)) return; + + //Version + if (!UnityEditorInternal.InternalEditorUtility.isHumanControllingUs) + { + Version(out var gameVersion, out var bundleVersion); + PlayerSettings.bundleVersion = gameVersion; + PlayerSettings.Android.bundleVersionCode = bundleVersion; + } + + //Backend + PlayerSettings.SetScriptingBackend(BuildTargetGroup.Android, buildScript.BuildAndroid.ScriptingBackend); + + //Keystore Config + SetAndroidSignCredentials(buildScript); + + if (buildScript.BuildAndroid.BuildAAB) + { + //Make + const string subPathAab = "Build/Android/AAB/"; + MakeDirectory(subPathAab); + + var buildOptions = new BuildPlayerOptions + { + scenes = buildScript.BuildAndroid.GetScenes(), + locationPathName = subPathAab + buildScript.GameName + ".aab", + target = BuildTarget.Android, + options = GetOptions(buildScript.BuildAndroid) + }; + + EditorUserBuildSettings.buildAppBundle = true; + ProcessReport(BuildPipeline.BuildPlayer(buildOptions)); + } + + if (buildScript.BuildAndroid.BuildAPK) + { + //Make + const string subPathAPK = "Build/Android/APK/"; + MakeDirectory(subPathAPK); + + var buildOptions = new BuildPlayerOptions + { + scenes = buildScript.BuildAndroid.GetScenes(), + locationPathName = subPathAPK + buildScript.GameName + ".apk", + target = BuildTarget.Android, + options = GetOptions(buildScript.BuildAndroid) + }; + + EditorUserBuildSettings.buildAppBundle = false; + ProcessReport(BuildPipeline.BuildPlayer(buildOptions)); + } + } + + public static void BuildIOS() + { + var buildScript = GetBuildScript(); + if (!Validate(buildScript)) return; + + //Version + if (!UnityEditorInternal.InternalEditorUtility.isHumanControllingUs) + { + Version(out var gameVersion, out var bundleVersion); + PlayerSettings.bundleVersion = gameVersion; + PlayerSettings.iOS.buildNumber = bundleVersion.ToString(); + } + + //Options + var buildOptions = new BuildPlayerOptions + { + scenes = buildScript.BuildIOS.GetScenes(), + locationPathName = "Build/iOS/" + buildScript.GameName, + target = BuildTarget.iOS, + options = GetOptions(buildScript.BuildIOS) + }; + + var buildReport = BuildPipeline.BuildPlayer(buildOptions); + if (ProcessReportIsSuccess(buildReport)) + { + CopyAdditionalFolders(buildOptions, buildScript.BuildIOS.AdditionalFolders); + } + ProcessReport(buildReport); + } + + public static void BuildWindows() + { + var buildScript = GetBuildScript(); + if (!Validate(buildScript)) return; + + //Version + if (!UnityEditorInternal.InternalEditorUtility.isHumanControllingUs) + { + Version(out var version, out _); + PlayerSettings.bundleVersion = version; + } + + //Backend + PlayerSettings.SetScriptingBackend(BuildTargetGroup.Standalone, buildScript.BuildWindows.ScriptingBackend); + + //Options + var buildOptions = new BuildPlayerOptions + { + scenes = buildScript.BuildWindows.GetScenes(), + locationPathName = "Build/Windows/" + buildScript.GameName + ".exe", + target = BuildTarget.StandaloneWindows64, + options = GetOptions(buildScript.BuildWindows) + }; + + var buildReport = BuildPipeline.BuildPlayer(buildOptions); + if (ProcessReportIsSuccess(buildReport)) + { + CopyAdditionalFolders(buildOptions, buildScript.BuildWindows.AdditionalFolders); + } + ProcessReport(buildReport); + } + + public static void BuildMacOS() + { + var buildScript = GetBuildScript(); + if (!Validate(buildScript)) return; + + //Version + if (!UnityEditorInternal.InternalEditorUtility.isHumanControllingUs) + { + Version(out var version, out _); + PlayerSettings.bundleVersion = version; + } + + //Backend + PlayerSettings.SetScriptingBackend(BuildTargetGroup.Standalone, buildScript.BuildMacOS.ScriptingBackend); + + //Options + var buildOptions = new BuildPlayerOptions + { + scenes = buildScript.BuildMacOS.GetScenes(), + locationPathName = "Build/MacOS/" + buildScript.GameName + ".app", + target = BuildTarget.StandaloneOSX, + options = GetOptions(buildScript.BuildMacOS) + }; + + var buildReport = BuildPipeline.BuildPlayer(buildOptions); + if (ProcessReportIsSuccess(buildReport)) + { + CopyAdditionalFolders(buildOptions, buildScript.BuildMacOS.AdditionalFolders); + } + ProcessReport(buildReport); + } + + public static void BuildLinux() + { + var buildScript = GetBuildScript(); + if (!Validate(buildScript)) return; + + //Version + if (!UnityEditorInternal.InternalEditorUtility.isHumanControllingUs) + { + Version(out var version, out _); + PlayerSettings.bundleVersion = version; + } + + //Backend + PlayerSettings.SetScriptingBackend(BuildTargetGroup.Standalone, buildScript.BuildLinux.ScriptingBackend); + + //Options + var buildOptions = new BuildPlayerOptions + { + scenes = buildScript.BuildLinux.GetScenes(), + locationPathName = "Build/Linux/" + buildScript.GameName, + target = BuildTarget.StandaloneLinux64, + options = GetOptions(buildScript.BuildLinux) + }; + + var buildReport = BuildPipeline.BuildPlayer(buildOptions); + if (ProcessReportIsSuccess(buildReport)) + { + CopyAdditionalFolders(buildOptions, buildScript.BuildLinux.AdditionalFolders); + } + ProcessReport(buildReport); + } + + public static void BuildGameServerWindows() + { + var buildScript = GetBuildScript(); + if (!Validate(buildScript)) return; + + //Version + if (!UnityEditorInternal.InternalEditorUtility.isHumanControllingUs) + { + Version(out var version, out _); + PlayerSettings.bundleVersion = version; + } + + //Backend + PlayerSettings.SetScriptingBackend(BuildTargetGroup.Standalone, buildScript.BuildGameServerWindows.ScriptingBackend); + + //Options + var buildOptions = new BuildPlayerOptions + { + scenes = buildScript.BuildGameServerWindows.GetScenes(), + locationPathName = "Build/GameServerWindows/" + buildScript.GameName + ".exe", + target = BuildTarget.StandaloneWindows64, + options = GetOptions(buildScript.BuildGameServerWindows,BuildOptions.EnableHeadlessMode) + }; + + var buildReport = BuildPipeline.BuildPlayer(buildOptions); + if (ProcessReportIsSuccess(buildReport)) + { + CopyAdditionalFolders(buildOptions, buildScript.BuildGameServerWindows.AdditionalFolders); + } + ProcessReport(buildReport); + } + + public static void BuildGameServerLinux() + { + var buildScript = GetBuildScript(); + if (!Validate(buildScript)) return; + + //Version + if (!UnityEditorInternal.InternalEditorUtility.isHumanControllingUs) + { + Version(out var version, out _); + PlayerSettings.bundleVersion = version; + } + + //Backend + PlayerSettings.SetScriptingBackend(BuildTargetGroup.Standalone, buildScript.BuildGameServerLinux.ScriptingBackend); + + //Options + var buildOptions = new BuildPlayerOptions + { + scenes = buildScript.BuildGameServerLinux.GetScenes(), + locationPathName = "Build/GameServerLinux/" + buildScript.GameName, + target = BuildTarget.StandaloneLinux64, + options = GetOptions(buildScript.BuildGameServerLinux,BuildOptions.EnableHeadlessMode) + }; + + var buildReport = BuildPipeline.BuildPlayer(buildOptions); + if (ProcessReportIsSuccess(buildReport)) + { + CopyAdditionalFolders(buildOptions, buildScript.BuildGameServerLinux.AdditionalFolders); + } + ProcessReport(buildReport); + } + + public static void BuildGameServerMacOS() + { + var buildScript = GetBuildScript(); + if (!Validate(buildScript)) return; + + //Version + if (!UnityEditorInternal.InternalEditorUtility.isHumanControllingUs) + { + Version(out var version, out _); + PlayerSettings.bundleVersion = version; + } + + var buildConfig = buildScript.BuildGameServerMacOS; + //Backend + PlayerSettings.SetScriptingBackend(BuildTargetGroup.Standalone, buildConfig.ScriptingBackend); + + //Options + var buildOptions = new BuildPlayerOptions + { + scenes = buildConfig.GetScenes(), + locationPathName = "Build/GameServerMacOS/" + buildScript.GameName + ".app", + target = BuildTarget.StandaloneOSX, + options = GetOptions(buildConfig,BuildOptions.EnableHeadlessMode) + }; + + var buildReport = BuildPipeline.BuildPlayer(buildOptions); + if (ProcessReportIsSuccess(buildReport)) + { + CopyAdditionalFolders(buildOptions, buildScript.BuildGameServerMacOS.AdditionalFolders); + } + ProcessReport(buildReport); + } + + public static void BuildUWP() + { + var buildScript = GetBuildScript(); + if (!Validate(buildScript)) return; + + //Version + if (!UnityEditorInternal.InternalEditorUtility.isHumanControllingUs) + { + Version(out var version, out _); + PlayerSettings.bundleVersion = version; + if (System.Version.TryParse(version, out var iVersion)) + { + PlayerSettings.WSA.packageVersion = iVersion; + } + else + { + DebugMessege.Log("Failed to parse game version.", DebugLevel.ERROR); + } + } + + + //Backend + //Always IL2CPP + //PlayerSettings.SetScriptingBackend(BuildTargetGroup.WSA, buildScript.BuildUWP.ScriptingBackend); + + //Options + var buildOptions = new BuildPlayerOptions + { + scenes = buildScript.BuildUWP.GetScenes(), + locationPathName = "Build/UWP/", + target = BuildTarget.WSAPlayer, + options = GetOptions(buildScript.BuildUWP) + }; + + ProcessReport(BuildPipeline.BuildPlayer(buildOptions)); + } + + public static void BuildWebGL() + { + var buildScript = GetBuildScript(); + if (!Validate(buildScript)) return; + + //Version + if (!UnityEditorInternal.InternalEditorUtility.isHumanControllingUs) + { + Version(out var version, out _); + PlayerSettings.bundleVersion = version; + } + + //Options + var buildOptions = new BuildPlayerOptions + { + scenes = buildScript.BuildWebGL.GetScenes(), + locationPathName = "Build/WebGL/", + target = BuildTarget.WebGL, + options = GetOptions(buildScript.BuildWebGL) + }; + + ProcessReport(BuildPipeline.BuildPlayer(buildOptions)); + } + + public static void Version(out string gameVersion, out int bundleVersion) + { + var g = Arg("-gameversion"); + if (string.IsNullOrEmpty(g)) + { + g = Arg("-buildVersion"); + } + gameVersion = string.IsNullOrEmpty(g)? PlayerSettings.bundleVersion : g; + + var bv = Arg("-bundleversion"); + if (string.IsNullOrEmpty(bv)) + { + bv = Arg("-androidVersionCode"); + } + bundleVersion = int.TryParse(bv, out bundleVersion)? bundleVersion : 1; + + Debug.Log("GameVersion:[" + gameVersion + "][" + bundleVersion + "]"); + } + + public static string Arg(string argument) + { + string[] args = System.Environment.GetCommandLineArgs(); + for (int i = 0; i < args.Length; i++) + { + if (!args[i].Equals(argument)) continue; + if (i + 1 >= args.Length) return null; + return args[i + 1]; + + } + return null; + } + + public static void MakeDirectory(string relativePath) + { + var path = GetProjectPath() + relativePath; + if (Directory.Exists(path)) return; + Directory.CreateDirectory(path); + } + + public static string GetProjectPath() + { + return Application.dataPath.Substring(0, Application.dataPath.Length - 6); + } + + public static BuildScript GetBuildScript(bool logPath = false) + { + foreach (var guid in AssetDatabase.FindAssets("t:BuildScript")) + { + var path = AssetDatabase.GUIDToAssetPath(guid); + if (logPath) Debug.Log("[GameWorkstore.Automation] BuildScript at path:" + path); + return AssetDatabase.LoadAssetAtPath(path); + } + return null; + } + + private static BuildOptions GetOptions(BuildBase buildBase, BuildOptions baseOptions = BuildOptions.None) + { + return (buildBase.Development ? BuildOptions.Development : BuildOptions.None) | baseOptions; + } + + public static bool ProcessReportIsSuccess(BuildReport buildReport) + { + return buildReport.summary.result == BuildResult.Succeeded; + } + + public static void ProcessReport(BuildReport buildReport) + { + if (UnityEditorInternal.InternalEditorUtility.isHumanControllingUs) return; + if (ProcessReportIsSuccess(buildReport)) return; + EditorApplication.Exit(1); + } + + public static bool Validate(BuildScript buildScript) + { + if (buildScript == null) + { + DebugMessege.Log("Cannot build without a BuildScript.", DebugLevel.ERROR); + return false; + } + if (string.IsNullOrEmpty(buildScript.GameName)) + { + DebugMessege.Log("GameName cannot be null or empty.", DebugLevel.ERROR); + return false; + } + if(buildScript.GameVersionWriterConfig.Enabled && string.IsNullOrEmpty(buildScript.GameVersionWriterConfig.Namespace)) + { + DebugMessege.Log("GameVersionWriter namespace cannot be null or empty.", DebugLevel.ERROR); + return false; + } + return true; + } + + [MenuItem("Help/Automation/SetAndroidCredentials")] + public static void SetAndroidCredentials() + { + var buildScript = BuildClass.GetBuildScript(); + BuildClass.SetAndroidSignCredentials(buildScript); + } + + public static void SetAndroidSignCredentials(BuildScript buildScript) + { + if(buildScript == null) return; + if (!buildScript.BuildAndroid.UseKeystore) return; + PlayerSettings.Android.useCustomKeystore = true; + PlayerSettings.Android.keystoreName = GetProjectPath() + buildScript.BuildAndroid.KeyStoreSettings.KeystorePath; + PlayerSettings.Android.keystorePass = buildScript.BuildAndroid.KeyStoreSettings.KeystorePassword; + PlayerSettings.Android.keyaliasName = buildScript.BuildAndroid.KeyStoreSettings.AliasName; + PlayerSettings.Android.keyaliasPass = buildScript.BuildAndroid.KeyStoreSettings.AliasPassword; + } + + private static void CopyAdditionalFolders(BuildPlayerOptions buildOptions, string[] additionalFolders) + { + string targetRoot = GetFolder(buildOptions); + if (string.IsNullOrEmpty(targetRoot)) return; + + foreach(var additionalFolder in additionalFolders) + { + var source = Path.Combine(GetProjectPath(), additionalFolder); + var target = Path.Combine(targetRoot, additionalFolder); + if (Directory.Exists(target)) + { + Directory.Delete(target, true); + } + CopyFilesRecursively(source, target); + } + } + + private static void CopyFilesRecursively(string sourcePath, string targetPath) + { + Directory.CreateDirectory(targetPath); + //Now Create all of the directories + foreach (string dirPath in Directory.GetDirectories(sourcePath, "*", SearchOption.AllDirectories)) + { + Directory.CreateDirectory(dirPath.Replace(sourcePath, targetPath)); + } + + //Copy all the files & Replaces any files with the same name + foreach (string newPath in Directory.GetFiles(sourcePath, "*.*", SearchOption.AllDirectories)) + { + File.Copy(newPath, newPath.Replace(sourcePath, targetPath), true); + } + } + + public static string GetFolder(BuildPlayerOptions buildOptions) + { + var path = Path.Combine(GetProjectPath(), buildOptions.locationPathName); + switch (buildOptions.target) + { + case BuildTarget.StandaloneWindows: + case BuildTarget.StandaloneWindows64: + case BuildTarget.StandaloneOSX: + case BuildTarget.StandaloneLinux64: + case BuildTarget.iOS: + return Directory.GetParent(path).FullName; + default: + return string.Empty; + } + } + } +} \ No newline at end of file diff --git a/Runtime/BuildClass.cs.meta b/Runtime/BuildClass.cs.meta new file mode 100644 index 0000000..dc184fc --- /dev/null +++ b/Runtime/BuildClass.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4e4219a3914553f46a24a9a584d53cc3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/BuildScript.cs b/Runtime/BuildScript.cs new file mode 100644 index 0000000..af2a387 --- /dev/null +++ b/Runtime/BuildScript.cs @@ -0,0 +1,145 @@ +using System; +using System.Linq; +using UnityEditor; +using UnityEngine; +using GameWorkstore.Patterns; + +namespace GameWorkstore.Automation +{ + [Serializable] + public class CustomScenes + { + public SceneAssetPath[] List; + } + + [Serializable] + public class BuildBase + { + public bool UseCustomScenes = false; + public bool Development = false; + [ConditionalField("UseCustomScenes")] public CustomScenes Scenes = new CustomScenes(); + + public string[] GetScenes() + { + return UseCustomScenes ? Scenes.List.Select(GetSceneName).ToArray() : EditorBuildSettingsScene.GetActiveSceneList(EditorBuildSettings.scenes); + } + + private static string GetSceneName(SceneAssetPath sceneAssetPath) + { + return sceneAssetPath.Scene; + } + } + + [Serializable] + public class BuildStandalone : BuildBase + { + public ScriptingImplementation ScriptingBackend = ScriptingImplementation.IL2CPP; + public string[] AdditionalFolders = new string[0]; + } + + [Serializable] + public class BuildAppleIOS : BuildBase + { + public string[] AdditionalFolders = new string[0]; + } + + [Serializable] + public class BuildAndroid : BuildBase + { + public bool UseKeystore = false; + public bool BuildAPK = false; + public bool BuildAAB = true; + public ScriptingImplementation ScriptingBackend = ScriptingImplementation.IL2CPP; + + [Serializable] + public struct KeyStoreSettingsStruct + { + public string KeystorePath; + public string KeystorePassword; + public string AliasName; + public string AliasPassword; + } + [ConditionalField("UseKeystore")] public KeyStoreSettingsStruct KeyStoreSettings; + } + + [Serializable] + public class AutoVersionWriter + { + public bool Enabled; + [Tooltip("Path starting from Assets folder")] + public string Path; + public string Namespace; + + public AutoVersionWriter() + { + Enabled = true; + Path = "Scripts/Version/"; + Namespace = "Unset.Namespace"; + } + } + + [CreateAssetMenu(fileName = "BuildScript", menuName = "Automation/BuildScript")] + public class BuildScript : ScriptableObject + { + public string GameName; + + public AutoVersionWriter GameVersionWriterConfig; + + [Header("Android")] + public bool ViewBuildAndroid = false; + [ConditionalField("ViewBuildAndroid")] public BuildAndroid BuildAndroid = new BuildAndroid(); + + [Header("iOS")] + public bool ViewBuildIOS = false; + [ConditionalField("ViewBuildIOS")] public BuildAppleIOS BuildIOS = new BuildAppleIOS(); + + [Header("Windows")] + public bool ViewBuildWindows = false; + [ConditionalField("ViewBuildWindows")] public BuildStandalone BuildWindows = new BuildStandalone(); + + [Header("MacOS")] + public bool ViewBuildMacOS = false; + [ConditionalField("ViewBuildMacOS")] public BuildStandalone BuildMacOS = new BuildStandalone(); + + [Header("Linux")] + public bool ViewBuildLinux = false; + [ConditionalField("ViewBuildLinux")] public BuildStandalone BuildLinux = new BuildStandalone(); + + [Header("UWP")] + public bool ViewBuildUWP = false; + [ConditionalField("ViewBuildUWP")] public BuildBase BuildUWP = new BuildBase(); + + [Header("WebGL")] + public bool ViewBuildWebGL = false; + [ConditionalField("ViewBuildWebGL")] public BuildBase BuildWebGL = new BuildBase(); + + [Header("GameServer - Windows")] + public bool ViewBuildGameServerWindows = false; + [ConditionalField("ViewBuildGameServerWindows")] public BuildStandalone BuildGameServerWindows = new BuildStandalone(); + + [Header("GameServer - Linux")] + public bool ViewBuildGameServerLinux = false; + [ConditionalField("ViewBuildGameServerLinux")] public BuildStandalone BuildGameServerLinux = new BuildStandalone(); + + [Header("GameServer - MacOS")] + public bool ViewBuildGameServerMacOS = false; + [ConditionalField(("ViewBuildGameServerMacOS"))] public BuildStandalone BuildGameServerMacOS = new BuildStandalone(); + + [Header("Build")] + public HelpBox build = new HelpBox("Build Now", HelpBoxType.Info); + + [ButtonMethod] public static void Android() { BuildClass.BuildAndroid(); } + [ButtonMethod] public static void AppleIOS() { BuildClass.BuildIOS(); } + + [ButtonMethod] public static void Windows() { BuildClass.BuildWindows(); } + [ButtonMethod] public static void MacOS() { BuildClass.BuildMacOS(); } + [ButtonMethod] public static void Linux() { BuildClass.BuildLinux(); } + + [ButtonMethod] public static void WebGL() { BuildClass.BuildWebGL(); } + [ButtonMethod] public static void UWP() { BuildClass.BuildUWP(); } + + [ButtonMethod] public static void GameServerWindows() { BuildClass.BuildGameServerWindows(); } + [ButtonMethod] public static void GameServerLinux() { BuildClass.BuildGameServerLinux(); } + [ButtonMethod] public static void GameServerMacOS() { BuildClass.BuildGameServerMacOS(); } + } +} \ No newline at end of file diff --git a/Runtime/BuildScript.cs.meta b/Runtime/BuildScript.cs.meta new file mode 100644 index 0000000..41d163a --- /dev/null +++ b/Runtime/BuildScript.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b12163007ee079c45b98839ab1003048 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/GameWorkstore.Automation.asmdef b/Runtime/GameWorkstore.Automation.asmdef new file mode 100644 index 0000000..9034904 --- /dev/null +++ b/Runtime/GameWorkstore.Automation.asmdef @@ -0,0 +1,18 @@ +{ + "name": "GameWorkstore.Automation", + "rootNamespace": "", + "references": [ + "GUID:c32d36751e998d74999be5c29b033d6e" + ], + "includePlatforms": [ + "Editor" + ], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [], + "noEngineReferences": false +} \ No newline at end of file diff --git a/Runtime/GameWorkstore.Automation.asmdef.meta b/Runtime/GameWorkstore.Automation.asmdef.meta new file mode 100644 index 0000000..5da67c1 --- /dev/null +++ b/Runtime/GameWorkstore.Automation.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 381921da55d39454f9a6ce7095941507 +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/package.json b/package.json new file mode 100644 index 0000000..8318a4c --- /dev/null +++ b/package.json @@ -0,0 +1,17 @@ +{ + "name": "com.gameworkstore.automation", + "version": "1.0.9", + "displayName": "GameWorkstore Automation", + "description": "Automate your projects with this powerful tool with many build options!", + "unity": "2020.1", + "icon": ".icon.png", + "keywords": [ "build", "automation" ], + "author": { + "name": "Game Workstore", + "email": "contact@gameworkstore.com", + "url": "https://gameworkstore.com" + }, + "dependencies": { + "com.gameworkstore.patterns": "1.1.2" + } +} \ No newline at end of file diff --git a/package.json.meta b/package.json.meta new file mode 100644 index 0000000..4f2d073 --- /dev/null +++ b/package.json.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 8ad599dd1e292f84eb0739267c563750 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: