├── .gitignore ├── CHANGELOG.md ├── CHANGELOG.md.meta ├── DOCUMENTATION.pdf ├── DOCUMENTATION.pdf.meta ├── Editor.meta ├── Editor ├── Core.meta ├── Core │ ├── BuildTask.meta │ ├── BuildTask │ │ ├── BuildConfig.DestinationData.cs │ │ ├── BuildConfig.DestinationData.cs.meta │ │ ├── BuildConfig.GUI.cs │ │ ├── BuildConfig.GUI.cs.meta │ │ ├── BuildConfig.ModifierData.cs │ │ ├── BuildConfig.ModifierData.cs.meta │ │ ├── BuildConfig.Serialization.cs │ │ ├── BuildConfig.Serialization.cs.meta │ │ ├── BuildConfig.SourceData.cs │ │ ├── BuildConfig.SourceData.cs.meta │ │ ├── BuildConfig.cs │ │ ├── BuildConfig.cs.meta │ │ ├── BuildModifiers.meta │ │ ├── BuildModifiers │ │ │ ├── ABuildConfigModifer.GUI.cs │ │ │ ├── ABuildConfigModifer.GUI.cs.meta │ │ │ ├── ABuildConfigModifer.cs │ │ │ ├── ABuildConfigModifer.cs.meta │ │ │ ├── AExcludePathsByRegex_BuildModifier.GUI.cs │ │ │ ├── AExcludePathsByRegex_BuildModifier.GUI.cs.meta │ │ │ ├── AExcludePathsByRegex_BuildModifier.cs │ │ │ ├── AExcludePathsByRegex_BuildModifier.cs.meta │ │ │ ├── BuildModifierAttribute.cs │ │ │ ├── BuildModifierAttribute.cs.meta │ │ │ ├── CompressModifier.GUI.cs │ │ │ ├── CompressModifier.GUI.cs.meta │ │ │ ├── CompressModifier.cs │ │ │ ├── CompressModifier.cs.meta │ │ │ ├── DecompressModifier.GUI.cs │ │ │ ├── DecompressModifier.GUI.cs.meta │ │ │ ├── DecompressModifier.cs │ │ │ ├── DecompressModifier.cs.meta │ │ │ ├── ExcludeFilesModifier.cs │ │ │ ├── ExcludeFilesModifier.cs.meta │ │ │ ├── ExcludeFoldersModifier.cs │ │ │ └── ExcludeFoldersModifier.cs.meta │ │ ├── BuildTask.cs │ │ ├── BuildTask.cs.meta │ │ ├── BuildTaskReport.cs │ │ ├── BuildTaskReport.cs.meta │ │ ├── DownloadSources.meta │ │ ├── DownloadSources │ │ │ ├── ABrowsePathSource.GUI.cs │ │ │ ├── ABrowsePathSource.GUI.cs.meta │ │ │ ├── ABrowsePathSource.cs │ │ │ ├── ABrowsePathSource.cs.meta │ │ │ ├── ABuildSource.GUI.cs │ │ │ ├── ABuildSource.GUI.cs.meta │ │ │ ├── ABuildSource.cs │ │ │ ├── ABuildSource.cs.meta │ │ │ ├── BuildSourceAttribute.cs │ │ │ ├── BuildSourceAttribute.cs.meta │ │ │ ├── FileSource.cs │ │ │ ├── FileSource.cs.meta │ │ │ ├── FolderSource.cs │ │ │ ├── FolderSource.cs.meta │ │ │ ├── URLSource.GUI.cs │ │ │ ├── URLSource.GUI.cs.meta │ │ │ ├── URLSource.cs │ │ │ └── URLSource.cs.meta │ │ ├── Steps.meta │ │ ├── Steps │ │ │ ├── ABuildTask_Step.cs │ │ │ ├── ABuildTask_Step.cs.meta │ │ │ ├── BuildTaskStep_CacheSources.cs │ │ │ ├── BuildTaskStep_CacheSources.cs.meta │ │ │ ├── BuildTaskStep_GetSources.cs │ │ │ ├── BuildTaskStep_GetSources.cs.meta │ │ │ ├── BuildTaskStep_ModifyCachedSources.cs │ │ │ ├── BuildTaskStep_ModifyCachedSources.cs.meta │ │ │ ├── BuildTaskStep_PrepareDestinations.cs │ │ │ ├── BuildTaskStep_PrepareDestinations.cs.meta │ │ │ ├── BuildTaskStep_Upload.cs │ │ │ └── BuildTaskStep_Upload.cs.meta │ │ ├── UploadDestinations.meta │ │ └── UploadDestinations │ │ │ ├── ABuildDestination.GUI.cs │ │ │ ├── ABuildDestination.GUI.cs.meta │ │ │ ├── ABuildDestination.cs │ │ │ ├── ABuildDestination.cs.meta │ │ │ ├── BuildDestinationAttribute.cs │ │ │ ├── BuildDestinationAttribute.cs.meta │ │ │ ├── LocalPathDestination.GUI.cs │ │ │ ├── LocalPathDestination.GUI.cs.meta │ │ │ ├── LocalPathDestination.cs │ │ │ ├── LocalPathDestination.cs.meta │ │ │ ├── NoUploadDestination.cs │ │ │ └── NoUploadDestination.cs.meta │ ├── BuildUploaderReportWindow.cs │ ├── BuildUploaderReportWindow.cs.meta │ ├── BuildUploaderWelcomeWindow.cs │ ├── BuildUploaderWelcomeWindow.cs.meta │ ├── BuildUploaderWindow.cs │ ├── BuildUploaderWindow.cs.meta │ ├── Data.meta │ ├── Data │ │ ├── Preferences.cs │ │ ├── Preferences.cs.meta │ │ ├── ProjectSettings.cs │ │ └── ProjectSettings.cs.meta │ ├── Utils.meta │ ├── Utils │ │ ├── CustomDropdown.cs │ │ ├── CustomDropdown.cs.meta │ │ ├── CustomMultiDropdown.cs │ │ ├── CustomMultiDropdown.cs.meta │ │ ├── CustomTextField.cs │ │ ├── CustomTextField.cs.meta │ │ ├── CustomToggle.cs │ │ ├── CustomToggle.cs.meta │ │ ├── DropdownElement.cs │ │ ├── DropdownElement.cs.meta │ │ ├── EncodedEditorPrefs.cs │ │ ├── EncodedEditorPrefs.cs.meta │ │ ├── EncodedValue.cs │ │ ├── EncodedValue.cs.meta │ │ ├── IOUtils.cs │ │ ├── IOUtils.cs.meta │ │ ├── InternalReorderableList.cs │ │ ├── InternalReorderableList.cs.meta │ │ ├── InternalUtils.cs │ │ ├── InternalUtils.cs.meta │ │ ├── JSON.meta │ │ ├── JSON │ │ │ ├── JSON.Deserializer.cs │ │ │ ├── JSON.Deserializer.cs.meta │ │ │ ├── JSON.Serializer.cs │ │ │ ├── JSON.Serializer.cs.meta │ │ │ ├── JSON.Test.cs │ │ │ ├── JSON.Test.cs.meta │ │ │ ├── JSON.cs │ │ │ └── JSON.cs.meta │ │ ├── PasswordField.cs │ │ ├── PasswordField.cs.meta │ │ ├── ProgressUtils.cs │ │ ├── ProgressUtils.cs.meta │ │ ├── ProjectEditorPrefs.cs │ │ ├── ProjectEditorPrefs.cs.meta │ │ ├── ReflectionUtils.cs │ │ ├── ReflectionUtils.cs.meta │ │ ├── ReorderableListOfExcludeFileByRegexSelection.cs │ │ ├── ReorderableListOfExcludeFileByRegexSelection.cs.meta │ │ ├── SerializedPropertyExtensions.cs │ │ ├── SerializedPropertyExtensions.cs.meta │ │ ├── UIHelpers.cs │ │ ├── UIHelpers.cs.meta │ │ ├── Utils.cs │ │ ├── Utils.cs.meta │ │ ├── WebRequestMethod.cs │ │ ├── WebRequestMethod.cs.meta │ │ ├── WindowTab.cs │ │ ├── WindowTab.cs.meta │ │ ├── ZipUtils.cs │ │ └── ZipUtils.cs.meta │ ├── Wiki.meta │ ├── Wiki │ │ ├── Wiki.cs │ │ ├── Wiki.cs.meta │ │ ├── WikiAttribute.cs │ │ └── WikiAttribute.cs.meta │ ├── WindowUploadTab.cs │ └── WindowUploadTab.cs.meta ├── Services.meta ├── Services │ ├── AService.cs │ ├── AService.cs.meta │ ├── GithubService.meta │ ├── GithubService │ │ ├── Destinations.meta │ │ ├── Destinations │ │ │ ├── GithubNewReleaseDestination.GUI.cs │ │ │ ├── GithubNewReleaseDestination.GUI.cs.meta │ │ │ ├── GithubNewReleaseDestination.cs │ │ │ └── GithubNewReleaseDestination.cs.meta │ │ ├── GithubAPI.meta │ │ ├── GithubAPI │ │ │ ├── Github.cs │ │ │ └── Github.cs.meta │ │ ├── GithubService.Preferences.cs │ │ ├── GithubService.Preferences.cs.meta │ │ ├── GithubService.cs │ │ └── GithubService.cs.meta │ ├── SteamworksService.meta │ ├── SteamworksService │ │ ├── Data.meta │ │ ├── Data │ │ │ ├── Steam.meta │ │ │ ├── Steam │ │ │ │ ├── SteamApp.cs │ │ │ │ ├── SteamApp.cs.meta │ │ │ │ ├── SteamAppData.cs │ │ │ │ ├── SteamAppData.cs.meta │ │ │ │ ├── SteamBranch.cs │ │ │ │ ├── SteamBranch.cs.meta │ │ │ │ ├── SteamPageInfo.cs │ │ │ │ ├── SteamPageInfo.cs.meta │ │ │ │ ├── SteamSDK.cs │ │ │ │ └── SteamSDK.cs.meta │ │ │ ├── SteamUIUtils.cs │ │ │ └── SteamUIUtils.cs.meta │ │ ├── Modifiers.meta │ │ ├── Modifiers │ │ │ ├── SteamDRM_BuildModifier.GUI.cs │ │ │ ├── SteamDRM_BuildModifier.GUI.cs.meta │ │ │ ├── SteamDRM_BuildModifier.cs │ │ │ └── SteamDRM_BuildModifier.cs.meta │ │ ├── ReorderableListOfBranches.cs │ │ ├── ReorderableListOfBranches.cs.meta │ │ ├── ReorderableListOfDepots.cs │ │ ├── ReorderableListOfDepots.cs.meta │ │ ├── SteamUploadDestination.meta │ │ ├── SteamUploadDestination │ │ │ ├── Data.meta │ │ │ ├── Data │ │ │ │ ├── AppVDFFile.cs │ │ │ │ ├── AppVDFFile.cs.meta │ │ │ │ ├── DepotList.cs │ │ │ │ ├── DepotList.cs.meta │ │ │ │ ├── DepotVDFFile.cs │ │ │ │ ├── DepotVDFFile.cs.meta │ │ │ │ ├── IVdfMap.cs │ │ │ │ ├── IVdfMap.cs.meta │ │ │ │ ├── VDFFile.cs │ │ │ │ ├── VDFFile.cs.meta │ │ │ │ ├── VdfMap.cs │ │ │ │ └── VdfMap.cs.meta │ │ │ ├── SteamGuardTwoFactorWindow.cs │ │ │ ├── SteamGuardTwoFactorWindow.cs.meta │ │ │ ├── SteamGuardWindow.cs │ │ │ ├── SteamGuardWindow.cs.meta │ │ │ ├── SteamUploadDestination.GUI.cs │ │ │ ├── SteamUploadDestination.GUI.cs.meta │ │ │ ├── SteamUploadDestination.cs │ │ │ └── SteamUploadDestination.cs.meta │ │ ├── SteamworksService.cs │ │ ├── SteamworksService.cs.meta │ │ ├── SteamworksService_Preferences.cs │ │ ├── SteamworksService_Preferences.cs.meta │ │ ├── SteamworksService_ProjectSettings.cs │ │ └── SteamworksService_ProjectSettings.cs.meta │ ├── UnityCloudService.meta │ └── UnityCloudService │ │ ├── UnityCloudAPI.meta │ │ ├── UnityCloudAPI │ │ ├── UnityCloud.cs │ │ ├── UnityCloud.cs.meta │ │ ├── UnityCloudAPI.cs │ │ ├── UnityCloudAPI.cs.meta │ │ ├── UnityCloudAPIEditorUtil.cs │ │ ├── UnityCloudAPIEditorUtil.cs.meta │ │ ├── UnityCloudBuild.cs │ │ ├── UnityCloudBuild.cs.meta │ │ ├── UnityCloudTarget.cs │ │ └── UnityCloudTarget.cs.meta │ │ ├── UnityCloudBuildUI.cs │ │ ├── UnityCloudBuildUI.cs.meta │ │ ├── UnityCloudService.Preferences.cs │ │ ├── UnityCloudService.Preferences.cs.meta │ │ ├── UnityCloudService.cs │ │ ├── UnityCloudService.cs.meta │ │ ├── UnityCloudSource.GUI.cs │ │ ├── UnityCloudSource.GUI.cs.meta │ │ ├── UnityCloudSource.cs │ │ ├── UnityCloudSource.cs.meta │ │ ├── UnityCloudWindowTab.cs │ │ └── UnityCloudWindowTab.cs.meta ├── veugeljame.builduploader.editor.asmdef └── veugeljame.builduploader.editor.asmdef.meta ├── Icon.png ├── Icon.png.meta ├── LICENSE.md ├── LICENSE.md.meta ├── LargeIcon.png ├── LargeIcon.png.meta ├── README.md ├── README.md.meta ├── Scripts.meta ├── Scripts ├── UnityCloudService.meta ├── UnityCloudService │ ├── CloudBuildManifest.cs │ └── CloudBuildManifest.cs.meta ├── veugeljame.builduploader.asmdef └── veugeljame.builduploader.asmdef.meta ├── package.json ├── package.json.meta ├── warningicon.png └── warningicon.png.meta /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # 2.2.0 2 | - General 3 | - Added **Welcome Window** for more information `Window/Build Uploader/Welcome` 4 | - Added **Build Report Window** which shows after every build from the UI 5 | - Exposed a lot of code, so anyone can create and trigger a BuildTask without UI 6 | - BuildTasks create a BuildTaskReport to easily view logs 7 | - Made the Description text area bigger and added more options to copy/paste 8 | - All Sources/Modifiers/Destinations have a `?` to link to their documentation 9 | - Fixed new lines and tabs not serializing correctly 10 | - Fixed zipping a folder and saving to the same folder causing IOException 11 | - Fixed unzipping a .zip file halting editor 12 | - Fixed many edge cases causing the BuildTask to run indefinitely and not reporting exceptions 13 | - Fixed Custom Sources/Modifiers/Destinations made outside the Build Uploader package not showing in the dropdowns 14 | - Fixed LocalPathDestination requiring a file name when not compressing to a .zip 15 | - Minor UI improvements 16 | - Minor Logging improvements 17 | - Basic [Wiki](https://github.com/JamesVeug/UnitySteamBuildUploader/wiki) support 18 | - Sources 19 | - Each config can now have multiple Sources 20 | - Added `URLSource` to download files from online 21 | - Added `FolderSource` 22 | - Added PathType to File and Folder Source to select files within the project 23 | - Changed File Source to only handle files 24 | - Modifiers 25 | - Can now add/remove any Modifier same as Sources/Destinations 26 | - Can now be enabled/disabled 27 | - Added `CompressModifier` to turn a selection of files to a .zip file 28 | - Added `DecompressModifier` to unzip .zip files 29 | - Destinations 30 | - Each config can now have multiple Destinations 31 | - Added `NewGithubRelease` Destination 32 | - Added Duplicate File dropdown to LocalPathDestination. Set to Overwrite by default 33 | - Changed SteamworksDestination to create files in the Prepare step to fail before uploading starts 34 | - Fixed SteamworksDestination not showing Steam Guard popup on first run 35 | - Preferences 36 | - Added new checkbox to enable/disable auto decompressing .zip files from sources (On by default) 37 | - Added new checkbox to enable/disable auto saving of build tasks (Off by default) 38 | - Added new text field to change directory of cached builds. 39 | - Added tooltips to all preferences 40 | - Fixed Build Uploader not filtering by certain keywords 41 | 42 | # 2.1.1 43 | - General 44 | - First pass Mac/linux support 45 | - Fixed DRM Wrapping not working for games/companies with spaces in the name 46 | - Fixed DRM Wrapping not working with SteamGuard/Two Factor support properly 47 | - Safety guards to add modifiers back in case they disappear 48 | 49 | 50 | # 2.1.0 51 | ## Upload Tab 52 | - Added `Folder` Source so its now possible ot upload a folder for Steam DLC. 53 | - Added `LocalPath` Destination to copy a modified build to somewhere on your computer. 54 | - Changed `File` Source 55 | - Only uploads a selected file EXCEPT .exe which will upload the whole folder 56 | - Removed file extension restriction 57 | - Added build modifiers to change a Build before uploading 58 | - Remove files meeting regex 59 | - By default, all build configs remove `*_DoNotShip` files. 60 | - Steam DRM (Anti-piracy) 61 | - Upload .exe to Steam so the game has to be run from Steam. 62 | - Description no longer adds `Windows` to what gets uploaded to Steam. 63 | - Description is exactly what is written in the text box. 64 | - Lots of fixes and improvements to the upload process 65 | 66 | ## Preferences 67 | - Added Button to go open Cache folder 68 | - Added Toggle to enable/disable removing of cached files after uploading 69 | - Great for checking what you're uploading before it uploads! 70 | - Fixed trying to enter Steam credentials causing username/password to swap around making it impossible to enter 71 | 72 | ## General 73 | - Fixed a bunch of warnings that appear when recompiling the project 74 | 75 | ## Readme 76 | - Added instructions of how the upload process works 77 | - Lots more information 78 | 79 | # 2.0.1 80 | - Fixed issues where the package would not compile in Unity 2020 and 2019 81 | 82 | # 2.0.0 83 | - General 84 | - Package renamed to `Build Uploader` 85 | - Refactored Steamworks and UnityCloud code be in a services folder 86 | - Added support me, discord, github links to readme 87 | - All dropdowns describe what they need instead of something generic 88 | - Fixes 89 | - Moved all saved directories to a `Build Uploader` folder within `Application.persistentDataPath` 90 | - Minor UI adjustments to the Upload tab 91 | - Fixed warnings that appear when recompiling the project 92 | -------------------------------------------------------------------------------- /CHANGELOG.md.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c33e3493569c3ce43bf890340a9a3e1e 3 | timeCreated: 1717398587 -------------------------------------------------------------------------------- /DOCUMENTATION.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JamesVeug/UnitySteamBuildUploader/2e6df95625a9ad1f0fe70a93a6b1287d71c1c778/DOCUMENTATION.pdf -------------------------------------------------------------------------------- /DOCUMENTATION.pdf.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 51e9f00b69cf6f44a9b31f44fff0d156 3 | DefaultImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Editor.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3ffdcbeb9bf355c488dd80f8047bc38d 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Editor/Core.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 17d26a306576404495225fb59c7967d9 3 | timeCreated: 1740303734 -------------------------------------------------------------------------------- /Editor/Core/BuildTask.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 76677a5039b04f168a3c94322802a6fe 3 | timeCreated: 1741165910 -------------------------------------------------------------------------------- /Editor/Core/BuildTask/BuildConfig.DestinationData.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using UnityEngine; 3 | 4 | namespace Wireframe 5 | { 6 | public partial class BuildConfig 7 | { 8 | [Wiki("Destinations", "Specify where you want to upload your build. All destinations are executed at the same time.")] 9 | public class DestinationData 10 | { 11 | [Wiki("Enabled", "When on, this destination will upload all content of the source files.")] 12 | public bool Enabled = true; 13 | public ABuildDestination Destination; 14 | public UIHelpers.BuildDestinationsPopup.DestinationData DestinationType; 15 | 16 | public Dictionary Serialize() 17 | { 18 | Dictionary data = new Dictionary 19 | { 20 | ["enabled"] = Enabled, 21 | ["destinationType"] = DestinationType?.Type?.FullName, 22 | ["destination"] = Destination?.Serialize(), 23 | }; 24 | 25 | return data; 26 | } 27 | 28 | public void Deserialize(Dictionary data) 29 | { 30 | Enabled = data.ContainsKey("enabled") ? (bool)data["enabled"] : true; 31 | DestinationType = new UIHelpers.BuildDestinationsPopup.DestinationData(); 32 | if (data.TryGetValue("destinationType", out object destinationType) && destinationType != null) 33 | { 34 | var type = System.Type.GetType(destinationType as string); 35 | if (UIHelpers.DestinationsPopup.TryGetValueFromType(type, out DestinationType)) 36 | { 37 | if (Utils.CreateInstance(DestinationType.Type, out Destination)) 38 | { 39 | Destination.Deserialize(data["destination"] as Dictionary); 40 | } 41 | } 42 | else 43 | { 44 | Debug.LogError($"Destination type {destinationType} not found"); 45 | } 46 | } 47 | } 48 | } 49 | } 50 | } -------------------------------------------------------------------------------- /Editor/Core/BuildTask/BuildConfig.DestinationData.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ccbd3ed0b8a248e5903d0fbd865bd3d3 3 | timeCreated: 1741750981 -------------------------------------------------------------------------------- /Editor/Core/BuildTask/BuildConfig.GUI.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 03b589fe576f475db118fd3ccbae7343 3 | timeCreated: 1745223377 -------------------------------------------------------------------------------- /Editor/Core/BuildTask/BuildConfig.ModifierData.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using UnityEngine; 5 | 6 | namespace Wireframe 7 | { 8 | public partial class BuildConfig 9 | { 10 | [Wiki("Modifiers", "Make changes to the files gathered from sources before uploading. Modifiers are executed in one at a time and in order.")] 11 | public class ModifierData 12 | { 13 | [Wiki("Enabled", "When on, this modifier will modify the content of the files for a build.")] 14 | public bool Enabled; 15 | public ABuildConfigModifer Modifier; 16 | public UIHelpers.BuildModifiersPopup.ModifierData ModifierType; 17 | 18 | public ModifierData() 19 | { 20 | 21 | } 22 | 23 | public ModifierData(ABuildConfigModifer modifier, bool enabled=true) 24 | { 25 | Enabled = enabled; 26 | Modifier = modifier; 27 | ModifierType = UIHelpers.ModifiersPopup.Values.FirstOrDefault(a => a.Type == modifier.GetType()); 28 | } 29 | 30 | public Dictionary Serialize() 31 | { 32 | Dictionary data = new Dictionary 33 | { 34 | ["enabled"] = Enabled, 35 | ["modifierType"] = ModifierType?.Type?.FullName, 36 | ["modifier"] = Modifier?.Serialize() 37 | }; 38 | 39 | return data; 40 | } 41 | 42 | public void Deserialize(Dictionary data) 43 | { 44 | Enabled = data.ContainsKey("enabled") ? (bool)data["enabled"] : true; 45 | ModifierType = new UIHelpers.BuildModifiersPopup.ModifierData(); 46 | if (data.TryGetValue("modifierType", out object modifierType) && modifierType != null) 47 | { 48 | Type type = Type.GetType(modifierType as string); 49 | if (UIHelpers.ModifiersPopup.TryGetValueFromType(type, out ModifierType)) 50 | { 51 | if (Utils.CreateInstance(ModifierType.Type, out Modifier)) 52 | { 53 | Modifier.Deserialize(data["modifier"] as Dictionary); 54 | } 55 | } 56 | else 57 | { 58 | Debug.LogError($"Modifier type {modifierType} not found"); 59 | } 60 | } 61 | else 62 | { 63 | Debug.LogError($"Modifier type not found in data: {modifierType}"); 64 | } 65 | } 66 | } 67 | } 68 | } -------------------------------------------------------------------------------- /Editor/Core/BuildTask/BuildConfig.ModifierData.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 8cc6386e8f08480ca86d631494123d2d 3 | timeCreated: 1745489166 -------------------------------------------------------------------------------- /Editor/Core/BuildTask/BuildConfig.Serialization.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d6ff8f71a7e14c3c806dc311be576fa6 3 | timeCreated: 1741774171 -------------------------------------------------------------------------------- /Editor/Core/BuildTask/BuildConfig.SourceData.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using UnityEngine; 4 | 5 | namespace Wireframe 6 | { 7 | public partial class BuildConfig 8 | { 9 | [Wiki("Sources", "Specify what data you want to include in your upload. All Sources are executed at the same time then copied to the cached folder 1 by 1.")] 10 | public class SourceData 11 | { 12 | [Wiki("Enabled", "When on, this source will gather the content from a source and get it ready to be uploaded")] 13 | public bool Enabled = true; 14 | 15 | [Wiki("Export Path", "A sub-path in the cached directory of which this source will be saved to before being modified and uploaded. Leave empty to save to the root folder.")] 16 | public string ExportFolder; 17 | 18 | [Wiki("Duplicate Files", "When copying files over and there already being the same file, what should we do with the new file?")] 19 | public Utils.FileExistHandling DuplicateFileHandling = Utils.FileExistHandling.Error; 20 | 21 | public ABuildSource Source; 22 | public UIHelpers.BuildSourcesPopup.SourceData SourceType; 23 | 24 | public Dictionary Serialize() 25 | { 26 | Dictionary data = new Dictionary 27 | { 28 | ["enabled"] = Enabled, 29 | ["duplicateFileHandling"] = DuplicateFileHandling.ToString(), 30 | ["subFolderPath"] = ExportFolder, 31 | ["sourceType"] = SourceType?.Type?.FullName, 32 | ["source"] = Source?.Serialize() 33 | }; 34 | 35 | return data; 36 | } 37 | 38 | public void Deserialize(Dictionary data) 39 | { 40 | Enabled = data.ContainsKey("enabled") ? (bool)data["enabled"] : true; 41 | DuplicateFileHandling = data.ContainsKey("duplicateFileHandling") ? (Utils.FileExistHandling)System.Enum.Parse(typeof(Utils.FileExistHandling), data["duplicateFileHandling"] as string) : Utils.FileExistHandling.Error; 42 | ExportFolder = data.ContainsKey("subFolderPath") ? data["subFolderPath"] as string : ""; 43 | SourceType = new UIHelpers.BuildSourcesPopup.SourceData(); 44 | if (data.TryGetValue("sourceType", out object sourceType) && sourceType != null) 45 | { 46 | var type = System.Type.GetType(sourceType as string); 47 | if (UIHelpers.SourcesPopup.TryGetValueFromType(type, out SourceType)) 48 | { 49 | if (Utils.CreateInstance(SourceType.Type, out Source)) 50 | { 51 | Source.Deserialize(data["source"] as Dictionary); 52 | } 53 | } 54 | else 55 | { 56 | Debug.LogError($"Cannot find type {sourceType}"); 57 | } 58 | } 59 | else 60 | { 61 | Debug.LogError($"Source type {sourceType} not found"); 62 | } 63 | } 64 | } 65 | } 66 | } -------------------------------------------------------------------------------- /Editor/Core/BuildTask/BuildConfig.SourceData.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3600e21366934b66b409208394b3e0d9 3 | timeCreated: 1741750973 -------------------------------------------------------------------------------- /Editor/Core/BuildTask/BuildConfig.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 148062b1e4800ac4bb3f9caa30e1a5f6 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Core/BuildTask/BuildModifiers.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f9716bf27abb4d2eb0948ec7660b2ee8 3 | timeCreated: 1741208843 -------------------------------------------------------------------------------- /Editor/Core/BuildTask/BuildModifiers/ABuildConfigModifer.GUI.cs: -------------------------------------------------------------------------------- 1 | namespace Wireframe 2 | { 3 | public abstract partial class ABuildConfigModifer 4 | { 5 | protected internal abstract void OnGUIExpanded(ref bool isDirty); 6 | } 7 | } -------------------------------------------------------------------------------- /Editor/Core/BuildTask/BuildModifiers/ABuildConfigModifer.GUI.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 41ab370021044437bf042e8f21beab55 3 | timeCreated: 1745559429 -------------------------------------------------------------------------------- /Editor/Core/BuildTask/BuildModifiers/ABuildConfigModifer.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading.Tasks; 3 | 4 | namespace Wireframe 5 | { 6 | public abstract partial class ABuildConfigModifer 7 | { 8 | internal UIHelpers.BuildDestinationsPopup.DestinationData ModifierType; 9 | 10 | public ABuildConfigModifer() 11 | { 12 | // Required for reflection 13 | } 14 | 15 | public abstract bool IsSetup(out string reason); 16 | public abstract Task ModifyBuildAtPath(string cachedDirectory, BuildConfig buildConfig, int buildIndex, BuildTaskReport.StepResult stepResult); 17 | 18 | public virtual void TryGetWarnings(BuildConfig config, List warnings) 19 | { 20 | 21 | } 22 | 23 | public virtual void TryGetWarnings(ABuildSource source, List warnings) 24 | { 25 | 26 | } 27 | 28 | public virtual void TryGetWarnings(ABuildDestination destination, List warnings) 29 | { 30 | 31 | } 32 | 33 | public abstract Dictionary Serialize(); 34 | public abstract void Deserialize(Dictionary data); 35 | } 36 | } -------------------------------------------------------------------------------- /Editor/Core/BuildTask/BuildModifiers/ABuildConfigModifer.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b2699891d7b54343af70c426eeda034f 3 | timeCreated: 1741206762 -------------------------------------------------------------------------------- /Editor/Core/BuildTask/BuildModifiers/AExcludePathsByRegex_BuildModifier.GUI.cs: -------------------------------------------------------------------------------- 1 | namespace Wireframe 2 | { 3 | public abstract partial class AExcludePathsByRegex_BuildModifier 4 | { 5 | protected internal override void OnGUIExpanded(ref bool isDirty) 6 | { 7 | isDirty |= m_reorderableList.OnGUI(); 8 | } 9 | } 10 | } -------------------------------------------------------------------------------- /Editor/Core/BuildTask/BuildModifiers/AExcludePathsByRegex_BuildModifier.GUI.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1be50a6c5c244d8485927c1f51baa19c 3 | timeCreated: 1745559505 -------------------------------------------------------------------------------- /Editor/Core/BuildTask/BuildModifiers/AExcludePathsByRegex_BuildModifier.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: cc0ae362878e41829838ee2f20f6d592 3 | timeCreated: 1745219296 -------------------------------------------------------------------------------- /Editor/Core/BuildTask/BuildModifiers/BuildModifierAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Wireframe 4 | { 5 | public class BuildModifierAttribute : Attribute 6 | { 7 | public string DisplayName { get; } 8 | 9 | public BuildModifierAttribute(string displayName) 10 | { 11 | DisplayName = displayName; 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /Editor/Core/BuildTask/BuildModifiers/BuildModifierAttribute.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 5058ccca8c1c419cb1a952b1b574efde 3 | timeCreated: 1745492270 -------------------------------------------------------------------------------- /Editor/Core/BuildTask/BuildModifiers/CompressModifier.GUI.cs: -------------------------------------------------------------------------------- 1 | using UnityEditor; 2 | using UnityEngine; 3 | 4 | namespace Wireframe 5 | { 6 | public partial class CompressModifier 7 | { 8 | protected internal override void OnGUIExpanded(ref bool isDirty) 9 | { 10 | using (new GUILayout.HorizontalScope()) 11 | { 12 | GUILayout.Label("Compression Type", GUILayout.Width(120)); 13 | var newCompressionType = (CompressionType)EditorGUILayout.EnumPopup(m_compressionType); 14 | if (m_compressionType != newCompressionType) 15 | { 16 | m_compressionType = newCompressionType; 17 | isDirty = true; 18 | } 19 | } 20 | 21 | using (new GUILayout.HorizontalScope()) 22 | { 23 | GUILayout.Label("Compressed Name", GUILayout.Width(120)); 24 | var newFileName = EditorGUILayout.TextField(m_compressedFileName); 25 | if (m_compressedFileName != newFileName) 26 | { 27 | m_compressedFileName = newFileName; 28 | isDirty = true; 29 | } 30 | } 31 | 32 | using (new GUILayout.HorizontalScope()) 33 | { 34 | GUILayout.Label("Target Path", GUILayout.Width(120)); 35 | var newSuPath = EditorGUILayout.TextField(m_targetPathToCompress); 36 | if (m_targetPathToCompress != newSuPath) 37 | { 38 | m_targetPathToCompress = newSuPath; 39 | isDirty = true; 40 | } 41 | } 42 | 43 | using (new GUILayout.HorizontalScope()) 44 | { 45 | GUILayout.Label("Remove old files", GUILayout.Width(120)); 46 | var newRemoveContent = EditorGUILayout.Toggle(m_removeContentAfterCompress, GUILayout.Width(20)); 47 | if (m_removeContentAfterCompress != newRemoveContent) 48 | { 49 | m_removeContentAfterCompress = newRemoveContent; 50 | isDirty = true; 51 | } 52 | } 53 | } 54 | } 55 | } -------------------------------------------------------------------------------- /Editor/Core/BuildTask/BuildModifiers/CompressModifier.GUI.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 252b1b516a274a078489ed634a824cbf 3 | timeCreated: 1745704587 -------------------------------------------------------------------------------- /Editor/Core/BuildTask/BuildModifiers/CompressModifier.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 4cf7bb68414e46b98ef1a0b6d464353e 3 | timeCreated: 1745619615 -------------------------------------------------------------------------------- /Editor/Core/BuildTask/BuildModifiers/DecompressModifier.GUI.cs: -------------------------------------------------------------------------------- 1 | using UnityEditor; 2 | using UnityEngine; 3 | 4 | namespace Wireframe 5 | { 6 | public partial class DecompressModifier 7 | { 8 | protected internal override void OnGUIExpanded(ref bool isDirty) 9 | { 10 | using (new GUILayout.HorizontalScope()) 11 | { 12 | GUILayout.Label("Decompression Type", GUILayout.Width(120)); 13 | var newCompressionType = (DecompressionType)EditorGUILayout.EnumPopup(m_decompressionType); 14 | if (m_decompressionType != newCompressionType) 15 | { 16 | m_decompressionType = newCompressionType; 17 | isDirty = true; 18 | } 19 | } 20 | 21 | using (new GUILayout.HorizontalScope()) 22 | { 23 | GUILayout.Label("File Path", GUILayout.Width(120)); 24 | var newFileName = EditorGUILayout.TextField(m_filePath); 25 | if (m_filePath != newFileName) 26 | { 27 | m_filePath = newFileName; 28 | isDirty = true; 29 | } 30 | } 31 | 32 | using (new GUILayout.HorizontalScope()) 33 | { 34 | GUILayout.Label("Target Path", GUILayout.Width(120)); 35 | var newSuPath = EditorGUILayout.TextField(m_targetPathToCompress); 36 | if (m_targetPathToCompress != newSuPath) 37 | { 38 | m_targetPathToCompress = newSuPath; 39 | isDirty = true; 40 | } 41 | } 42 | 43 | using (new GUILayout.HorizontalScope()) 44 | { 45 | GUILayout.Label("Remove old file", GUILayout.Width(120)); 46 | var newRemoveContent = EditorGUILayout.Toggle(m_removeCompressedFile, GUILayout.Width(20)); 47 | if (m_removeCompressedFile != newRemoveContent) 48 | { 49 | m_removeCompressedFile = newRemoveContent; 50 | isDirty = true; 51 | } 52 | } 53 | } 54 | } 55 | } -------------------------------------------------------------------------------- /Editor/Core/BuildTask/BuildModifiers/DecompressModifier.GUI.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1ba7f76f9003457da445a155644fbcf3 3 | timeCreated: 1745836585 -------------------------------------------------------------------------------- /Editor/Core/BuildTask/BuildModifiers/DecompressModifier.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f69bf8069eff421daf4bc35c6ca88998 3 | timeCreated: 1745835707 -------------------------------------------------------------------------------- /Editor/Core/BuildTask/BuildModifiers/ExcludeFilesModifier.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | 3 | namespace Wireframe 4 | { 5 | [Wiki("ExcludeFilesModifier", "modifiers", "Exclude/delete files from the build by specifying a regex pattern.")] 6 | [BuildModifier("Exclude Files")] 7 | public class ExcludeFilesModifier : AExcludePathsByRegex_BuildModifier 8 | { 9 | protected override string ListHeader => "Exclude Files"; 10 | 11 | public ExcludeFilesModifier() : base() 12 | { 13 | 14 | } 15 | 16 | public ExcludeFilesModifier(params Selection[] fileRegexes) : base(fileRegexes) 17 | { 18 | 19 | } 20 | 21 | public ExcludeFilesModifier(params string[] fileRegexes) : base(fileRegexes) 22 | { 23 | 24 | } 25 | 26 | public ExcludeFilesModifier(string fileRegex, bool recursive = false, bool searchAllDirectories = false) : base(fileRegex, recursive, searchAllDirectories) 27 | { 28 | 29 | } 30 | 31 | protected override string[] GetFiles(string cachedDirectory, Selection regex) 32 | { 33 | SearchOption searchOption = regex.SearchAllDirectories ? 34 | SearchOption.AllDirectories : 35 | SearchOption.TopDirectoryOnly; 36 | 37 | string[] files = Directory.GetFiles(cachedDirectory, regex.Regex, searchOption); 38 | return files; 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /Editor/Core/BuildTask/BuildModifiers/ExcludeFilesModifier.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 32486e49e6254f86930bc11dcf80fba2 3 | timeCreated: 1741208853 -------------------------------------------------------------------------------- /Editor/Core/BuildTask/BuildModifiers/ExcludeFoldersModifier.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | 3 | namespace Wireframe 4 | { 5 | [Wiki("ExcludeFoldersModifier", "modifiers", "Exclude/delete folders from the build by specifying a regex pattern.")] 6 | [BuildModifier("Exclude Folders")] 7 | public class ExcludeFoldersModifier : AExcludePathsByRegex_BuildModifier 8 | { 9 | protected override string ListHeader => "Exclude Folders"; 10 | 11 | public ExcludeFoldersModifier() : base() 12 | { 13 | 14 | } 15 | 16 | public ExcludeFoldersModifier(params Selection[] fileRegexes) : base(fileRegexes) 17 | { 18 | 19 | } 20 | 21 | public ExcludeFoldersModifier(params string[] fileRegexes) : base(fileRegexes) 22 | { 23 | 24 | } 25 | 26 | public ExcludeFoldersModifier(string fileRegex, bool recursive = false, bool searchAllDirectories = false) : base(fileRegex, recursive, searchAllDirectories) 27 | { 28 | 29 | } 30 | 31 | protected override string[] GetFiles(string cachedDirectory, Selection regex) 32 | { 33 | SearchOption searchOption = regex.SearchAllDirectories ? 34 | SearchOption.AllDirectories : 35 | SearchOption.TopDirectoryOnly; 36 | 37 | string[] files = Directory.GetDirectories(cachedDirectory, regex.Regex, searchOption); 38 | return files; 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /Editor/Core/BuildTask/BuildModifiers/ExcludeFoldersModifier.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 28711e430982f884b91fb4188e23caaf 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Core/BuildTask/BuildTask.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 425f20909145b7d4b9fbaddbd911562b 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Core/BuildTask/BuildTaskReport.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e11094e4eaad4c068def8c11e55a9bb6 3 | timeCreated: 1745223820 -------------------------------------------------------------------------------- /Editor/Core/BuildTask/DownloadSources.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2e4133e6d7d32a745afbe025cea58281 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Editor/Core/BuildTask/DownloadSources/ABrowsePathSource.GUI.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using UnityEditor; 3 | using UnityEngine; 4 | 5 | namespace Wireframe 6 | { 7 | public abstract partial class ABrowsePathSource 8 | { 9 | private string ButtonText => GetType().GetCustomAttribute()?.ButtonText ?? GetType().Name; 10 | 11 | private GUIStyle m_pathButtonExistsStyle; 12 | private GUIStyle m_pathButtonDoesNotExistStyle; 13 | private GUIStyle m_pathInputFieldExistsStyle; 14 | private GUIStyle m_pathInputFieldDoesNotExistStyle; 15 | 16 | protected internal abstract string SelectFile(); 17 | 18 | private void Setup() 19 | { 20 | m_pathButtonExistsStyle = new GUIStyle(GUI.skin.button); 21 | m_pathButtonDoesNotExistStyle = new GUIStyle(GUI.skin.button); 22 | m_pathButtonDoesNotExistStyle.normal.textColor = Color.red; 23 | 24 | m_pathInputFieldExistsStyle = new GUIStyle(GUI.skin.textField); 25 | m_pathInputFieldDoesNotExistStyle = new GUIStyle(GUI.skin.textField); 26 | m_pathInputFieldDoesNotExistStyle.normal.textColor = Color.red; 27 | } 28 | 29 | public override void OnGUIExpanded(ref bool isDirty) 30 | { 31 | Setup(); 32 | 33 | using (new EditorGUILayout.HorizontalScope()) 34 | { 35 | GUILayout.Label("Path Type:", GUILayout.Width(120)); 36 | 37 | var newPathType = (PathType)EditorGUILayout.EnumPopup(m_pathType); 38 | if (newPathType != m_pathType) 39 | { 40 | m_pathType = newPathType; 41 | isDirty = true; 42 | } 43 | } 44 | 45 | bool exists = PathExists(); 46 | GUIStyle style = exists ? m_pathInputFieldExistsStyle : m_pathInputFieldDoesNotExistStyle; 47 | using (new EditorGUILayout.HorizontalScope()) 48 | { 49 | GUILayout.Label("Path:", GUILayout.Width(120)); 50 | 51 | string newPath = GUILayout.TextField(m_enteredFilePath, style, GUILayout.MaxWidth(200)); 52 | if (m_enteredFilePath != newPath) 53 | { 54 | m_enteredFilePath = newPath; 55 | isDirty = true; 56 | } 57 | 58 | if (GUILayout.Button("...", GUILayout.Width(20))) 59 | { 60 | string path = SelectFile(); 61 | isDirty |= SetNewPath(path); 62 | } 63 | 64 | if (GUILayout.Button("Show", GUILayout.Width(50))) 65 | { 66 | EditorUtility.RevealInFinder(GetFullPath()); 67 | } 68 | } 69 | 70 | using (new EditorGUILayout.HorizontalScope()) 71 | { 72 | using (new EditorGUI.DisabledScope(true)) 73 | { 74 | EditorGUILayout.TextField(GetFullPath(), style); 75 | } 76 | } 77 | } 78 | 79 | public override void OnGUICollapsed(ref bool isDirty, float maxWidth) 80 | { 81 | Setup(); 82 | 83 | bool exists = PathExists(); 84 | GUIStyle style = exists ? m_pathButtonExistsStyle : m_pathButtonDoesNotExistStyle; 85 | style.alignment = TextAnchor.MiddleLeft; 86 | 87 | string displayedPath = Utils.TruncateText(GetFullPath(), maxWidth, ButtonText); 88 | if (GUILayout.Button(displayedPath, style)) 89 | { 90 | string newPath = SelectFile(); 91 | if (m_pathType != PathType.Absolute) 92 | { 93 | string subPath = GetSubPath(); 94 | if (!newPath.StartsWith(subPath)) 95 | { 96 | EditorUtility.DisplayDialog("Invalid Path", "The selected path just start in:\n" + subPath + "\n\nOr change the PathType of the source." , "OK"); 97 | return; 98 | } 99 | } 100 | 101 | isDirty |= SetNewPath(newPath); 102 | } 103 | } 104 | } 105 | } -------------------------------------------------------------------------------- /Editor/Core/BuildTask/DownloadSources/ABrowsePathSource.GUI.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 5a68988cc0a8458c802fec67f39eea6d 3 | timeCreated: 1745560312 -------------------------------------------------------------------------------- /Editor/Core/BuildTask/DownloadSources/ABrowsePathSource.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 153199b81101485badd855ffb23a3f9f 3 | timeCreated: 1741159114 -------------------------------------------------------------------------------- /Editor/Core/BuildTask/DownloadSources/ABuildSource.GUI.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | 3 | namespace Wireframe 4 | { 5 | public abstract partial class ABuildSource 6 | { 7 | public string DisplayName => GetType().GetCustomAttribute()?.DisplayName ?? GetType().Name; 8 | public abstract void OnGUIExpanded(ref bool isDirty); 9 | public abstract void OnGUICollapsed(ref bool isDirty, float maxWidth); 10 | } 11 | } -------------------------------------------------------------------------------- /Editor/Core/BuildTask/DownloadSources/ABuildSource.GUI.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 4f05f8c78b6a4019be32cd9064e03174 3 | timeCreated: 1745560453 -------------------------------------------------------------------------------- /Editor/Core/BuildTask/DownloadSources/ABuildSource.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading.Tasks; 3 | 4 | namespace Wireframe 5 | { 6 | public abstract partial class ABuildSource : DropdownElement 7 | { 8 | public bool IsRunning => m_getSourceInProgress; 9 | 10 | protected float m_downloadProgress; 11 | protected string m_progressDescription; 12 | protected bool m_getSourceInProgress; 13 | 14 | 15 | public ABuildSource() : base() 16 | { 17 | // Required for reflection 18 | } 19 | 20 | public int Id { get; set; } 21 | public abstract Task GetSource(BuildConfig buildConfig, BuildTaskReport.StepResult stepResult); 22 | public abstract string SourceFilePath(); 23 | public abstract float DownloadProgress(); 24 | public abstract string ProgressTitle(); 25 | public abstract string ProgressDescription(); 26 | public abstract bool IsSetup(out string reason); 27 | public abstract string GetBuildDescription(); 28 | 29 | public virtual void CleanUp(BuildTaskReport.StepResult result) 30 | { 31 | m_downloadProgress = 0.0f; 32 | m_getSourceInProgress = false; 33 | } 34 | 35 | 36 | public abstract Dictionary Serialize(); 37 | public abstract void Deserialize(Dictionary data); 38 | } 39 | } -------------------------------------------------------------------------------- /Editor/Core/BuildTask/DownloadSources/ABuildSource.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f64fd6e21b27629468d987a83ed24364 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Core/BuildTask/DownloadSources/BuildSourceAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Wireframe 4 | { 5 | public class BuildSourceAttribute : Attribute 6 | { 7 | public string DisplayName { get; } 8 | public string ButtonText { get; } 9 | 10 | public BuildSourceAttribute(string displayName, string buttonText) 11 | { 12 | DisplayName = displayName; 13 | ButtonText = buttonText; 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /Editor/Core/BuildTask/DownloadSources/BuildSourceAttribute.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 065391df387a41f2be8f66852abf96c0 3 | timeCreated: 1745491734 -------------------------------------------------------------------------------- /Editor/Core/BuildTask/DownloadSources/FileSource.cs: -------------------------------------------------------------------------------- 1 | using UnityEditor; 2 | 3 | namespace Wireframe 4 | { 5 | /// 6 | /// User is able to select a file to upload 7 | /// 8 | /// NOTE: This classes name path is saved in the JSON file so avoid renaming 9 | /// 10 | [Wiki(nameof(FileSource), "sources", "Choose a File to upload")] 11 | [BuildSource("File", "Choose file Upload...")] 12 | public class FileSource : ABrowsePathSource 13 | { 14 | public FileSource() : base() 15 | { 16 | // Required for reflection 17 | } 18 | 19 | public FileSource(string path) : base(path) 20 | { 21 | } 22 | 23 | protected internal override string SelectFile() 24 | { 25 | return EditorUtility.OpenFilePanel("Select file to Upload", "", ""); 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /Editor/Core/BuildTask/DownloadSources/FileSource.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e4ac3e2a65bc9dc4a92a5fae01dffeac 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Core/BuildTask/DownloadSources/FolderSource.cs: -------------------------------------------------------------------------------- 1 | using UnityEditor; 2 | 3 | namespace Wireframe 4 | { 5 | /// 6 | /// User is able to select a folder to upload 7 | /// 8 | /// NOTE: This classes name path is saved in the JSON file so avoid renaming 9 | /// 10 | [Wiki(nameof(FolderSource), "sources", "Choose a Folder to upload")] 11 | [BuildSource("Folder", "Choose Folder Upload...")] 12 | public class FolderSource : ABrowsePathSource 13 | { 14 | public FolderSource() : base() 15 | { 16 | // Required for reflection 17 | } 18 | 19 | public FolderSource(string path) : base(path) 20 | { 21 | } 22 | 23 | protected internal override string SelectFile() 24 | { 25 | return EditorUtility.OpenFolderPanel("Select Folder to upload", m_enteredFilePath, ""); 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /Editor/Core/BuildTask/DownloadSources/FolderSource.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 4783d53f9afe46f498a4475b64ceed14 3 | timeCreated: 1741159067 -------------------------------------------------------------------------------- /Editor/Core/BuildTask/DownloadSources/URLSource.GUI.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using UnityEditor; 4 | using UnityEngine; 5 | 6 | namespace Wireframe 7 | { 8 | public partial class URLSource 9 | { 10 | public override void OnGUICollapsed(ref bool isDirty, float maxWidth) 11 | { 12 | using (new EditorGUILayout.HorizontalScope()) 13 | { 14 | WebRequestMethod newMethod = (WebRequestMethod)EditorGUILayout.EnumPopup(m_method, GUILayout.Width(80)); 15 | if (m_method != newMethod) 16 | { 17 | m_method = newMethod; 18 | isDirty = true; 19 | } 20 | 21 | float width = maxWidth - 120; 22 | string truncatedText = Utils.TruncateText(m_url, width, "No URL entered..."); 23 | GUILayout.Label(truncatedText, GUILayout.Width(width)); 24 | } 25 | } 26 | 27 | public override void OnGUIExpanded(ref bool isDirty) 28 | { 29 | using (new EditorGUILayout.HorizontalScope()) 30 | { 31 | GUILayout.Label("URL:", GUILayout.Width(120)); 32 | string newUrl = GUILayout.TextField(m_url); 33 | if (m_url != newUrl) 34 | { 35 | m_url = newUrl; 36 | isDirty = true; 37 | } 38 | } 39 | 40 | using (new EditorGUILayout.HorizontalScope()) 41 | { 42 | GUILayout.Label("Method:", GUILayout.Width(120)); 43 | WebRequestMethod newMethod = (WebRequestMethod)EditorGUILayout.EnumPopup(m_method); 44 | if (m_method != newMethod) 45 | { 46 | m_method = newMethod; 47 | isDirty = true; 48 | } 49 | } 50 | 51 | using (new EditorGUILayout.HorizontalScope()) 52 | { 53 | GUILayout.Label("File Name:", GUILayout.Width(120)); 54 | string newFileName = GUILayout.TextField(m_fileName); 55 | if (m_fileName != newFileName) 56 | { 57 | m_fileName = newFileName; 58 | isDirty = true; 59 | } 60 | } 61 | 62 | using (new EditorGUILayout.HorizontalScope()) 63 | { 64 | GUILayout.Label("Headers:", GUILayout.Width(120)); 65 | if (m_headers.Count > 0) 66 | { 67 | isDirty |= DrawHeader(m_headers, 0); 68 | } 69 | } 70 | 71 | using (new EditorGUILayout.HorizontalScope()) 72 | { 73 | GUILayout.Label("", GUILayout.Width(120)); 74 | using (new EditorGUILayout.VerticalScope()) 75 | { 76 | for (var i = 1; i < m_headers.Count; i++) 77 | { 78 | DrawHeader(m_headers, i); 79 | } 80 | 81 | if (GUILayout.Button("Add", GUILayout.Width(50))) 82 | { 83 | m_headers.Add(new Tuple("", "")); 84 | isDirty = true; 85 | } 86 | } 87 | } 88 | } 89 | 90 | private bool DrawHeader(List> headers, int index) 91 | { 92 | var header = headers[index]; 93 | using (new EditorGUILayout.HorizontalScope()) 94 | { 95 | if (GUILayout.Button("X", GUILayout.Width(20))) 96 | { 97 | m_headers.RemoveAt(index); 98 | return true; 99 | } 100 | 101 | string newKey = GUILayout.TextField(header.Item1, GUILayout.Width(120)); 102 | if (header.Item1 != newKey) 103 | { 104 | header = new Tuple(newKey, header.Item2); 105 | m_headers[index] = header; 106 | return true; 107 | } 108 | 109 | string newValue = GUILayout.TextField(header.Item2); 110 | if (header.Item2 != newValue) 111 | { 112 | header = new Tuple(header.Item1, newValue); 113 | m_headers[index] = header; 114 | return true; 115 | } 116 | } 117 | 118 | return false; 119 | } 120 | } 121 | } -------------------------------------------------------------------------------- /Editor/Core/BuildTask/DownloadSources/URLSource.GUI.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2c6ed90abfe642299ce598b2318c3582 3 | timeCreated: 1745561092 -------------------------------------------------------------------------------- /Editor/Core/BuildTask/DownloadSources/URLSource.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 44925ea7513b4d5494b920197fae0931 3 | timeCreated: 1741825469 -------------------------------------------------------------------------------- /Editor/Core/BuildTask/Steps.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9c4a9894e52043a0a13b2d9f6ee22140 3 | timeCreated: 1741168237 -------------------------------------------------------------------------------- /Editor/Core/BuildTask/Steps/ABuildTask_Step.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Text; 3 | using System.Threading.Tasks; 4 | 5 | namespace Wireframe 6 | { 7 | public abstract class ABuildTask_Step 8 | { 9 | public enum StepType 10 | { 11 | GetSources, 12 | CacheSources, 13 | ModifyCacheSources, 14 | PrepareDestinations, 15 | Upload, 16 | Cleanup 17 | } 18 | 19 | public enum StepProcess 20 | { 21 | Pre, 22 | Intra, 23 | Post 24 | } 25 | 26 | public abstract StepType Type { get; } 27 | public abstract Task Run(BuildTask buildTask, BuildTaskReport report); 28 | public abstract Task PostRunResult(BuildTask buildTask, BuildTaskReport report); 29 | 30 | protected void ReportCachedFiles(BuildTask buildTask, BuildTaskReport report) 31 | { 32 | List buildConfigs = buildTask.BuildConfigs; 33 | BuildTaskReport.StepResult[] results = report.NewReports(Type, buildConfigs.Count); 34 | for (var i = 0; i < buildConfigs.Count; i++) 35 | { 36 | var config = buildConfigs[i]; 37 | var result = results[i]; 38 | if (!config.Enabled) 39 | { 40 | continue; 41 | } 42 | 43 | string cachePath = buildTask.CachedLocations[i]; 44 | if (string.IsNullOrEmpty(cachePath)) 45 | { 46 | result.AddLog($"Config {i+1} has cached files. Something went wrong."); 47 | return; 48 | } 49 | 50 | ReportFilesAtPath(cachePath, $"Config {i+1} cached files:", result); 51 | } 52 | } 53 | 54 | protected void ReportFilesAtPath(string cachePath, string prefix, BuildTaskReport.StepResult result) 55 | { 56 | List allFiles = Utils.GetSortedFilesAndDirectories(cachePath); 57 | 58 | StringBuilder sb = new StringBuilder(); 59 | sb.AppendLine(prefix); 60 | foreach (string file in allFiles) 61 | { 62 | sb.AppendLine("\t-" + file); 63 | } 64 | result.AddLog(sb.ToString()); 65 | } 66 | } 67 | } -------------------------------------------------------------------------------- /Editor/Core/BuildTask/Steps/ABuildTask_Step.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a48357f3c59d45045b667fbacf2d541c 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Core/BuildTask/Steps/BuildTaskStep_CacheSources.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: edd82aaa1688b6449ae74205118bd39f 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Core/BuildTask/Steps/BuildTaskStep_GetSources.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 250e6d4e954c33044b25c90bbf2405f2 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Core/BuildTask/Steps/BuildTaskStep_ModifyCachedSources.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Threading.Tasks; 4 | 5 | namespace Wireframe 6 | { 7 | public class BuildTaskStep_ModifyCachedSources : ABuildTask_Step 8 | { 9 | public override StepType Type => StepType.ModifyCacheSources; 10 | 11 | public override async Task Run(BuildTask buildTask, BuildTaskReport report) 12 | { 13 | int progressId = ProgressUtils.Start(Type.ToString(), "Setting up..."); 14 | List buildConfigs = buildTask.BuildConfigs; 15 | 16 | List> tasks = new List>(); 17 | for (int j = 0; j < buildConfigs.Count; j++) 18 | { 19 | if (!buildConfigs[j].Enabled) 20 | { 21 | continue; 22 | } 23 | 24 | Task task = ModifyBuild(buildTask, j, report); 25 | tasks.Add(task); 26 | } 27 | 28 | bool allSuccessful = true; 29 | while (true) 30 | { 31 | bool done = true; 32 | float completionAmount = 0.0f; 33 | for (int j = 0; j < tasks.Count; j++) 34 | { 35 | Task task = tasks[j]; 36 | if (!task.IsCompleted) 37 | { 38 | done = false; 39 | } 40 | else 41 | { 42 | allSuccessful &= task.Result; 43 | completionAmount++; 44 | } 45 | } 46 | 47 | if (done) 48 | { 49 | break; 50 | } 51 | 52 | float progress = completionAmount / tasks.Count; 53 | ProgressUtils.Report(progressId, progress, "Waiting for all sources to be modified..."); 54 | await Task.Yield(); 55 | } 56 | 57 | ProgressUtils.Remove(progressId); 58 | return allSuccessful; 59 | } 60 | 61 | private async Task ModifyBuild(BuildTask task, int sourceIndex, BuildTaskReport report) 62 | { 63 | BuildConfig buildConfig = task.BuildConfigs[sourceIndex]; 64 | BuildTaskReport.StepResult[] results = report.NewReports(Type, buildConfig.Modifiers.Count); 65 | for (var i = 0; i < buildConfig.Modifiers.Count; i++) 66 | { 67 | var modifer = buildConfig.Modifiers[i]; 68 | if (!modifer.Enabled) 69 | { 70 | continue; 71 | } 72 | 73 | var stepResult = results[i]; 74 | try 75 | { 76 | bool success = await modifer.Modifier.ModifyBuildAtPath(task.CachedLocations[sourceIndex], buildConfig, sourceIndex, stepResult); 77 | if (!success) 78 | { 79 | return false; 80 | } 81 | } 82 | catch (Exception ex) 83 | { 84 | stepResult.AddException(ex); 85 | stepResult.SetFailed("Modifier failed: " + modifer.Modifier.GetType().Name); 86 | return false; 87 | } 88 | } 89 | 90 | return true; 91 | } 92 | 93 | public override Task PostRunResult(BuildTask buildTask, BuildTaskReport report) 94 | { 95 | return Task.FromResult(true); 96 | } 97 | } 98 | } -------------------------------------------------------------------------------- /Editor/Core/BuildTask/Steps/BuildTaskStep_ModifyCachedSources.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: cd129b37ec70490087671cbc39489ebb 3 | timeCreated: 1741211317 -------------------------------------------------------------------------------- /Editor/Core/BuildTask/Steps/BuildTaskStep_PrepareDestinations.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace Wireframe 7 | { 8 | public class BuildTaskStep_PrepareDestinations : ABuildTask_Step 9 | { 10 | public override StepType Type => StepType.PrepareDestinations; 11 | 12 | public override async Task Run(BuildTask buildTask, BuildTaskReport report) 13 | { 14 | int progressId = ProgressUtils.Start(Type.ToString(), "Setting up..."); 15 | List buildConfigs = buildTask.BuildConfigs; 16 | 17 | var tasks = new List, Task>>(); 18 | for (int j = 0; j < buildConfigs.Count; j++) 19 | { 20 | if (!buildConfigs[j].Enabled) 21 | { 22 | continue; 23 | } 24 | 25 | string cachePath = buildTask.CachedLocations[j]; 26 | Task task = PrepareDestination(buildConfigs[j], cachePath, buildTask.BuildDescription, report); 27 | List destinations = buildConfigs[j].Destinations.Where(a => a.Enabled).ToList(); 28 | tasks.Add(new Tuple, Task>(destinations, task)); 29 | } 30 | 31 | bool allSuccessful = true; 32 | while (true) 33 | { 34 | bool done = true; 35 | float completionAmount = 0.0f; 36 | int totalDestinations = 0; 37 | for (int j = 0; j < tasks.Count; j++) 38 | { 39 | Tuple, Task> tuple = tasks[j]; 40 | if (!tuple.Item2.IsCompleted) 41 | { 42 | done = false; 43 | foreach (BuildConfig.DestinationData data in tuple.Item1) 44 | { 45 | completionAmount += 0.5f; // TODO: Add progress to PrepareDestination 46 | } 47 | totalDestinations += tuple.Item1.Count; 48 | } 49 | else 50 | { 51 | allSuccessful &= tuple.Item2.Result; 52 | completionAmount += tuple.Item1.Count; 53 | } 54 | } 55 | 56 | if (done) 57 | { 58 | break; 59 | } 60 | 61 | float progress = completionAmount / totalDestinations; 62 | ProgressUtils.Report(progressId, progress, "Waiting for destinations to prepare..."); 63 | await Task.Yield(); 64 | } 65 | 66 | ProgressUtils.Remove(progressId); 67 | return allSuccessful; 68 | } 69 | 70 | private async Task PrepareDestination(BuildConfig buildConfig, string cachePath, string desc, BuildTaskReport report) 71 | { 72 | BuildTaskReport.StepResult[] reports = report.NewReports(Type, buildConfig.Destinations.Count); 73 | for (var i = 0; i < buildConfig.Destinations.Count; i++) 74 | { 75 | var destination = buildConfig.Destinations[i]; 76 | var result = reports[i]; 77 | if (!destination.Enabled) 78 | { 79 | result.AddLog("Skipping destination because it's disabled"); 80 | continue; 81 | } 82 | 83 | 84 | ABuildDestination buildDestination = destination.Destination; 85 | try 86 | { 87 | bool success = await buildDestination.Prepare(cachePath, desc, result); 88 | if (!success) 89 | { 90 | return false; 91 | } 92 | } 93 | catch (Exception e) 94 | { 95 | result.AddException(e); 96 | result.SetFailed("Failed to prepare destination: " + e.Message); 97 | return false; 98 | } 99 | } 100 | 101 | return true; 102 | } 103 | 104 | public override Task PostRunResult(BuildTask buildTask, BuildTaskReport report) 105 | { 106 | // Do nothing 107 | return Task.FromResult(true); 108 | } 109 | } 110 | } -------------------------------------------------------------------------------- /Editor/Core/BuildTask/Steps/BuildTaskStep_PrepareDestinations.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f5f2d85093019f84cabb86880e445bd0 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Core/BuildTask/Steps/BuildTaskStep_Upload.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 10ad6800b40e78c4db9a2e57c1af05d5 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Core/BuildTask/UploadDestinations.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9e4b1d422b4bb144bb07d6fd10f3bbdd 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Editor/Core/BuildTask/UploadDestinations/ABuildDestination.GUI.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | 3 | namespace Wireframe 4 | { 5 | public abstract partial class ABuildDestination 6 | { 7 | string DropdownElement.DisplayName => 8 | GetType().GetCustomAttribute()?.DisplayName ?? GetType().Name; 9 | 10 | protected internal abstract void OnGUIExpanded(ref bool isDirty); 11 | protected internal abstract void OnGUICollapsed(ref bool isDirty, float maxWidth); 12 | } 13 | } -------------------------------------------------------------------------------- /Editor/Core/BuildTask/UploadDestinations/ABuildDestination.GUI.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 4272f39934ad420dbf788ac5461db269 3 | timeCreated: 1745561227 -------------------------------------------------------------------------------- /Editor/Core/BuildTask/UploadDestinations/ABuildDestination.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading.Tasks; 3 | 4 | namespace Wireframe 5 | { 6 | public abstract partial class ABuildDestination : DropdownElement 7 | { 8 | protected string m_filePath; 9 | protected string m_buildDescription; 10 | 11 | protected float m_uploadProgress; 12 | protected string m_progressDescription; 13 | protected bool m_uploadInProgress; 14 | 15 | public ABuildDestination() 16 | { 17 | // Required for reflection 18 | } 19 | 20 | public bool IsRunning => m_uploadInProgress; 21 | public int Id { get; set; } 22 | 23 | public virtual Task Prepare(string filePath, string buildDescription, BuildTaskReport.StepResult result) 24 | { 25 | m_filePath = filePath; 26 | m_buildDescription = buildDescription; 27 | m_uploadInProgress = true; 28 | return Task.FromResult(true); 29 | } 30 | 31 | public abstract Task Upload(BuildTaskReport.StepResult stepResult); 32 | public abstract string ProgressTitle(); 33 | public abstract bool IsSetup(out string reason); 34 | public abstract Dictionary Serialize(); 35 | public abstract void Deserialize(Dictionary s); 36 | 37 | public virtual void CleanUp(BuildTaskReport.StepResult result) 38 | { 39 | m_uploadProgress = 0.0f; 40 | m_uploadInProgress = false; 41 | } 42 | 43 | public virtual float UploadProgress() 44 | { 45 | return m_uploadProgress; 46 | } 47 | 48 | public virtual string ProgressDescription() 49 | { 50 | return m_progressDescription; 51 | } 52 | 53 | public virtual Task PostUpload(BuildTaskReport.StepResult report) 54 | { 55 | return Task.FromResult(true); 56 | } 57 | } 58 | } -------------------------------------------------------------------------------- /Editor/Core/BuildTask/UploadDestinations/ABuildDestination.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b695e98155ae8664da6dfe5d6bb075aa 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Core/BuildTask/UploadDestinations/BuildDestinationAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Wireframe 4 | { 5 | public class BuildDestinationAttribute : Attribute 6 | { 7 | public string DisplayName { get; } 8 | 9 | public BuildDestinationAttribute(string displayName) 10 | { 11 | DisplayName = displayName; 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /Editor/Core/BuildTask/UploadDestinations/BuildDestinationAttribute.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c10b36db2a8e447ca7412d1df8fb478a 3 | timeCreated: 1745491975 -------------------------------------------------------------------------------- /Editor/Core/BuildTask/UploadDestinations/LocalPathDestination.GUI.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1807e37c99e544c993bfe5563044a0d5 3 | timeCreated: 1745401841 -------------------------------------------------------------------------------- /Editor/Core/BuildTask/UploadDestinations/LocalPathDestination.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 501693f250ee4e469fe4b36aef19c54c 3 | timeCreated: 1741425506 -------------------------------------------------------------------------------- /Editor/Core/BuildTask/UploadDestinations/NoUploadDestination.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading.Tasks; 3 | 4 | namespace Wireframe 5 | { 6 | /// 7 | /// A no destination end point when uploading a build 8 | /// Good for testing if your builds can be retrieved from the sources without worrying if they are uploading or not 9 | /// 10 | /// NOTE: This classes name path is saved in the JSON file so avoid renaming 11 | /// 12 | [Wiki("NowhereDestination", "destinations", "Does not move the files anywhere. Useful for testing sources and modifiers.")] 13 | [BuildDestination("Nowhere")] 14 | public class NoUploadDestination : ABuildDestination 15 | { 16 | public NoUploadDestination() : base() 17 | { 18 | // Required for reflection 19 | } 20 | 21 | protected internal override void OnGUIExpanded(ref bool isDirty) 22 | { 23 | 24 | } 25 | 26 | protected internal override void OnGUICollapsed(ref bool isDirty, float maxWidth) 27 | { 28 | 29 | } 30 | 31 | public override Task Upload(BuildTaskReport.StepResult result) 32 | { 33 | m_uploadProgress = 1; 34 | return Task.FromResult(true); 35 | } 36 | 37 | public override string ProgressTitle() 38 | { 39 | return "Uploading nowhere"; 40 | } 41 | 42 | public override bool IsSetup(out string reason) 43 | { 44 | reason = ""; 45 | return true; 46 | } 47 | 48 | public override Dictionary Serialize() 49 | { 50 | Dictionary data = new Dictionary(); 51 | return data; 52 | } 53 | 54 | public override void Deserialize(Dictionary data) 55 | { 56 | 57 | } 58 | } 59 | } -------------------------------------------------------------------------------- /Editor/Core/BuildTask/UploadDestinations/NoUploadDestination.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 7f6e5abd1ac7d4747b77ddc67b088c45 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Core/BuildUploaderReportWindow.cs: -------------------------------------------------------------------------------- 1 | using UnityEditor; 2 | using UnityEngine; 3 | 4 | namespace Wireframe 5 | { 6 | internal class BuildUploaderReportWindow : EditorWindow 7 | { 8 | private BuildTaskReport report; 9 | 10 | private string txt; 11 | private Vector2 scroll; 12 | 13 | public static void ShowWindow(BuildTaskReport report, string taskReport=null) 14 | { 15 | var window = GetWindow("Build Uploader Report"); 16 | 17 | Rect windowPosition = window.position; 18 | windowPosition.size = new Vector2(Screen.currentResolution.width * 0.5f, Screen.currentResolution.height * 0.5f); 19 | windowPosition.center = new Rect(0f, 0f, Screen.currentResolution.width, Screen.currentResolution.height).center; 20 | window.position = windowPosition; 21 | 22 | window.report = report; 23 | window.txt = taskReport ?? report.GetReport(); 24 | window.ShowPopup(); 25 | } 26 | 27 | private void OnGUI() 28 | { 29 | if (report == null) 30 | { 31 | EditorGUILayout.LabelField("No report available."); 32 | return; 33 | } 34 | 35 | if (GUILayout.Button("Save")) 36 | { 37 | string fileName = $"BuildReport_{report.StartTime:yyyy-MM-dd_HH-mm-ss}.txt"; 38 | string path = EditorUtility.SaveFilePanel("Save Report", "", fileName, "txt"); 39 | if (!string.IsNullOrEmpty(path)) 40 | { 41 | System.IO.File.WriteAllText(path, txt); 42 | } 43 | } 44 | 45 | scroll = EditorGUILayout.BeginScrollView(scroll); 46 | EditorGUILayout.TextArea(txt); 47 | EditorGUILayout.EndScrollView(); 48 | } 49 | } 50 | } -------------------------------------------------------------------------------- /Editor/Core/BuildUploaderReportWindow.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: bf8a64d22675469fb0cc8ad45c0e7221 3 | timeCreated: 1746267493 -------------------------------------------------------------------------------- /Editor/Core/BuildUploaderWelcomeWindow.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | using UnityEditor; 4 | using UnityEngine; 5 | using Object = UnityEngine.Object; 6 | 7 | namespace Wireframe { 8 | public class BuildUploaderWelcomeWindow : EditorWindow 9 | { 10 | private Vector2 scrollPosition; 11 | 12 | [MenuItem("Window/Build Uploader/Welcome", false, 1)] 13 | public static void ShowWindow() 14 | { 15 | BuildUploaderWelcomeWindow window = GetWindow(); 16 | window.titleContent = new GUIContent("Welcome to Build Uploader!", Utils.WindowIcon); 17 | 18 | Rect windowPosition = window.position; 19 | windowPosition.size = new Vector2(400, Screen.currentResolution.height * 0.5f); 20 | windowPosition.center = new Rect(0f, 0f, Screen.currentResolution.width, Screen.currentResolution.height).center; 21 | window.position = windowPosition; 22 | window.Show(); 23 | } 24 | 25 | private void OnGUI() 26 | { 27 | GUILayout.Label("Need help setting up the Build Uploader?"); 28 | 29 | GUIStyle style = GUI.skin.label; 30 | style.wordWrap = true; 31 | GUILayout.Label("Check out the Documentation for a step by step guide on how to set up the Build Uploader.", style); 32 | 33 | Links(); 34 | 35 | Changes(); 36 | } 37 | 38 | private void Changes() 39 | { 40 | GUILayout.Label("Changelog"); 41 | scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition); 42 | 43 | using (new EditorGUI.DisabledScope(true)) 44 | { 45 | GUIStyle style = GUI.skin.textArea; 46 | // style.richText = true; 47 | EditorGUILayout.TextArea(GetChangeLog(), style); 48 | } 49 | 50 | EditorGUILayout.EndScrollView(); 51 | } 52 | 53 | private string GetChangeLog() 54 | { 55 | var iconPath = "Packages/com.veugeljame.builduploader/CHANGELOG.md"; 56 | Object loadAssetAtPath = AssetDatabase.LoadAssetAtPath(iconPath, typeof(TextAsset)); 57 | string allText = loadAssetAtPath is TextAsset textAsset ? textAsset.text : ""; 58 | return allText; 59 | } 60 | 61 | private static void Links() 62 | { 63 | using (new EditorGUILayout.HorizontalScope()) 64 | { 65 | if (GUILayout.Button("Documentation")) 66 | { 67 | Application.OpenURL("https://github.com/JamesVeug/UnitySteamBuildUploader/wiki"); 68 | } 69 | 70 | if (GUILayout.Button("Discord")) 71 | { 72 | Application.OpenURL("https://discord.gg/R2UjXB6pQ8"); 73 | } 74 | 75 | if (GUILayout.Button("Github")) 76 | { 77 | Application.OpenURL("https://github.com/JamesVeug/UnitySteamBuildUploader"); 78 | } 79 | 80 | if (GUILayout.Button("Support Me")) 81 | { 82 | Application.OpenURL("https://buymeacoffee.com/jamesgamesnz"); 83 | } 84 | 85 | if (GUILayout.Button("Report Bug")) 86 | { 87 | Application.OpenURL("https://github.com/JamesVeug/UnitySteamBuildUploader/issues"); 88 | } 89 | } 90 | } 91 | } 92 | 93 | [InitializeOnLoad] 94 | public class ScriptReloadWatcher 95 | { 96 | static ScriptReloadWatcher() 97 | { 98 | EditorApplication.delayCall += OnScriptsReloaded; 99 | } 100 | 101 | private static void OnScriptsReloaded() 102 | { 103 | if (!ProjectEditorPrefs.GetBool("BuildUploaderWelcomeWindow")) 104 | { 105 | BuildUploaderWelcomeWindow.ShowWindow(); 106 | ProjectEditorPrefs.SetBool("BuildUploaderWelcomeWindow", true); 107 | } 108 | } 109 | } 110 | } -------------------------------------------------------------------------------- /Editor/Core/BuildUploaderWelcomeWindow.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c9385a9d37a34433994bcbd1809d4b4e 3 | timeCreated: 1743844413 -------------------------------------------------------------------------------- /Editor/Core/BuildUploaderWindow.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 696c638983c01384cb945a094c8c4b93 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Core/Data.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 05fba746a75b9c242bb69c1eba9dcbfb 3 | timeCreated: 1711530253 -------------------------------------------------------------------------------- /Editor/Core/Data/Preferences.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 61f63ee57dd92b140ba4724fa57ea9cb 3 | timeCreated: 1718792710 -------------------------------------------------------------------------------- /Editor/Core/Data/ProjectSettings.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using UnityEditor; 3 | 4 | namespace Wireframe 5 | { 6 | public class ProjectSettings : SettingsProvider 7 | { 8 | [SettingsProvider] 9 | public static SettingsProvider CreateSettingsProvider() 10 | { 11 | var provider = 12 | new ProjectSettings("Project/BuildUploader", SettingsScope.Project) 13 | { 14 | label = "Build Uploader", 15 | keywords = new HashSet(new[] 16 | { 17 | "Steam", "Build", "Uploader", "Pipe", "line", "Github", "Cache" 18 | }) 19 | }; 20 | 21 | return provider; 22 | } 23 | 24 | private ProjectSettings(string path, SettingsScope scopes, IEnumerable keywords = null) : base(path, scopes, keywords) 25 | { 26 | } 27 | 28 | public override void OnGUI(string searchContext) 29 | { 30 | base.OnGUI(searchContext); 31 | 32 | foreach (AService service in InternalUtils.AllServices()) 33 | { 34 | service.ProjectSettingsGUI(); 35 | } 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /Editor/Core/Data/ProjectSettings.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e1dbc47cbf4ce49409e7b65a12850702 3 | timeCreated: 1735725000 -------------------------------------------------------------------------------- /Editor/Core/Utils.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1ae739a3585b6b54c8f5936cbe6b61e9 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Editor/Core/Utils/CustomDropdown.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using UnityEditor; 4 | using UnityEngine; 5 | 6 | namespace Wireframe 7 | { 8 | public abstract class CustomDropdown where T : DropdownElement 9 | { 10 | public virtual string FirstEntryText => "Choose from Dropdown"; 11 | public virtual bool AddChooseFromDropdownEntry => true; 12 | public T[] Values 13 | { 14 | get 15 | { 16 | if(NeedsSettingUp()){ 17 | Refresh(); 18 | } 19 | return rawValues; 20 | } 21 | } 22 | 23 | protected abstract List FetchAllData(); 24 | 25 | private string[] names = null; 26 | private T[] values = null; 27 | private T[] rawValues = null; 28 | 29 | public void Refresh() 30 | { 31 | List data = new List(FetchAllData()); 32 | data.Sort(SortNames); 33 | rawValues = data.ToArray(); 34 | 35 | int count = data.Count + (AddChooseFromDropdownEntry ? 1 : 0); 36 | List namesTemp = new List(count); 37 | if (AddChooseFromDropdownEntry) 38 | { 39 | namesTemp.Add(FirstEntryText); 40 | } 41 | namesTemp.AddRange(data.ConvertAll(x => x.Id + ". " + x.DisplayName)); 42 | names = namesTemp.ToArray(); 43 | 44 | if (AddChooseFromDropdownEntry) 45 | { 46 | data.Insert(0, default); 47 | } 48 | values = data.ToArray(); 49 | } 50 | 51 | private int SortNames(T a, T b) 52 | { 53 | if (a.DisplayName == FirstEntryText) 54 | { 55 | return -1; 56 | } 57 | else if (b.DisplayName == FirstEntryText) 58 | { 59 | return 1; 60 | } 61 | 62 | int compareTo = a.Id.CompareTo(b.Id); 63 | if (compareTo != 0) 64 | { 65 | return compareTo; 66 | } 67 | return a.DisplayName.CompareTo(b.DisplayName); 68 | } 69 | 70 | public bool DrawPopup(IList collection, int index, params GUILayoutOption[] options) 71 | { 72 | T t = collection[index]; 73 | bool edited = DrawPopup(ref t, options); 74 | collection[index] = t; 75 | return edited; 76 | } 77 | 78 | public bool DrawPopup(ref T initial, params GUILayoutOption[] options) 79 | { 80 | if (NeedsSettingUp()) 81 | { 82 | Refresh(); 83 | if (NeedsSettingUp()) 84 | { 85 | return false; 86 | } 87 | } 88 | 89 | int index = -1; 90 | if (!AddChooseFromDropdownEntry && initial == null) 91 | { 92 | // Choose first entry in the list 93 | } 94 | else 95 | { 96 | for (int i = 0; i < values.Length; i++) 97 | { 98 | if (initial == null || initial.Equals(values[i])) 99 | { 100 | index = i; 101 | break; 102 | } 103 | } 104 | } 105 | 106 | bool edited = false; 107 | if (index < 0) 108 | { 109 | index = 0; 110 | edited = true; 111 | } 112 | 113 | int v = EditorGUILayout.Popup(index, names, options); 114 | if (v != index) 115 | { 116 | edited = true; 117 | } 118 | 119 | T newConfig = values[v]; 120 | initial = newConfig; 121 | return edited; 122 | } 123 | 124 | private bool NeedsSettingUp() 125 | { 126 | return names == null || names.Length == 0 || values == null || values.Length == 0; 127 | } 128 | } 129 | } -------------------------------------------------------------------------------- /Editor/Core/Utils/CustomDropdown.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 07428d69718f9454cbd3d69c0f8a82b0 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Core/Utils/CustomMultiDropdown.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using UnityEditor; 3 | using UnityEngine; 4 | 5 | namespace Wireframe 6 | { 7 | public abstract class CustomMultiDropdown where Y : DropdownElement 8 | { 9 | public virtual string FirstEntryText => "Choose from Dropdown"; 10 | 11 | public abstract List<(T, List)> GetAllData(); 12 | 13 | private static Dictionary nameLookup; 14 | private static Dictionary valueLookup; 15 | 16 | public virtual bool IsItemValid(Y y) 17 | { 18 | return true; 19 | } 20 | 21 | public bool DrawPopup(T target, ref Y initial, params GUILayoutOption[] options) 22 | { 23 | if (FailedToRefresh()) 24 | { 25 | return false; 26 | } 27 | else if (target == null) 28 | { 29 | return false; 30 | } 31 | else if (!valueLookup.ContainsKey(target)) 32 | { 33 | return false; 34 | } 35 | 36 | Y[] values = valueLookup[target]; 37 | 38 | int index = -1; 39 | for (int i = 0; i < values.Length; i++) 40 | { 41 | if (initial == null || initial.Equals(values[i])) 42 | { 43 | index = i; 44 | break; 45 | } 46 | } 47 | 48 | bool edited = false; 49 | if (index < 0) 50 | { 51 | index = 0; 52 | edited = true; 53 | } 54 | 55 | string[] names = nameLookup[target]; 56 | if (names.Length == 0) 57 | return false; 58 | 59 | int v = EditorGUILayout.Popup(index, names, options); 60 | if (v != index) 61 | { 62 | edited = true; 63 | } 64 | 65 | Y newConfig = values[v]; 66 | initial = newConfig; 67 | return edited; 68 | } 69 | 70 | public void Refresh() 71 | { 72 | nameLookup = new Dictionary(); 73 | valueLookup = new Dictionary(); 74 | 75 | List<(T, List)> currentBuilds = GetAllData(); 76 | if (currentBuilds == null) 77 | return; 78 | 79 | for (int i = 0; i < currentBuilds.Count; i++) 80 | { 81 | List builds = new List(currentBuilds[i].Item2); 82 | builds.Sort(SortByName); 83 | 84 | List names = new List(); 85 | List values = new List(); 86 | 87 | names.Add(FirstEntryText); 88 | values.Add(default); 89 | 90 | for (var j = 0; j < builds.Count; j++) 91 | { 92 | if (IsItemValid(builds[j])) 93 | { 94 | values.Add(builds[j]); 95 | names.Add(builds[j].Id + ". " + builds[j].DisplayName); 96 | } 97 | } 98 | 99 | nameLookup[currentBuilds[i].Item1] = names.ToArray(); 100 | valueLookup[currentBuilds[i].Item1] = values.ToArray(); 101 | } 102 | } 103 | 104 | public virtual int SortByName(Y a, Y b) 105 | { 106 | if (a.DisplayName == FirstEntryText) 107 | { 108 | return -1; 109 | } 110 | else if (b.DisplayName == FirstEntryText) 111 | { 112 | return 1; 113 | } 114 | 115 | int compareTo = a.Id.CompareTo(b.Id); 116 | if (compareTo != 0) 117 | { 118 | return compareTo; 119 | } 120 | return a.DisplayName.CompareTo(b.DisplayName); 121 | } 122 | 123 | private bool FailedToRefresh() 124 | { 125 | if (NeedsRefreshing()) 126 | { 127 | Refresh(); 128 | if (NeedsRefreshing()) 129 | { 130 | return true; 131 | } 132 | } 133 | 134 | return false; 135 | } 136 | 137 | private static bool NeedsRefreshing() 138 | { 139 | return nameLookup == null || nameLookup.Count == 0 || valueLookup == null || valueLookup.Count == 0; 140 | } 141 | } 142 | } -------------------------------------------------------------------------------- /Editor/Core/Utils/CustomMultiDropdown.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 67fdda0967028184aa3657e5a2c61ac2 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Core/Utils/CustomTextField.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | namespace Wireframe 4 | { 5 | public static class CustomTextField 6 | { 7 | public static bool Draw(ref string text, params GUILayoutOption[] options) 8 | { 9 | string newPath = GUILayout.TextField(text, options); 10 | if (text != newPath) 11 | { 12 | text = newPath; 13 | return true; 14 | } 15 | 16 | return false; 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /Editor/Core/Utils/CustomTextField.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d50a39491c23475e8f9a48aca76a59d7 3 | timeCreated: 1741598192 -------------------------------------------------------------------------------- /Editor/Core/Utils/CustomToggle.cs: -------------------------------------------------------------------------------- 1 | using UnityEditor; 2 | using UnityEngine; 3 | 4 | namespace Wireframe 5 | { 6 | public static class CustomToggle 7 | { 8 | public static bool DrawToggle(string label, ref bool value, params GUILayoutOption[] options) 9 | { 10 | bool newValue = EditorGUILayout.Toggle(label, value, options); 11 | if (newValue != value) 12 | { 13 | value = newValue; 14 | return true; 15 | } 16 | 17 | return false; 18 | } 19 | public static bool DrawToggle(ref bool value, params GUILayoutOption[] options) 20 | { 21 | bool newValue = EditorGUILayout.Toggle(value, options); 22 | if (newValue != value) 23 | { 24 | value = newValue; 25 | return true; 26 | } 27 | 28 | return false; 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /Editor/Core/Utils/CustomToggle.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e8c5e5e94db6ef44b8e8bf8ad4fb7ec8 3 | timeCreated: 1717332108 -------------------------------------------------------------------------------- /Editor/Core/Utils/DropdownElement.cs: -------------------------------------------------------------------------------- 1 | namespace Wireframe 2 | { 3 | public interface DropdownElement 4 | { 5 | int Id { get; } 6 | string DisplayName { get; } 7 | } 8 | } -------------------------------------------------------------------------------- /Editor/Core/Utils/DropdownElement.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d8c15988c96449f7b9409e50bcf4c31b 3 | timeCreated: 1740303799 -------------------------------------------------------------------------------- /Editor/Core/Utils/EncodedEditorPrefs.cs: -------------------------------------------------------------------------------- 1 | using UnityEditor; 2 | 3 | namespace Wireframe 4 | { 5 | public static class EncodedEditorPrefs 6 | { 7 | public static void MigrateKeyToEncoded(string oldKey, string newKey) 8 | { 9 | if (!EditorPrefs.HasKey(oldKey)) 10 | { 11 | return; 12 | } 13 | 14 | string encodedNewKey = EncodedValue.Encode64(newKey); 15 | if (typeof(T) == typeof(bool)) 16 | { 17 | bool unencodedValue = EditorPrefs.GetBool(oldKey); 18 | string encodedValue = EncodedValue.Encode64(unencodedValue); 19 | EditorPrefs.SetString(encodedNewKey, encodedValue); 20 | } 21 | else if (typeof(T) == typeof(string)) 22 | { 23 | string unencodedValue = EditorPrefs.GetString(oldKey); 24 | string encodedValue = EncodedValue.Encode64(unencodedValue); 25 | EditorPrefs.SetString(encodedNewKey, encodedValue); 26 | } 27 | else 28 | { 29 | throw new System.NotImplementedException(typeof(T).FullName); 30 | } 31 | EditorPrefs.DeleteKey(oldKey); 32 | } 33 | 34 | public static void SetBool(string key, bool value) 35 | { 36 | string encodedKey = EncodedValue.Encode64(key); 37 | string encodedValue = EncodedValue.Encode64(value); 38 | EditorPrefs.SetString(encodedKey, encodedValue); 39 | } 40 | 41 | public static bool GetBool(string key, bool defaultValue) 42 | { 43 | string encodedKey = EncodedValue.Encode64(key); 44 | string encodedDefaultValue = EncodedValue.Encode64(defaultValue); 45 | string encodedValue = EditorPrefs.GetString(encodedKey, encodedDefaultValue); 46 | return EncodedValue.Decode64(encodedValue); 47 | } 48 | 49 | public static void SetString(string key, string value) 50 | { 51 | string encodedKey = EncodedValue.Encode64(key); 52 | string encodedValue = EncodedValue.Encode64(value); 53 | EditorPrefs.SetString(encodedKey, encodedValue); 54 | } 55 | 56 | public static string GetString(string key, string defaultValue) 57 | { 58 | string encodedKey = EncodedValue.Encode64(key); 59 | string encodedDefaultValue = EncodedValue.Encode64(defaultValue); 60 | string encodedValue = EditorPrefs.GetString(encodedKey, encodedDefaultValue); 61 | return EncodedValue.Decode64(encodedValue); 62 | } 63 | } 64 | } -------------------------------------------------------------------------------- /Editor/Core/Utils/EncodedEditorPrefs.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 84d0d461583b43dca381c4db4413d081 3 | timeCreated: 1741491931 -------------------------------------------------------------------------------- /Editor/Core/Utils/EncodedValue.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Wireframe 4 | { 5 | public readonly struct EncodedValue : IEquatable> 6 | { 7 | private readonly byte[] m_value; 8 | 9 | public EncodedValue(T value) 10 | { 11 | m_value = Encode(value); 12 | } 13 | 14 | public EncodedValue(byte[] bytes) 15 | { 16 | m_value = bytes; 17 | } 18 | 19 | public static byte[] Encode(T value) 20 | { 21 | char[] m = new char[] { 'B', 'i', 'l', 'd', 'U', 'p', 'l', 'o', 'd', 'r' }; 22 | char[] s = value.ToString().ToCharArray(); 23 | char[] c = new char[m.Length + s.Length]; 24 | for (int i = 0; i < m.Length; i++) 25 | { 26 | c[i] = (char)(m[i] + 10); 27 | } 28 | 29 | for (int i = 0; i < s.Length; i++) 30 | { 31 | c[i + 10] = (char)(s[i] + 10); 32 | } 33 | 34 | return System.Text.Encoding.UTF8.GetBytes(c); 35 | } 36 | 37 | public string Encode64() 38 | { 39 | return Convert.ToBase64String(m_value); 40 | } 41 | 42 | public static string Encode64(T value) 43 | { 44 | var base64String = Convert.ToBase64String(Encode(value)); 45 | return base64String; 46 | } 47 | 48 | public static EncodedValue Decode64(string s) 49 | { 50 | if (string.IsNullOrEmpty(s)) 51 | { 52 | return new EncodedValue(Array.Empty()); 53 | } 54 | 55 | return new EncodedValue(Convert.FromBase64String(s)); 56 | } 57 | 58 | private static T Decode(byte[] bytes) 59 | { 60 | if (bytes.Length == 0) 61 | { 62 | return default; 63 | } 64 | 65 | char[] chars = System.Text.Encoding.UTF8.GetChars(bytes); 66 | for (int i = 0; i < chars.Length; i++) 67 | { 68 | chars[i] = (char)(chars[i] - 10); 69 | } 70 | 71 | string v = new string(chars, 10, chars.Length - 10); 72 | T newValue = (T)Convert.ChangeType(v, typeof(T)); 73 | return newValue; 74 | } 75 | 76 | public static implicit operator T(EncodedValue encodedValue) 77 | { 78 | return Decode(encodedValue.m_value); 79 | } 80 | 81 | public static implicit operator EncodedValue(T value) 82 | { 83 | return new EncodedValue(value); 84 | } 85 | 86 | public static EncodedValue Encoded(string s) 87 | { 88 | if (string.IsNullOrEmpty(s)) 89 | { 90 | return new EncodedValue(Array.Empty()); 91 | } 92 | 93 | return new EncodedValue(Convert.FromBase64String(s)); 94 | } 95 | 96 | public bool Equals(EncodedValue other) 97 | { 98 | return Equals(m_value, other.m_value); 99 | } 100 | 101 | public override bool Equals(object obj) 102 | { 103 | return obj is EncodedValue other && Equals(other); 104 | } 105 | 106 | public override int GetHashCode() 107 | { 108 | return (m_value != null ? m_value.GetHashCode() : 0); 109 | } 110 | } 111 | } -------------------------------------------------------------------------------- /Editor/Core/Utils/EncodedValue.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 51ca863d2a73425da685b359cf9fc58d 3 | timeCreated: 1741471941 -------------------------------------------------------------------------------- /Editor/Core/Utils/IOUtils.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using System.Threading.Tasks; 3 | 4 | namespace Wireframe 5 | { 6 | public static class IOUtils 7 | { 8 | public static Task WriteAllTextAsync(string path, string content) 9 | { 10 | #if UNITY_2021_1_OR_NEWER 11 | return File.WriteAllTextAsync(path, content); 12 | #else 13 | return Task.Run(() => 14 | { 15 | File.WriteAllText(path, content); 16 | }); 17 | #endif 18 | } 19 | 20 | public static Task WriteAllBytesAsync(string path, byte[] content) 21 | { 22 | #if UNITY_2021_2_OR_NEWER 23 | return File.WriteAllBytesAsync(path, content); 24 | #else 25 | return Task.Run(() => 26 | { 27 | File.WriteAllBytes(path, content); 28 | }); 29 | #endif 30 | } 31 | 32 | public static Task ReadAllBytesAsync(string path) 33 | { 34 | #if UNITY_2021_2_OR_NEWER 35 | return File.ReadAllBytesAsync(path); 36 | #else 37 | return Task.Run(() => 38 | { 39 | return File.ReadAllBytes(path); 40 | }); 41 | #endif 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /Editor/Core/Utils/IOUtils.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2587a5dcd33141c29c4ba7d27d7cfa81 3 | timeCreated: 1746394869 -------------------------------------------------------------------------------- /Editor/Core/Utils/InternalReorderableList.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using UnityEditor; 4 | using UnityEditorInternal; 5 | using UnityEngine; 6 | 7 | namespace Wireframe 8 | { 9 | public abstract class InternalReorderableList 10 | { 11 | protected List list; 12 | protected bool dirty = false; 13 | 14 | private ReorderableList reorderableList; 15 | private string header = ""; 16 | private Action addCallback; 17 | 18 | public void Initialize(List listReference, string listHeader, Action onAddCallback=null) 19 | { 20 | header = listHeader; 21 | addCallback = onAddCallback; 22 | list = listReference; 23 | 24 | reorderableList = new ReorderableList(listReference, typeof(T), true, true, true, true); 25 | reorderableList.drawElementCallback = DrawItem; 26 | reorderableList.drawHeaderCallback = DrawHeader; 27 | reorderableList.onAddCallback = AddCallback; 28 | reorderableList.onRemoveCallback = RemoveCallback; 29 | reorderableList.onChangedCallback = ChangedCallback; 30 | } 31 | 32 | public bool OnGUI() 33 | { 34 | reorderableList.DoLayoutList(); 35 | if (dirty) 36 | { 37 | dirty = false; 38 | return true; 39 | } 40 | return false; 41 | } 42 | 43 | protected abstract void DrawItem(Rect rect, int index, bool isActive, bool isFocused); 44 | protected abstract T CreateItem(int index); 45 | 46 | protected virtual void DrawHeader(Rect rect) 47 | { 48 | // your GUI code here for list header 49 | EditorGUI.LabelField(rect, header); 50 | } 51 | 52 | private void AddCallback(ReorderableList l) 53 | { 54 | l.index++; 55 | T depot = CreateItem(list.Count + 1); 56 | list.Add(depot); 57 | dirty = true; 58 | 59 | addCallback?.Invoke(depot); 60 | } 61 | 62 | private void RemoveCallback(ReorderableList list1) 63 | { 64 | list.RemoveAt(list1.index); 65 | dirty = true; 66 | } 67 | 68 | private void ChangedCallback(ReorderableList list1) 69 | { 70 | dirty = true; 71 | } 72 | } 73 | } -------------------------------------------------------------------------------- /Editor/Core/Utils/InternalReorderableList.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: dc192554497341078bffa207e84d8fd5 3 | timeCreated: 1740601410 -------------------------------------------------------------------------------- /Editor/Core/Utils/InternalUtils.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Reflection; 4 | 5 | namespace Wireframe 6 | { 7 | internal static class InternalUtils 8 | { 9 | private static List allServices = null; 10 | private static List allBuildSources = null; 11 | private static List allBuildModifiers = null; 12 | private static List allBuildDestinations = null; 13 | 14 | public static List AllServices() 15 | { 16 | if (allServices == null) 17 | { 18 | FetchAllTypes(); 19 | } 20 | 21 | return allServices; 22 | } 23 | 24 | public static T GetService() where T : AService 25 | { 26 | foreach (AService service in AllServices()) 27 | { 28 | if (service is T t) 29 | { 30 | return t; 31 | } 32 | } 33 | 34 | return null; 35 | } 36 | 37 | public static List AllBuildSources() 38 | { 39 | if (allBuildSources == null) 40 | { 41 | FetchAllTypes(); 42 | } 43 | 44 | return allBuildSources; 45 | } 46 | 47 | public static List AllBuildModifiers() 48 | { 49 | if (allBuildModifiers == null) 50 | { 51 | FetchAllTypes(); 52 | } 53 | 54 | return allBuildModifiers; 55 | } 56 | 57 | public static List AllBuildDestinations() 58 | { 59 | if (allBuildDestinations == null) 60 | { 61 | FetchAllTypes(); 62 | } 63 | 64 | return allBuildDestinations; 65 | } 66 | 67 | private static void FetchAllTypes() 68 | { 69 | allServices = new List(); 70 | allBuildSources = new List(); 71 | allBuildModifiers = new List(); 72 | allBuildDestinations = new List(); 73 | 74 | Type sourceType = typeof(ABuildSource); 75 | Type serviceType = typeof(AService); 76 | Type modifierType = typeof(ABuildConfigModifer); 77 | Type destinationType = typeof(ABuildDestination); 78 | 79 | // Slow but only done once per compilation 80 | foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies()) 81 | { 82 | foreach (Type type in assembly.GetTypes()) 83 | { 84 | if (!type.IsClass) continue; 85 | if (type.IsAbstract) continue; 86 | 87 | if (sourceType.IsAssignableFrom(type)) 88 | { 89 | allBuildSources.Add(type); 90 | } 91 | else if (serviceType.IsAssignableFrom(type)) 92 | { 93 | allServices.Add((AService)Activator.CreateInstance(type)); 94 | } 95 | else if (destinationType.IsAssignableFrom(type)) 96 | { 97 | allBuildDestinations.Add(type); 98 | } 99 | else if (modifierType.IsAssignableFrom(type)) 100 | { 101 | allBuildModifiers.Add(type); 102 | } 103 | } 104 | } 105 | } 106 | } 107 | } -------------------------------------------------------------------------------- /Editor/Core/Utils/InternalUtils.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f0c8b76f42594bc0840b1b7fb5f6147a 3 | timeCreated: 1740303172 -------------------------------------------------------------------------------- /Editor/Core/Utils/JSON.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a6b4a667d59e2c14c868c586fbfbb4b5 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Editor/Core/Utils/JSON/JSON.Deserializer.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 6452c098d8067724dbe01c381a83012e 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Core/Utils/JSON/JSON.Serializer.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 122170aa11ecb904faf651ffe5331701 3 | timeCreated: 1735707931 -------------------------------------------------------------------------------- /Editor/Core/Utils/JSON/JSON.Test.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: be9eed299da5dca49a675f0110fdb542 3 | timeCreated: 1735707861 -------------------------------------------------------------------------------- /Editor/Core/Utils/JSON/JSON.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Wireframe 4 | { 5 | /// 6 | /// Simple JSON class to serialize and deserialize objects. 7 | /// Not really efficient, does not work for all cases but at least works for the Build Uploader. 8 | /// Using this instead of a library to avoid dependencies and JSONUtility does not work for what I need. 9 | /// 10 | public static partial class JSON 11 | { 12 | public static string SerializeObject(T data) 13 | { 14 | return JSONSerializer.TOJSON(data, typeof(T)); 15 | } 16 | 17 | public static string SerializeObject(object data) 18 | { 19 | Type type = data == null ? null : data.GetType(); 20 | return JSONSerializer.TOJSON(data, type); 21 | } 22 | 23 | public static T DeserializeObject(string json) 24 | { 25 | return JSONDeserializer.FromJSON(json); 26 | } 27 | 28 | public static object DeserializeObject(string json, Type type) 29 | { 30 | return JSONDeserializer.FromJSON(json, type); 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /Editor/Core/Utils/JSON/JSON.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 51fbcfc1790b9b14fb92ea3c06249133 3 | timeCreated: 1735470116 -------------------------------------------------------------------------------- /Editor/Core/Utils/PasswordField.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | 5 | namespace Wireframe 6 | { 7 | public static class PasswordField 8 | { 9 | private static Dictionary m_passwordFieldToggles = new Dictionary(); 10 | public static string Draw(string label, string tooltip, int labelLength, string password, char mask = '*', Action onHelpPressed = null) 11 | { 12 | using (new GUILayout.HorizontalScope()) 13 | { 14 | int realLabelLength = labelLength; 15 | if (onHelpPressed != null) 16 | { 17 | realLabelLength -= 20; 18 | } 19 | 20 | GUILayout.Label(new GUIContent(label, tooltip), GUILayout.Width(realLabelLength)); 21 | 22 | if (onHelpPressed != null) 23 | { 24 | if (GUILayout.Button("?", GUILayout.Width(20))) 25 | { 26 | onHelpPressed(); 27 | } 28 | } 29 | 30 | if (password == null) 31 | { 32 | password = ""; 33 | } 34 | 35 | if (!m_passwordFieldToggles.TryGetValue(label, out bool showPassword)) 36 | { 37 | m_passwordFieldToggles.Add(label, false); 38 | } 39 | 40 | string newPassword = null; 41 | if (showPassword) 42 | { 43 | newPassword = GUILayout.TextField(password); 44 | 45 | } 46 | else 47 | { 48 | newPassword = GUILayout.PasswordField(password, mask); 49 | } 50 | 51 | if (GUILayout.Button(showPassword ? "Hide" : "Show", GUILayout.Width(50))) 52 | { 53 | m_passwordFieldToggles[label] = !showPassword; 54 | } 55 | 56 | return newPassword; 57 | } 58 | 59 | } 60 | } 61 | } -------------------------------------------------------------------------------- /Editor/Core/Utils/PasswordField.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f60c4fcef47b6454482680d7d654d9c2 3 | timeCreated: 1712117816 -------------------------------------------------------------------------------- /Editor/Core/Utils/ProgressUtils.cs: -------------------------------------------------------------------------------- 1 | #if UNITY_2020_2_OR_NEWER 2 | using UnityEditor; 3 | #endif 4 | 5 | namespace Wireframe 6 | { 7 | public static class ProgressUtils 8 | { 9 | public static bool Exists(int progressId) 10 | { 11 | #if UNITY_2020_2_OR_NEWER 12 | return Progress.Exists(progressId); 13 | #else 14 | return false; 15 | #endif 16 | } 17 | 18 | public static void Remove(int progressId) 19 | { 20 | #if UNITY_2020_2_OR_NEWER 21 | Progress.Remove(progressId); 22 | #endif 23 | } 24 | 25 | public static int Start(string title, string desc) 26 | { 27 | #if UNITY_2020_2_OR_NEWER 28 | return Progress.Start(title, desc); 29 | #else 30 | return -1; 31 | #endif 32 | } 33 | 34 | public static void Report(int progressId, float progress, string description) 35 | { 36 | #if UNITY_2020_2_OR_NEWER 37 | Progress.Report(progressId, progress, description); 38 | #endif 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /Editor/Core/Utils/ProgressUtils.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1d36dd046bc24d5d97d9eec9f69fffa3 3 | timeCreated: 1740598638 -------------------------------------------------------------------------------- /Editor/Core/Utils/ProjectEditorPrefs.cs: -------------------------------------------------------------------------------- 1 | namespace Wireframe 2 | { 3 | public class ProjectEditorPrefs 4 | { 5 | private static readonly string ProjectKeySuffix = $"{UnityEditor.PlayerSettings.companyName}_{UnityEditor.PlayerSettings.productName}_"; 6 | 7 | public static void SetBool(string key, bool value) 8 | { 9 | UnityEditor.EditorPrefs.SetBool(ProjectKeySuffix + key, value); 10 | } 11 | 12 | public static bool GetBool(string key, bool defaultValue = false) 13 | { 14 | return UnityEditor.EditorPrefs.GetBool(ProjectKeySuffix + key, defaultValue); 15 | } 16 | 17 | public static void SetInt(string key, int value) 18 | { 19 | UnityEditor.EditorPrefs.SetInt(ProjectKeySuffix + key, value); 20 | } 21 | 22 | public static int GetInt(string key, int defaultValue = 0) 23 | { 24 | return UnityEditor.EditorPrefs.GetInt(ProjectKeySuffix + key, defaultValue); 25 | } 26 | 27 | public static void SetString(string key, string value) 28 | { 29 | UnityEditor.EditorPrefs.SetString(ProjectKeySuffix + key, value); 30 | } 31 | 32 | public static string GetString(string key, string defaultValue = "") 33 | { 34 | return UnityEditor.EditorPrefs.GetString(ProjectKeySuffix + key, defaultValue); 35 | } 36 | 37 | public static void SetFloat(string key, float value) 38 | { 39 | UnityEditor.EditorPrefs.SetFloat(ProjectKeySuffix + key, value); 40 | } 41 | 42 | public static float GetFloat(string key, float defaultValue = 0.0f) 43 | { 44 | return UnityEditor.EditorPrefs.GetFloat(ProjectKeySuffix + key, defaultValue); 45 | } 46 | 47 | public static void DeleteKey(string key) 48 | { 49 | UnityEditor.EditorPrefs.DeleteKey(ProjectKeySuffix + key); 50 | } 51 | 52 | public static bool HasKey(string key) 53 | { 54 | return UnityEditor.EditorPrefs.HasKey(ProjectKeySuffix + key); 55 | } 56 | } 57 | } -------------------------------------------------------------------------------- /Editor/Core/Utils/ProjectEditorPrefs.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 790193a9051449d990c4fe2712a3ab32 3 | timeCreated: 1741813390 -------------------------------------------------------------------------------- /Editor/Core/Utils/ReflectionUtils.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Reflection; 4 | 5 | namespace Wireframe 6 | { 7 | internal static class ReflectionUtils 8 | { 9 | public static IEnumerable GetAllFields(Type type) 10 | { 11 | while (type != null) 12 | { 13 | foreach (var field in type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly)) 14 | { 15 | yield return field; 16 | } 17 | type = type.BaseType; 18 | } 19 | } 20 | 21 | /// 22 | /// Gets an attribute on an enum field value 23 | /// 24 | /// The type of the attribute you want to retrieve 25 | /// The enum value 26 | /// The attribute of type T that exists on the enum value 27 | /// ().Description;]]> 28 | public static T GetAttributeOfType(this Enum enumVal) where T:Attribute 29 | { 30 | var type = enumVal.GetType(); 31 | var memInfo = type.GetMember(enumVal.ToString()); 32 | var attributes = memInfo[0].GetCustomAttributes(typeof(T), false); 33 | return (attributes.Length > 0) ? (T)attributes[0] : null; 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /Editor/Core/Utils/ReflectionUtils.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 5a3e279cd4604a199342b77ed7d6c99b 3 | timeCreated: 1745716180 -------------------------------------------------------------------------------- /Editor/Core/Utils/ReorderableListOfExcludeFileByRegexSelection.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | namespace Wireframe 4 | { 5 | public class ReorderableListOfExcludeFileByRegexSelection : InternalReorderableList 6 | { 7 | protected override void DrawItem(Rect rect, int index, bool isActive, bool isFocused) 8 | { 9 | AExcludePathsByRegex_BuildModifier.Selection element = list[index]; 10 | 11 | Rect rect0 = new Rect(rect.x, rect.y, Mathf.Min(20, rect.width / 4), rect.height); 12 | bool e = GUI.Toggle(rect0, element.Enabled, ""); 13 | if (e != element.Enabled) 14 | { 15 | element.Enabled = e; 16 | dirty = true; 17 | } 18 | 19 | Rect rect1 = new Rect(rect0.x + rect0.width, rect.y, Mathf.Min(120, rect.width / 4), rect.height); 20 | string n = GUI.TextField(rect1, element.Regex); 21 | if (n != element.Regex) 22 | { 23 | element.Regex = n; 24 | dirty = true; 25 | } 26 | 27 | Rect rect2 = new Rect(rect1.x + rect1.width + 20, rect.y, Mathf.Min(150, rect.width / 4), rect.height); 28 | bool b2 = GUI.Toggle(rect2, element.SearchAllDirectories, "Search all Directories"); 29 | if (b2 != element.SearchAllDirectories) 30 | { 31 | element.SearchAllDirectories = b2; 32 | dirty = true; 33 | } 34 | 35 | Rect rect3 = new Rect(rect2.x + rect2.width + 10, rect.y, Mathf.Min(200, rect.width / 4), rect.height); 36 | bool b = GUI.Toggle(rect3, element.Recursive, "Delete Recursively"); 37 | if (b != element.Recursive) 38 | { 39 | element.Recursive = b; 40 | dirty = true; 41 | } 42 | } 43 | 44 | protected override AExcludePathsByRegex_BuildModifier.Selection CreateItem(int index) 45 | { 46 | return new AExcludePathsByRegex_BuildModifier.Selection(); 47 | } 48 | } 49 | } -------------------------------------------------------------------------------- /Editor/Core/Utils/ReorderableListOfExcludeFileByRegexSelection.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: dca8182ac1e945ecb61051522f3d6918 3 | timeCreated: 1741207626 -------------------------------------------------------------------------------- /Editor/Core/Utils/SerializedPropertyExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using UnityEditor; 3 | 4 | namespace Wireframe 5 | { 6 | public static class SerializedPropertyExtensions 7 | { 8 | public static object GetValue(this SerializedProperty prop) 9 | { 10 | if (prop == null) return null; 11 | 12 | #if UNITY_2022_1_OR_NEWER 13 | return prop.GetValue(); 14 | #else 15 | // Note: I think this doesn't actually work. It's not used so not bothering to fix it 16 | var path = prop.propertyPath.Replace(".Array.data[", "["); 17 | object obj = prop.serializedObject.targetObject; 18 | var elements = path.Split('.'); 19 | foreach (var element in elements) 20 | { 21 | if (element.Contains("[")) 22 | { 23 | var elementName = element.Substring(0, element.IndexOf("[")); 24 | var index = System.Convert.ToInt32(element.Substring(element.IndexOf("[")).Replace("[", "") 25 | .Replace("]", "")); 26 | obj = GetValue_Imp(obj, elementName, index); 27 | } 28 | else 29 | { 30 | obj = GetValue_Imp(obj, element); 31 | } 32 | } 33 | 34 | return obj; 35 | #endif 36 | } 37 | 38 | public static void SetValue(this SerializedProperty prop, object value) 39 | { 40 | if (prop == null) return; 41 | 42 | #if UNITY_2022_1_OR_NEWER 43 | prop.boxedValue = value; 44 | #else 45 | // Note: I think this doesn't actually work. It's not used so not bothering to fix it 46 | prop.managedReferenceValue = value; 47 | #endif 48 | } 49 | 50 | private static object GetValue_Imp(object source, string name) 51 | { 52 | if (source == null) 53 | return null; 54 | var type = source.GetType(); 55 | 56 | while (type != null) 57 | { 58 | var f = type.GetField(name, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance); 59 | if (f != null) 60 | return f.GetValue(source); 61 | 62 | var p = type.GetProperty(name, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase); 63 | if (p != null) 64 | return p.GetValue(source, null); 65 | 66 | type = type.BaseType; 67 | } 68 | return null; 69 | } 70 | 71 | private static object GetValue_Imp(object source, string name, int index) 72 | { 73 | var enumerable = GetValue_Imp(source, name) as System.Collections.IEnumerable; 74 | if (enumerable == null) return null; 75 | var enm = enumerable.GetEnumerator(); 76 | //while (index-- >= 0) 77 | // enm.MoveNext(); 78 | //return enm.Current; 79 | 80 | for (int i = 0; i <= index; i++) 81 | { 82 | if (!enm.MoveNext()) return null; 83 | } 84 | return enm.Current; 85 | } 86 | } 87 | } -------------------------------------------------------------------------------- /Editor/Core/Utils/SerializedPropertyExtensions.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 361c44df12b9476f9d6ee3d9b6327d70 3 | timeCreated: 1740598242 -------------------------------------------------------------------------------- /Editor/Core/Utils/UIHelpers.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 48bf5fa0636d4277b7abe0060153ea12 3 | timeCreated: 1740305274 -------------------------------------------------------------------------------- /Editor/Core/Utils/Utils.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e5f6746b41204d6c856e33f95bf8f5b5 3 | timeCreated: 1740306356 -------------------------------------------------------------------------------- /Editor/Core/Utils/WebRequestMethod.cs: -------------------------------------------------------------------------------- 1 | namespace Wireframe 2 | { 3 | public enum WebRequestMethod 4 | { 5 | GET, 6 | POST, 7 | PUT, 8 | DELETE 9 | } 10 | } -------------------------------------------------------------------------------- /Editor/Core/Utils/WebRequestMethod.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3ff5e8dd19804c3ca393c6d7990c4c74 3 | timeCreated: 1741826006 -------------------------------------------------------------------------------- /Editor/Core/Utils/WindowTab.cs: -------------------------------------------------------------------------------- 1 | namespace Wireframe 2 | { 3 | internal abstract class WindowTab 4 | { 5 | protected BuildUploaderWindow UploaderWindow; 6 | public abstract string TabName { get; } 7 | 8 | public virtual bool Enabled => true; 9 | 10 | public void Initialize(BuildUploaderWindow uploaderWindow) 11 | { 12 | this.UploaderWindow = uploaderWindow; 13 | } 14 | 15 | public virtual void OnGUI() 16 | { 17 | 18 | } 19 | 20 | public virtual void Update() 21 | { 22 | 23 | } 24 | 25 | public virtual void Save() 26 | { 27 | 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /Editor/Core/Utils/WindowTab.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 87ce626338afd92449d9940c6251d542 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Core/Utils/ZipUtils.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 12869e707fbb4758a091cbd708b2d450 3 | timeCreated: 1740599823 -------------------------------------------------------------------------------- /Editor/Core/Wiki.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ec9c57d25166488faddc61a842eca22e 3 | timeCreated: 1745706086 -------------------------------------------------------------------------------- /Editor/Core/Wiki/Wiki.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 502594b6210a4f51bb63b9824eec1743 3 | timeCreated: 1745706358 -------------------------------------------------------------------------------- /Editor/Core/Wiki/WikiAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Wireframe 4 | { 5 | public class WikiAttribute : Attribute 6 | { 7 | public string SubPath { get; } 8 | public string Name { get; } 9 | public string Text { get; } 10 | public int Order { get; } 11 | public WikiAttribute(string name, string subpath, string text, int order=0) 12 | { 13 | SubPath = subpath; 14 | Name = name; 15 | Text = text; 16 | Order = order; 17 | } 18 | 19 | public WikiAttribute(string name, string text, int order=0) 20 | { 21 | Name = name; 22 | Text = text; 23 | Order = order; 24 | SubPath = ""; 25 | } 26 | } 27 | 28 | internal static class WikiAttributeExtensions 29 | { 30 | public static bool TryGetWikiLink(this object source, out string url) 31 | { 32 | if (source == null) 33 | { 34 | url = null; 35 | return false; 36 | } 37 | 38 | return TryGetWikiLink(source.GetType(), out url); 39 | } 40 | 41 | public static bool TryGetWikiLink(this Type type, out string url) 42 | { 43 | var wikiAttribute = (WikiAttribute)Attribute.GetCustomAttribute(type, typeof(WikiAttribute)); 44 | if (wikiAttribute == null) 45 | { 46 | url = null; 47 | return false; 48 | } 49 | 50 | url = $"https://github.com/JamesVeug/UnitySteamBuildUploader/wiki/{wikiAttribute.SubPath}#{wikiAttribute.Name}"; 51 | return true; 52 | } 53 | } 54 | } -------------------------------------------------------------------------------- /Editor/Core/Wiki/WikiAttribute.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 10bf898bcf2246da95327981d697d37f 3 | timeCreated: 1745706097 -------------------------------------------------------------------------------- /Editor/Core/WindowUploadTab.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b581702f50eb0e048b815b55f2bb88d4 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Services.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: fbb5a844b278bc347b7adfcaef7e2afc 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Editor/Services/AService.cs: -------------------------------------------------------------------------------- 1 | namespace Wireframe 2 | { 3 | public abstract class AService 4 | { 5 | internal virtual WindowTab WindowTabType => null; 6 | public abstract bool IsReadyToStartBuild(out string reason); 7 | public abstract void PreferencesGUI(); 8 | public abstract void ProjectSettingsGUI(); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Editor/Services/AService.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f79503efe9af1104dbad7a53fac529cf 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Services/GithubService.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1ac3f5545a41493c9a52525f8f88664e 3 | timeCreated: 1741582427 -------------------------------------------------------------------------------- /Editor/Services/GithubService/Destinations.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a136c5a6fd6740e8bf3def74a27910e3 3 | timeCreated: 1741597029 -------------------------------------------------------------------------------- /Editor/Services/GithubService/Destinations/GithubNewReleaseDestination.GUI.cs: -------------------------------------------------------------------------------- 1 | using UnityEditor; 2 | using UnityEngine; 3 | 4 | namespace Wireframe 5 | { 6 | public partial class GithubNewReleaseDestination 7 | { 8 | protected internal override void OnGUICollapsed(ref bool isDirty, float maxWidth) 9 | { 10 | string text = $"{m_owner}/{m_repo}/releases/tag/{m_tagName} ({m_target})"; 11 | EditorGUILayout.LabelField(text, EditorStyles.boldLabel); 12 | } 13 | 14 | protected internal override void OnGUIExpanded(ref bool isDirty) 15 | { 16 | if (GUILayout.Button("?", GUILayout.Width(20))) 17 | { 18 | Application.OpenURL( 19 | "https://docs.github.com/en/rest/releases/releases?apiVersion=2022-11-28#create-a-release"); 20 | } 21 | 22 | using (new GUILayout.HorizontalScope()) 23 | { 24 | GUILayout.Label("Owner:", GUILayout.Width(120)); 25 | isDirty |= CustomTextField.Draw(ref m_owner); 26 | } 27 | 28 | using (new GUILayout.HorizontalScope()) 29 | { 30 | GUILayout.Label("Repo:", GUILayout.Width(120)); 31 | isDirty |= CustomTextField.Draw(ref m_repo); 32 | } 33 | 34 | using (new GUILayout.HorizontalScope()) 35 | { 36 | GUILayout.Label("Release Name:", GUILayout.Width(120)); 37 | isDirty |= CustomTextField.Draw(ref m_releaseName); 38 | } 39 | 40 | using (new GUILayout.HorizontalScope()) 41 | { 42 | GUILayout.Label("Tag:", GUILayout.Width(120)); 43 | isDirty |= CustomTextField.Draw(ref m_tagName); 44 | } 45 | 46 | using (new GUILayout.HorizontalScope()) 47 | { 48 | GUILayout.Label("Branch or Commit:", GUILayout.Width(120)); 49 | isDirty |= CustomTextField.Draw(ref m_target); 50 | } 51 | 52 | using (new GUILayout.HorizontalScope()) 53 | { 54 | GUILayout.Label("Is Draft:", GUILayout.Width(120)); 55 | isDirty |= CustomToggle.DrawToggle(ref m_draft); 56 | } 57 | 58 | using (new GUILayout.HorizontalScope()) 59 | { 60 | GUILayout.Label("Is Prerelease:", GUILayout.Width(120)); 61 | isDirty |= CustomToggle.DrawToggle(ref m_prerelease); 62 | } 63 | 64 | using (new GUILayout.HorizontalScope()) 65 | { 66 | GUILayout.Label("Zip Contents:", GUILayout.Width(120)); 67 | isDirty |= CustomToggle.DrawToggle(ref m_zipContents); 68 | } 69 | } 70 | } 71 | } -------------------------------------------------------------------------------- /Editor/Services/GithubService/Destinations/GithubNewReleaseDestination.GUI.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 56ea50d7e3e64e6f866621699d0af858 3 | timeCreated: 1745401824 -------------------------------------------------------------------------------- /Editor/Services/GithubService/Destinations/GithubNewReleaseDestination.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e37d975edaa045a489df02a56326c5a8 3 | timeCreated: 1741597042 -------------------------------------------------------------------------------- /Editor/Services/GithubService/GithubAPI.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 8f0144b052ca421aa1569d0ba9db1983 3 | timeCreated: 1741582571 -------------------------------------------------------------------------------- /Editor/Services/GithubService/GithubAPI/Github.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ce7df6b86243462e9aab23c62405ab78 3 | timeCreated: 1741582539 -------------------------------------------------------------------------------- /Editor/Services/GithubService/GithubService.Preferences.cs: -------------------------------------------------------------------------------- 1 | using UnityEditor; 2 | using UnityEngine; 3 | 4 | namespace Wireframe 5 | { 6 | internal partial class GithubService 7 | { 8 | public override void PreferencesGUI() 9 | { 10 | GUILayout.Label("Github", EditorStyles.boldLabel); 11 | using (new EditorGUILayout.VerticalScope("box")) 12 | { 13 | Github.Enabled = GUILayout.Toggle(Github.Enabled, "Enabled"); 14 | using (new EditorGUI.DisabledScope(!Github.Enabled)) 15 | { 16 | Draw(); 17 | } 18 | } 19 | } 20 | 21 | private static void Draw() 22 | { 23 | using (new GUILayout.HorizontalScope()) 24 | { 25 | Github.Token = PasswordField.Draw("Token:", "Secret required to access your Github account", 105, Github.Token, onHelpPressed:TokenHelp); 26 | } 27 | } 28 | 29 | private static void TokenHelp() 30 | { 31 | Application.OpenURL("https://github.com/settings/tokens"); 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /Editor/Services/GithubService/GithubService.Preferences.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b0d0f8af9aa14ac0a99daa206dc4b274 3 | timeCreated: 1741582470 -------------------------------------------------------------------------------- /Editor/Services/GithubService/GithubService.cs: -------------------------------------------------------------------------------- 1 | namespace Wireframe 2 | { 3 | internal partial class GithubService : AService 4 | { 5 | public GithubService() 6 | { 7 | // Needed for reflection 8 | } 9 | 10 | public override bool IsReadyToStartBuild(out string reason) 11 | { 12 | if (!Github.Enabled) 13 | { 14 | reason = "Github is not enabled in Preferences"; 15 | return false; 16 | } 17 | 18 | if (string.IsNullOrEmpty(Github.Token)) 19 | { 20 | reason = "Github Token credentials are not set in Preferences"; 21 | return false; 22 | } 23 | 24 | reason = ""; 25 | return true; 26 | } 27 | 28 | public override void ProjectSettingsGUI() 29 | { 30 | 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /Editor/Services/GithubService/GithubService.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 873930354c1247798af5d2ef69def170 3 | timeCreated: 1741582434 -------------------------------------------------------------------------------- /Editor/Services/SteamworksService.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: dad2166a55fa490f980bbb2d142b800a 3 | timeCreated: 1740302713 -------------------------------------------------------------------------------- /Editor/Services/SteamworksService/Data.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 8c5b77c89af441aab362cc690aed09e7 3 | timeCreated: 1740302835 -------------------------------------------------------------------------------- /Editor/Services/SteamworksService/Data/Steam.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 133af726615ddf2418eb92812469822f 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Editor/Services/SteamworksService/Data/Steam/SteamApp.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using UnityEngine.UI; 4 | 5 | namespace Wireframe 6 | { 7 | [Serializable] 8 | public class SteamApp : DropdownElement 9 | { 10 | public int Id => ID; 11 | public string DisplayName => Name; 12 | 13 | public int ID = 0; 14 | public string Name = "Template"; 15 | public AppVDFFile App = new AppVDFFile(); 16 | public List Depots = new List(); 17 | public List ConfigBranches = new List(); 18 | 19 | // Deprecated in v1.1.3 in favor of ConfigBranches so we can add more fields for a branch 20 | [Obsolete("Use ConfigBranches instead")] 21 | public List Branches = null; 22 | 23 | public SteamApp() 24 | { 25 | ConfigBranches.Add(new SteamBranch(1, "none")); 26 | } 27 | 28 | public SteamApp(SteamApp current) 29 | { 30 | Name = current.Name; 31 | App = new AppVDFFile(current.App); 32 | 33 | Depots = new List(current.Depots); 34 | ConfigBranches = new List(current.ConfigBranches); 35 | } 36 | } 37 | 38 | [Serializable] 39 | public class SteamDepot : DropdownElement 40 | { 41 | public int Id => ID; 42 | public string DisplayName => Name; 43 | 44 | public int ID = 0; 45 | public string Name = "Template"; 46 | public DepotVDFFile Depot = new DepotVDFFile(); 47 | 48 | public SteamDepot() 49 | { 50 | 51 | } 52 | 53 | public SteamDepot(int id, string name) 54 | { 55 | ID = id; 56 | Name = name; 57 | } 58 | 59 | public SteamDepot(SteamDepot currentDepot) 60 | { 61 | Name = currentDepot.Name; 62 | Depot = new DepotVDFFile(currentDepot.Depot); 63 | } 64 | 65 | } 66 | } -------------------------------------------------------------------------------- /Editor/Services/SteamworksService/Data/Steam/SteamApp.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: cd1f0d45b02b06b43a4ae4c05f1ca586 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Services/SteamworksService/Data/Steam/SteamAppData.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Wireframe 5 | { 6 | [Serializable] 7 | public class SteamAppData 8 | { 9 | public List Configs = new List(); 10 | 11 | public List<(SteamApp, List)> ConfigToDepots() 12 | { 13 | var dataConfigToDepotOptionValues = new List<(SteamApp, List)>(); 14 | for (int i = 0; i < Configs.Count; i++) 15 | { 16 | SteamApp config = Configs[i]; 17 | string[] names = new string[config.Depots.Count]; 18 | List values = new List(config.Depots.Count); 19 | 20 | for (var j = 0; j < config.Depots.Count; j++) 21 | { 22 | names[j] = config.Depots[j].Name; 23 | } 24 | 25 | Array.Sort(names); 26 | for (int j = 0; j < names.Length; j++) 27 | { 28 | for (var k = 0; k < config.Depots.Count; k++) 29 | { 30 | string depotName = config.Depots[k].Name; 31 | if (names[j] == depotName) 32 | { 33 | values.Add(config.Depots[k]); 34 | break; 35 | } 36 | } 37 | } 38 | 39 | dataConfigToDepotOptionValues.Add((config, values)); 40 | } 41 | 42 | return dataConfigToDepotOptionValues; 43 | } 44 | 45 | public List<(SteamApp, List)> ConfigToBranches() 46 | { 47 | var dataConfigToDepotOptionValues = new List<(SteamApp, List)>(); 48 | for (int i = 0; i < Configs.Count; i++) 49 | { 50 | SteamApp config = Configs[i]; 51 | dataConfigToDepotOptionValues.Add((config, config.ConfigBranches)); 52 | } 53 | 54 | return dataConfigToDepotOptionValues; 55 | } 56 | } 57 | } -------------------------------------------------------------------------------- /Editor/Services/SteamworksService/Data/Steam/SteamAppData.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c671e84255887dc43bf432d88f37b772 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Services/SteamworksService/Data/Steam/SteamBranch.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Wireframe 4 | { 5 | [Serializable] 6 | public class SteamBranch : DropdownElement 7 | { 8 | public int Id => id; 9 | public string DisplayName => name; 10 | 11 | public int id; 12 | public string name; 13 | 14 | public SteamBranch(string name) 15 | { 16 | this.id = -1; 17 | this.name = name; 18 | } 19 | 20 | public SteamBranch(int id, string name) 21 | { 22 | this.id = id; 23 | this.name = name; 24 | } 25 | 26 | public SteamBranch(SteamBranch branch) 27 | { 28 | id = branch.id; 29 | name = branch.name; 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /Editor/Services/SteamworksService/Data/Steam/SteamBranch.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 44d9b5642abc23e49ba87420086ae86d 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Services/SteamworksService/Data/Steam/SteamPageInfo.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 6f74bfb0123773b448e7fd2c737a9346 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Services/SteamworksService/Data/Steam/SteamSDK.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 68d56933129104c4abb6753c4e1671da 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Services/SteamworksService/Data/SteamUIUtils.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 7b109f3f9ca398f4395a805f14b1f999 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Services/SteamworksService/Modifiers.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2713e333aae94b4389be3ad5291ace73 3 | timeCreated: 1741226038 -------------------------------------------------------------------------------- /Editor/Services/SteamworksService/Modifiers/SteamDRM_BuildModifier.GUI.cs: -------------------------------------------------------------------------------- 1 | using UnityEditor; 2 | using UnityEngine; 3 | 4 | namespace Wireframe 5 | { 6 | public partial class SteamDRM_BuildModifier 7 | { 8 | protected internal override void OnGUIExpanded(ref bool isDirty) 9 | { 10 | using (new GUILayout.HorizontalScope()) 11 | { 12 | if (GUILayout.Button("?", GUILayout.Width(20))) 13 | { 14 | Application.OpenURL("https://partner.steamgames.com/doc/features/drm"); 15 | } 16 | 17 | GUILayout.Label(":", GUILayout.Width(10)); 18 | 19 | SteamUIUtils.ConfigPopup.DrawPopup(ref m_app, GUILayout.Width(130)); 20 | 21 | GUILayout.Label("Flags", GUILayout.Width(40)); 22 | m_flags = EditorGUILayout.IntField(m_flags, GUILayout.Width(40)); 23 | } 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /Editor/Services/SteamworksService/Modifiers/SteamDRM_BuildModifier.GUI.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 90367b32a7e4431bb8fb84539a75b950 3 | timeCreated: 1745571551 -------------------------------------------------------------------------------- /Editor/Services/SteamworksService/Modifiers/SteamDRM_BuildModifier.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace Wireframe 7 | { 8 | [Wiki("Steam DRM", "modifiers", "Prevents your executable from being executed unless run from Steam by sending it to Steamworks.")] 9 | [BuildModifier("Steam DRM")] 10 | public partial class SteamDRM_BuildModifier : ABuildConfigModifer 11 | { 12 | [Wiki("App", "The Steam App ID to use for the build. eg: 1141030")] 13 | private SteamApp m_app; 14 | 15 | [Wiki("Flags", "The flags to use when wrapping the build. default: 0. See https://partner.steamgames.com/doc/features/drm")] 16 | private int m_flags; 17 | 18 | public SteamDRM_BuildModifier() 19 | { 20 | // Required for reflection 21 | m_app = null; 22 | m_flags = 0; 23 | } 24 | 25 | /// 26 | /// https://partner.steamgames.com/doc/features/drm 27 | /// 28 | public SteamDRM_BuildModifier(int appID, int flags = 0) 29 | { 30 | m_app = new SteamApp() 31 | { 32 | App = new AppVDFFile() 33 | { 34 | appid = appID 35 | } 36 | }; 37 | m_flags = flags; 38 | } 39 | 40 | public override bool IsSetup(out string reason) 41 | { 42 | if (!InternalUtils.GetService().IsReadyToStartBuild(out reason)) 43 | { 44 | return false; 45 | } 46 | 47 | if (m_app == null) 48 | { 49 | reason = "No Steam App selected"; 50 | return false; 51 | } 52 | 53 | reason = ""; 54 | return true; 55 | } 56 | 57 | public override async Task ModifyBuildAtPath(string cachedDirectory, BuildConfig buildConfig, 58 | int buildIndex, BuildTaskReport.StepResult stepResult) 59 | { 60 | // Find .exe 61 | string exePath = System.IO.Directory.GetFiles(cachedDirectory, "*.exe", System.IO.SearchOption.TopDirectoryOnly)[0]; 62 | if (string.IsNullOrEmpty(exePath) || !System.IO.File.Exists(exePath)) 63 | { 64 | stepResult.AddError("[Steam] No exe found to DRMWrap in " + cachedDirectory); 65 | stepResult.SetFailed("No exe found to DRMWrap"); 66 | return false; 67 | } 68 | 69 | int processID = ProgressUtils.Start("Steam DRM Modifier", "Wrapping exe with Steam DRM"); 70 | bool result = await SteamSDK.Instance.DRMWrap(m_app.App.appid, exePath, exePath, m_flags, stepResult); 71 | ProgressUtils.Remove(processID); 72 | return result; 73 | } 74 | 75 | public override void TryGetWarnings(ABuildDestination destination, List warnings) 76 | { 77 | if (!(destination is SteamUploadDestination) && !(destination is NoUploadDestination)) 78 | { 79 | warnings.Add("Steam DRM is set but the build is destined for a non-steam location. The build won't be playable!"); 80 | } 81 | } 82 | 83 | public override Dictionary Serialize() 84 | { 85 | return new Dictionary 86 | { 87 | ["flags"] = m_flags, 88 | ["appID"] = m_app?.Id 89 | }; 90 | } 91 | 92 | public override void Deserialize(Dictionary data) 93 | { 94 | m_flags = Convert.ToInt32(data["flags"]); 95 | 96 | if (data.TryGetValue("appID", out object configIDString) && configIDString != null) 97 | { 98 | SteamApp[] buildConfigs = SteamUIUtils.ConfigPopup.Values; 99 | m_app = buildConfigs.FirstOrDefault(a=> a.Id == (long)configIDString); 100 | } 101 | } 102 | } 103 | } -------------------------------------------------------------------------------- /Editor/Services/SteamworksService/Modifiers/SteamDRM_BuildModifier.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 121670dbba3b43869e3ee1ad09beb693 3 | timeCreated: 1741208894 -------------------------------------------------------------------------------- /Editor/Services/SteamworksService/ReorderableListOfBranches.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | namespace Wireframe 4 | { 5 | public class ReorderableListOfBranches : InternalReorderableList 6 | { 7 | protected override void DrawItem(Rect rect, int index, bool isActive, bool isFocused) 8 | { 9 | SteamBranch element = list[index]; 10 | 11 | Rect rect1 = new Rect(rect.x, rect.y, Mathf.Min(100, rect.width / 2), rect.height); 12 | string n = GUI.TextField(rect1, element.name); 13 | if (n != element.name) 14 | { 15 | element.name = n; 16 | dirty = true; 17 | } 18 | } 19 | 20 | protected override SteamBranch CreateItem(int index) 21 | { 22 | return new SteamBranch(index, ""); 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /Editor/Services/SteamworksService/ReorderableListOfBranches.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 70ffea13773f3fc4b895950d0454f6d9 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Services/SteamworksService/ReorderableListOfDepots.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using UnityEditor; 4 | using UnityEditorInternal; 5 | using UnityEngine; 6 | using Wireframe; 7 | 8 | namespace Wireframe 9 | { 10 | public class ReorderableListOfDepots : InternalReorderableList 11 | { 12 | protected override void DrawItem(Rect rect, int index, bool isActive, bool isFocused) 13 | { 14 | SteamDepot element = list[index]; 15 | 16 | Rect rect1 = new Rect(rect.x, rect.y, Mathf.Min(100, rect.width / 2), rect.height); 17 | string n = GUI.TextField(rect1, element.Name); 18 | if (n != element.Name) 19 | { 20 | element.Name = n; 21 | dirty = true; 22 | } 23 | 24 | rect1.x += rect1.width; 25 | string textField = GUI.TextField(rect1, element.Depot.DepotID.ToString()); 26 | if (int.TryParse(textField, out int value) && value != element.Depot.DepotID) 27 | { 28 | element.Depot.DepotID = value; 29 | dirty = true; 30 | } 31 | } 32 | 33 | protected override SteamDepot CreateItem(int index) 34 | { 35 | return new SteamDepot(index, ""); 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /Editor/Services/SteamworksService/ReorderableListOfDepots.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 22622f6afb0e9754da51482d21b118c0 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Services/SteamworksService/SteamUploadDestination.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 27e43dd9892c407385758e278bf0a62d 3 | timeCreated: 1740283695 -------------------------------------------------------------------------------- /Editor/Services/SteamworksService/SteamUploadDestination/Data.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: dd4c24293e5241069e9f5682fec78b1d 3 | timeCreated: 1740295067 -------------------------------------------------------------------------------- /Editor/Services/SteamworksService/SteamUploadDestination/Data/AppVDFFile.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Wireframe 4 | { 5 | [Serializable] 6 | public class AppVDFFile : VDFFile 7 | { 8 | public override string FileName => "appbuild"; 9 | 10 | // Set the app ID that this script will upload. 11 | public int appid; 12 | 13 | // The description for this build. 14 | // The description is only visible to you in the 'Your Builds' section of the App Admin panel. 15 | // This can be changed at any time after uploading a build on the 'Your Builds' page. 16 | public string desc; 17 | 18 | // The following paths can be absolute or relative to location of the script. 19 | 20 | // This directory will be the location for build logs, chunk cache, and intermediate output. 21 | // The cache stored within this causes future SteamPipe uploads to complete quicker by using diffing. 22 | // 23 | // NOTE: for best performance, use a separate disk for your build output. This splits the disk IO workload, letting your content root 24 | // disk handle the read requests and your output disk handle the write requests. 25 | public string buildoutput = "..\\output\\"; 26 | 27 | // The root of the content folder. 28 | public string contentroot = "..\\content\\"; 29 | 30 | // Branch name to automatically set live after successful build, none if empty. 31 | // Note that the 'default' branch can not be set live automatically. That must be done through the App Admin panel. 32 | public string setlive = ""; 33 | 34 | // Enable/Disable whether this a preview build. 35 | // It's highly recommended that you use preview builds while doing the initially setting up SteamPipe to 36 | // ensure that the depot manifest contains the correct files. 37 | public bool preview = false; 38 | 39 | // File path of the local content server if it's enabled. 40 | public string local = ""; 41 | 42 | // The list of depots included in this build. 43 | public DepotList depots = new DepotList(); 44 | 45 | public AppVDFFile() 46 | { 47 | 48 | } 49 | 50 | public AppVDFFile(AppVDFFile currentConfigApp) 51 | { 52 | appid = currentConfigApp.appid; 53 | desc = currentConfigApp.desc; 54 | buildoutput = currentConfigApp.buildoutput; 55 | contentroot = currentConfigApp.contentroot; 56 | setlive = currentConfigApp.setlive; 57 | preview = currentConfigApp.preview; 58 | local = currentConfigApp.local; 59 | depots = new DepotList(currentConfigApp.depots); 60 | } 61 | } 62 | } -------------------------------------------------------------------------------- /Editor/Services/SteamworksService/SteamUploadDestination/Data/AppVDFFile.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a3bdcc56dfbb74548917b08003bf9409 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Services/SteamworksService/SteamUploadDestination/Data/DepotList.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Wireframe 4 | { 5 | [Serializable] 6 | public class DepotList : VdfMap 7 | { 8 | public DepotList() 9 | { 10 | 11 | } 12 | 13 | public DepotList(DepotList depots) 14 | { 15 | foreach (var depot in depots.GetData()) 16 | { 17 | Add(depot.Key, depot.Value); 18 | } 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /Editor/Services/SteamworksService/SteamUploadDestination/Data/DepotList.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: fba8415851ae4df48f21eba9f0407f3e 3 | timeCreated: 1740295096 -------------------------------------------------------------------------------- /Editor/Services/SteamworksService/SteamUploadDestination/Data/DepotVDFFile.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Wireframe 4 | { 5 | [Serializable] 6 | public class DepotFileMapping : VDFFile 7 | { 8 | public override string FileName => "FileMapping"; 9 | 10 | // This can be a full path, or a path relative to ContentRoot 11 | public string LocalPath; 12 | 13 | // This is a path relative to the install folder of your game 14 | public string DepotPath; 15 | 16 | // If LocalPath contains wildcards, setting this means that all 17 | // matching files within subdirectories of LocalPath will also 18 | // be included. 19 | public bool recursive; 20 | 21 | public DepotFileMapping() 22 | { 23 | 24 | } 25 | 26 | public DepotFileMapping(DepotFileMapping fileMapping) 27 | { 28 | LocalPath = fileMapping.LocalPath; 29 | DepotPath = fileMapping.DepotPath; 30 | recursive = fileMapping.recursive; 31 | } 32 | } 33 | 34 | [Serializable] 35 | public class DepotVDFFile : VDFFile 36 | { 37 | public override string FileName => "DepotBuildConfig"; 38 | 39 | // Set your assigned depot ID here 40 | public int DepotID = 999999; 41 | 42 | // include all files recursively 43 | public DepotFileMapping FileMapping = new DepotFileMapping(); 44 | 45 | // but exclude all symbol files 46 | // This can be a full path, or a path relative to ContentRoot 47 | public string FileExclusion; 48 | 49 | public DepotVDFFile() 50 | { 51 | 52 | } 53 | 54 | public DepotVDFFile(DepotVDFFile depot) 55 | { 56 | DepotID = depot.DepotID; 57 | FileMapping = new DepotFileMapping(depot.FileMapping); 58 | FileExclusion = depot.FileExclusion; 59 | } 60 | } 61 | } -------------------------------------------------------------------------------- /Editor/Services/SteamworksService/SteamUploadDestination/Data/DepotVDFFile.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3c3dd515a84912c4984ee12b6f4d456a 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Services/SteamworksService/SteamUploadDestination/Data/IVdfMap.cs: -------------------------------------------------------------------------------- 1 | namespace Wireframe 2 | { 3 | public interface IVdfMap 4 | { 5 | 6 | } 7 | } -------------------------------------------------------------------------------- /Editor/Services/SteamworksService/SteamUploadDestination/Data/IVdfMap.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2aaeb1cf74fd43e78852c47c3f60165e 3 | timeCreated: 1740295089 -------------------------------------------------------------------------------- /Editor/Services/SteamworksService/SteamUploadDestination/Data/VDFFile.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9551dbef572dc6c42baa9223572db418 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Services/SteamworksService/SteamUploadDestination/Data/VdfMap.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Wireframe 5 | { 6 | [Serializable] 7 | public abstract class VdfMap : IVdfMap 8 | { 9 | public class MapData 10 | { 11 | public T Key; 12 | public Y Value; 13 | 14 | public MapData(T key, Y value) 15 | { 16 | Key = key; 17 | Value = value; 18 | } 19 | } 20 | 21 | public int Count 22 | { 23 | get { return Data.Count; } 24 | } 25 | 26 | public List GetData() 27 | { 28 | return Data; 29 | } 30 | 31 | private List Data; 32 | 33 | public VdfMap() 34 | { 35 | Data = new List(); 36 | } 37 | 38 | public void Add(T key, Y value) 39 | { 40 | Data.Add(new MapData(key, value)); 41 | } 42 | 43 | public void RemoveAt(int i) 44 | { 45 | Data.RemoveAt(i); 46 | } 47 | 48 | public T GetKey(int i) 49 | { 50 | return Data[i].Key; 51 | } 52 | 53 | public Y GetValue(int i) 54 | { 55 | return Data[i].Value; 56 | } 57 | 58 | public void Clear() 59 | { 60 | Data.Clear(); 61 | } 62 | } 63 | } -------------------------------------------------------------------------------- /Editor/Services/SteamworksService/SteamUploadDestination/Data/VdfMap.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d6a6b97e197b4f0685f2006fdb0086aa 3 | timeCreated: 1740295084 -------------------------------------------------------------------------------- /Editor/Services/SteamworksService/SteamUploadDestination/SteamGuardTwoFactorWindow.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | using UnityEditor; 4 | using UnityEngine; 5 | 6 | #pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed 7 | 8 | 9 | namespace Wireframe 10 | { 11 | /// 12 | /// Steam has the option to let you authenticate new logins with a code from the app. 13 | /// The user will get a notification on their phone when it occurs and can press to allow the build uploader to work 14 | /// OR they can enter a code manually from the app. 15 | /// 16 | internal class SteamGuardTwoFactorWindow : EditorWindow 17 | { 18 | private Action guardCodeCallback; 19 | private Action confirmationCallback; 20 | private string enteredText; 21 | private bool waitingForCode; 22 | 23 | // [MenuItem("Window/Steam Guard 2 Factor")] 24 | public static void ShowWindow() 25 | { 26 | ShowAsync((S) => { }, (S) => { }); 27 | } 28 | 29 | public static async Task ShowAsync(Action confirmed, Action codeCallback) 30 | { 31 | var window = GetWindow(); 32 | window.titleContent = new GUIContent("Steam Guard Two-Factor", Utils.WindowIcon); 33 | Rect windowPosition = window.position; 34 | windowPosition.size = new Vector2(400, 320); 35 | windowPosition.center = 36 | new Rect(0f, 0f, Screen.currentResolution.width, Screen.currentResolution.height).center; 37 | window.position = windowPosition; 38 | 39 | window.enteredText = ""; 40 | window.waitingForCode = true; 41 | window.guardCodeCallback = codeCallback; 42 | window.confirmationCallback = confirmed; 43 | while (window.waitingForCode) 44 | { 45 | await Task.Delay(100); 46 | } 47 | } 48 | 49 | private void OnEnable() 50 | { 51 | // Reset the entered text - fixes null when loading unity with this popup open 52 | enteredText = ""; 53 | } 54 | 55 | private void OnDisable() 56 | { 57 | if (waitingForCode) 58 | { 59 | confirmationCallback?.Invoke(false); 60 | } 61 | 62 | guardCodeCallback = null; 63 | confirmationCallback = null; 64 | waitingForCode = false; 65 | } 66 | 67 | private void OnGUI() 68 | { 69 | GUILayout.Label("Looks like you have Two-Factor verification enabled!\n" + 70 | "Open the Steam app on your device and do one of the following."); 71 | 72 | GUILayout.Space(10); 73 | 74 | // bold style 75 | var boldStyle = new GUIStyle(GUI.skin.label) { fontStyle = FontStyle.Bold }; 76 | GUILayout.Label("NOTE: Two-Factor authentication does not save.\n" + 77 | "So you will need to do this every time you upload a build.\n" + 78 | "I am sorry :(", boldStyle); 79 | 80 | GUILayout.Space(20); 81 | 82 | GUILayout.Label("1. Enter the Steam Guard Code"); 83 | using (new EditorGUILayout.HorizontalScope()) 84 | { 85 | // Draw TextField with large text to emphasise the steam guard 86 | var largeText = new GUIStyle(GUI.skin.textField) { fontSize = 40 }; 87 | enteredText = GUILayout.TextField(enteredText, largeText).ToUpper(); 88 | using (new EditorGUI.DisabledScope(enteredText.Length < 1)) 89 | { 90 | if (GUILayout.Button("Use Code", GUILayout.Width(100), GUILayout.Height(50))) 91 | { 92 | guardCodeCallback?.Invoke(enteredText); 93 | waitingForCode = false; 94 | Close(); 95 | } 96 | } 97 | } 98 | 99 | GUILayout.FlexibleSpace(); 100 | 101 | GUILayout.Label("2. Accept the request that appears on your phone.\n" + 102 | "Then click the button below."); 103 | GUILayout.Label("NOTE: If this does not work then try the Guard Code above."); 104 | if (GUILayout.Button("Confirmed!", GUILayout.Height(50))) 105 | { 106 | confirmationCallback?.Invoke(true); 107 | waitingForCode = false; 108 | Close(); 109 | } 110 | } 111 | } 112 | } -------------------------------------------------------------------------------- /Editor/Services/SteamworksService/SteamUploadDestination/SteamGuardTwoFactorWindow.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9d9b7648701aff6488c03c2072c73594 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Services/SteamworksService/SteamUploadDestination/SteamGuardWindow.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | using UnityEditor; 4 | using UnityEngine; 5 | 6 | #pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed 7 | 8 | 9 | namespace Wireframe 10 | { 11 | /// 12 | /// SteamGuard has an option to email/text you a verification code for new logins. 13 | /// 14 | internal class SteamGuardWindow : EditorWindow 15 | { 16 | private Action guardCodeCallback; 17 | private string enteredText; 18 | private bool waitingForCode; 19 | 20 | // [MenuItem("Window/Steam Guard")] 21 | public static void ShowWindow() 22 | { 23 | ShowAsync((S) => { }); 24 | } 25 | 26 | 27 | public static async Task ShowAsync(Action codeCallback) 28 | { 29 | var window = GetWindow(); 30 | window.titleContent = new GUIContent("Steam Guard Verification", Utils.WindowIcon); 31 | Rect windowPosition = window.position; 32 | windowPosition.size = new Vector2(300, 200); 33 | windowPosition.center = 34 | new Rect(0f, 0f, Screen.currentResolution.width, Screen.currentResolution.height).center; 35 | window.position = windowPosition; 36 | 37 | window.enteredText = ""; 38 | window.guardCodeCallback = codeCallback; 39 | window.waitingForCode = true; 40 | while (window.waitingForCode) 41 | { 42 | await Task.Delay(100); 43 | } 44 | } 45 | 46 | private void OnEnable() 47 | { 48 | // Reset the entered text - fixes null when loading unity with this popup open 49 | enteredText = ""; 50 | } 51 | 52 | private void OnDisable() 53 | { 54 | if (waitingForCode) 55 | { 56 | guardCodeCallback?.Invoke(null); 57 | } 58 | 59 | guardCodeCallback = null; 60 | waitingForCode = false; 61 | } 62 | 63 | private void OnGUI() 64 | { 65 | GUILayout.Label("Looks like you need to verify Steam Guard!\n" + 66 | "Enter the Steam Guard code below to continue."); 67 | 68 | 69 | // Draw TextField with large text to emphasise the steam guard 70 | var largeText = new GUIStyle(GUI.skin.textField) { fontSize = 40 }; 71 | enteredText = GUILayout.TextField(enteredText, largeText).ToUpper(); 72 | 73 | GUILayout.FlexibleSpace(); 74 | 75 | using (new EditorGUI.DisabledScope(enteredText.Length < 1)) 76 | { 77 | if (GUILayout.Button("Retry login", GUILayout.Height(50))) 78 | { 79 | guardCodeCallback?.Invoke(enteredText.Trim()); 80 | waitingForCode = false; 81 | Close(); 82 | } 83 | } 84 | } 85 | } 86 | } -------------------------------------------------------------------------------- /Editor/Services/SteamworksService/SteamUploadDestination/SteamGuardWindow.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 7d69b4def28b9104198a28125dd6a7e1 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Services/SteamworksService/SteamUploadDestination/SteamUploadDestination.GUI.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | namespace Wireframe 4 | { 5 | public partial class SteamUploadDestination 6 | { 7 | protected internal override void OnGUIExpanded(ref bool isDirty) 8 | { 9 | // Config 10 | using (new GUILayout.HorizontalScope()) 11 | { 12 | GUILayout.Label("App:", GUILayout.Width(120)); 13 | isDirty |= SteamUIUtils.ConfigPopup.DrawPopup(ref m_current); 14 | } 15 | 16 | // Depot 17 | using (new GUILayout.HorizontalScope()) 18 | { 19 | GUILayout.Label("Depot:", GUILayout.Width(120)); 20 | isDirty |= SteamUIUtils.DepotPopup.DrawPopup(m_current, ref m_depot); 21 | } 22 | 23 | // Branch 24 | using (new GUILayout.HorizontalScope()) 25 | { 26 | GUILayout.Label("Branch:", GUILayout.Width(120)); 27 | isDirty |= SteamUIUtils.BranchPopup.DrawPopup(m_current, ref m_destinationBranch); 28 | } 29 | 30 | // Tools 31 | using (new GUILayout.HorizontalScope()) 32 | { 33 | GUILayout.Label("Create AppFile:", GUILayout.Width(120)); 34 | isDirty |= CustomToggle.DrawToggle(ref m_createAppFile); 35 | } 36 | 37 | using (new GUILayout.HorizontalScope()) 38 | { 39 | GUILayout.Label("Create DepotFile:", GUILayout.Width(120)); 40 | bool drawToggle = CustomToggle.DrawToggle(ref m_createDepotFile); 41 | isDirty |= drawToggle; 42 | } 43 | 44 | using (new GUILayout.HorizontalScope()) 45 | { 46 | GUILayout.Label("Upload To Steam:", GUILayout.Width(120)); 47 | isDirty |= CustomToggle.DrawToggle(ref m_uploadToSteam); 48 | } 49 | } 50 | 51 | protected internal override void OnGUICollapsed(ref bool isDirty, float maxWidth) 52 | { 53 | isDirty |= SteamUIUtils.ConfigPopup.DrawPopup(ref m_current); 54 | isDirty |= SteamUIUtils.DepotPopup.DrawPopup(m_current, ref m_depot); 55 | isDirty |= SteamUIUtils.BranchPopup.DrawPopup(m_current, ref m_destinationBranch); 56 | } 57 | } 58 | } -------------------------------------------------------------------------------- /Editor/Services/SteamworksService/SteamUploadDestination/SteamUploadDestination.GUI.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3e8995c620cb4afcbf927e007ef2402b 3 | timeCreated: 1745401792 -------------------------------------------------------------------------------- /Editor/Services/SteamworksService/SteamUploadDestination/SteamUploadDestination.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a51c346b8674b7340b94fd0eaa9b3ccb 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Services/SteamworksService/SteamworksService.cs: -------------------------------------------------------------------------------- 1 | using UnityEditor; 2 | using UnityEngine; 3 | 4 | namespace Wireframe 5 | { 6 | /// 7 | /// Used by reflection 8 | /// 9 | internal partial class SteamworksService : AService 10 | { 11 | private static string steamPasswordConfirmation; 12 | private static bool steamPasswordConfirmed = string.IsNullOrEmpty(SteamSDK.UserPassword); 13 | 14 | public SteamworksService() 15 | { 16 | // Needed for reflection 17 | } 18 | 19 | public override bool IsReadyToStartBuild(out string reason) 20 | { 21 | if (!SteamSDK.Enabled) 22 | { 23 | reason = "Steam SDK is not enabled in Preferences"; 24 | return false; 25 | } 26 | 27 | 28 | if (!SteamSDK.Instance.IsInitialized) 29 | { 30 | reason = "Steam SDK is not initialized"; 31 | return false; 32 | } 33 | 34 | if (string.IsNullOrEmpty(SteamSDK.UserName) || 35 | string.IsNullOrEmpty(SteamSDK.UserPassword)) 36 | { 37 | reason = "Steam SDK credentials are not set in Preferences"; 38 | return false; 39 | } 40 | 41 | reason = ""; 42 | return true; 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /Editor/Services/SteamworksService/SteamworksService.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ad7a661beeea1c34599a3f7eaa26ef13 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Services/SteamworksService/SteamworksService_Preferences.cs: -------------------------------------------------------------------------------- 1 | using UnityEditor; 2 | using UnityEngine; 3 | 4 | namespace Wireframe 5 | { 6 | internal partial class SteamworksService 7 | { 8 | public override void PreferencesGUI() 9 | { 10 | GUILayout.Label("Steamworks", EditorStyles.boldLabel); 11 | using (new EditorGUILayout.VerticalScope("box")) 12 | { 13 | SteamSDK.Enabled = GUILayout.Toggle(SteamSDK.Enabled, "Enabled"); 14 | using (new EditorGUI.DisabledScope(!SteamSDK.Enabled)) 15 | { 16 | DrawSteamworks(); 17 | } 18 | } 19 | } 20 | 21 | private static void DrawSteamworks() 22 | { 23 | using (new EditorGUILayout.HorizontalScope()) 24 | { 25 | Color temp = GUI.color; 26 | GUI.color = SteamSDK.Instance.IsInitialized ? Color.green : Color.red; 27 | GUILayout.Label(new GUIContent("SteamSDK Path:", 28 | "The path to the SteamSDK folder. Build Uploader uses this to upload builds to Steamworks."), 29 | GUILayout.Width(105)); 30 | GUI.color = temp; 31 | 32 | 33 | if (!SteamSDK.Instance.IsInitialized) 34 | { 35 | if (GUILayout.Button("?", GUILayout.Width(20))) 36 | { 37 | Application.OpenURL("https://partner.steamgames.com/doc/sdk"); 38 | } 39 | } 40 | 41 | string newPath = GUILayout.TextField(SteamSDK.SteamSDKPath); 42 | 43 | if (GUILayout.Button("...", GUILayout.Width(50))) 44 | { 45 | newPath = EditorUtility.OpenFolderPanel("SteamSDK Folder", ".", ""); 46 | } 47 | 48 | if (GUILayout.Button("Show", GUILayout.Width(50))) 49 | { 50 | EditorUtility.RevealInFinder(SteamSDK.SteamSDKPath); 51 | } 52 | 53 | if (GUILayout.Button("CMD", GUILayout.Width(50))) 54 | { 55 | SteamSDK.Instance.ShowConsole(); 56 | } 57 | 58 | if (newPath != SteamSDK.SteamSDKPath && !string.IsNullOrEmpty(newPath)) 59 | { 60 | SteamSDK.SteamSDKPath = newPath; 61 | SteamSDK.Instance.Initialize(); 62 | } 63 | } 64 | 65 | 66 | if (steamPasswordConfirmed) 67 | { 68 | // Steam username 69 | using (new GUILayout.HorizontalScope()) 70 | { 71 | SteamSDK.UserName = PasswordField.Draw("Steam Username:", "Your Steamworks username used to login", 105, SteamSDK.UserName); 72 | } 73 | 74 | // Steam password 75 | using (new GUILayout.HorizontalScope()) 76 | { 77 | SteamSDK.UserPassword = PasswordField.Draw("Steam Password:", "Your Steamworks password used to login", 105, SteamSDK.UserPassword); 78 | } 79 | } 80 | else 81 | { 82 | steamPasswordConfirmation = PasswordField.Draw("Verify Password:", "Verify your Steamworks password", 105, steamPasswordConfirmation); 83 | if (steamPasswordConfirmation == SteamSDK.UserPassword) 84 | { 85 | steamPasswordConfirmed = true; 86 | } 87 | } 88 | 89 | if (GUILayout.Button("Reset login details")) 90 | { 91 | if (EditorUtility.DisplayDialog("Reset Steam Login Preferences", 92 | "Are you sure you want to reset your Steam login details?", "Yes", "No")) 93 | { 94 | SteamSDK.UserName = ""; 95 | SteamSDK.UserPassword = ""; 96 | steamPasswordConfirmation = ""; 97 | steamPasswordConfirmed = true; // confirmation password matches 98 | } 99 | } 100 | } 101 | } 102 | } -------------------------------------------------------------------------------- /Editor/Services/SteamworksService/SteamworksService_Preferences.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a37a5fea7e2c4c3dbf2ac615f88db871 3 | timeCreated: 1740304677 -------------------------------------------------------------------------------- /Editor/Services/SteamworksService/SteamworksService_ProjectSettings.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 6ff5f7a1885649e3a7e9a1ba510b5398 3 | timeCreated: 1740304732 -------------------------------------------------------------------------------- /Editor/Services/UnityCloudService.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: cb52605eb83f477faa0df046983265eb 3 | timeCreated: 1740302734 -------------------------------------------------------------------------------- /Editor/Services/UnityCloudService/UnityCloudAPI.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 744d6758283d5334096190a547b64a32 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Editor/Services/UnityCloudService/UnityCloudAPI/UnityCloud.cs: -------------------------------------------------------------------------------- 1 | using UnityEditor; 2 | using UnityEngine; 3 | 4 | namespace Wireframe 5 | { 6 | internal class UnityCloud 7 | { 8 | public static UnityCloud Instance 9 | { 10 | get 11 | { 12 | if (m_instance == null) 13 | { 14 | m_instance = new UnityCloud(); 15 | } 16 | 17 | return m_instance; 18 | } 19 | } 20 | 21 | private static UnityCloud m_instance; 22 | 23 | static UnityCloud() 24 | { 25 | // Migrate everything over to encoded values 26 | EncodedEditorPrefs.MigrateKeyToEncoded("unityCloud_organization", OrganizationKey); 27 | EncodedEditorPrefs.MigrateKeyToEncoded("unityCloud_project", ProjectKey); 28 | EncodedEditorPrefs.MigrateKeyToEncoded("unityCloud_secret", SecretKey); 29 | } 30 | 31 | public static bool Enabled 32 | { 33 | get => EditorPrefs.GetBool("unityCloud_enabled", false); 34 | set => EditorPrefs.SetBool("unityCloud_enabled", value); 35 | } 36 | 37 | private static string OrganizationKey => Application.productName + "UnityCloudOBuildUploader"; 38 | public string Organization 39 | { 40 | get => EncodedEditorPrefs.GetString(OrganizationKey, ""); 41 | set => EncodedEditorPrefs.SetString(OrganizationKey, value); 42 | } 43 | 44 | private static string ProjectKey => Application.productName + "UnityCloudPBuildUploader"; 45 | public string Project 46 | { 47 | get => EncodedEditorPrefs.GetString(ProjectKey, ""); 48 | set => EncodedEditorPrefs.SetString(ProjectKey, value); 49 | } 50 | 51 | private static string SecretKey => Application.productName + "UnityCloudSBuildUploader"; 52 | public string Secret 53 | { 54 | get => EncodedEditorPrefs.GetString(SecretKey, ""); 55 | set => EncodedEditorPrefs.SetString(SecretKey, value); 56 | } 57 | 58 | public bool IsInitialized() 59 | { 60 | return !string.IsNullOrEmpty(Organization) && !string.IsNullOrEmpty(Project) && 61 | !string.IsNullOrEmpty(Secret); 62 | } 63 | } 64 | } -------------------------------------------------------------------------------- /Editor/Services/UnityCloudService/UnityCloudAPI/UnityCloud.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f224fc5d5a4d45c498f7af6622bded90 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Services/UnityCloudService/UnityCloudAPI/UnityCloudAPI.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: db29425c7685bc74197271f06f443a39 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Services/UnityCloudService/UnityCloudAPI/UnityCloudAPIEditorUtil.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Wireframe 4 | { 5 | internal static class UnityCloudAPIEditorUtil 6 | { 7 | public class UnityCloudTargetPopup : CustomDropdown 8 | { 9 | protected override List FetchAllData() 10 | { 11 | return UnityCloudAPI.CloudBuildTargets; 12 | } 13 | } 14 | 15 | public class UnityCloudBuildPopup : CustomMultiDropdown 16 | { 17 | public override List<(UnityCloudTarget, List)> GetAllData() 18 | { 19 | return UnityCloudAPI.CurrentBuilds; 20 | } 21 | 22 | public override bool IsItemValid(UnityCloudBuild y) 23 | { 24 | return y.IsSuccessful; 25 | } 26 | 27 | public override int SortByName(UnityCloudBuild a, UnityCloudBuild b) 28 | { 29 | return b.build.CompareTo(a.build); 30 | } 31 | } 32 | 33 | public static UnityCloudTargetPopup TargetPopup => m_targetPopup ?? (m_targetPopup = new UnityCloudTargetPopup()); 34 | 35 | private static UnityCloudTargetPopup m_targetPopup; 36 | 37 | public static UnityCloudBuildPopup BuildPopup => m_buildPopup ?? (m_buildPopup = new UnityCloudBuildPopup()); 38 | private static UnityCloudBuildPopup m_buildPopup; 39 | 40 | } 41 | } -------------------------------------------------------------------------------- /Editor/Services/UnityCloudService/UnityCloudAPI/UnityCloudAPIEditorUtil.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d6c4a80583bf34846bc6d0f14755d020 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Services/UnityCloudService/UnityCloudAPI/UnityCloudBuild.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: de619431dc727074ca39a58919bdc450 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Services/UnityCloudService/UnityCloudAPI/UnityCloudTarget.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Wireframe 5 | { 6 | public enum Platform 7 | { 8 | Windows, 9 | Mac, 10 | } 11 | 12 | internal static class UnityCloudConfigExtensions 13 | { 14 | public static string ToPlatformString(this Platform p) 15 | { 16 | switch (p) 17 | { 18 | case Platform.Windows: 19 | return "standalonewindows64"; 20 | case Platform.Mac: 21 | return "standaloneosxuniversal"; 22 | default: 23 | throw new ArgumentOutOfRangeException(nameof(p), p, null); 24 | } 25 | } 26 | 27 | public static Platform ToPlatformEnum(this string p) 28 | { 29 | switch (p) 30 | { 31 | case "standalonewindows64": 32 | return Platform.Windows; 33 | case "standaloneosx": 34 | case "standaloneosxuniversal": 35 | return Platform.Mac; 36 | default: 37 | throw new ArgumentOutOfRangeException(nameof(p), p, null); 38 | } 39 | } 40 | } 41 | 42 | [Serializable] 43 | public class UnityCloudTarget : DropdownElement 44 | { 45 | [Serializable] 46 | public class LastBuilt 47 | { 48 | public string unityVersion; 49 | } 50 | 51 | public int Id => ID; 52 | public string DisplayName => name; 53 | 54 | public int ID; 55 | public string name; 56 | public string platform; 57 | public string buildtargetid; 58 | public bool enabled; 59 | public LastBuilt lastBuilt; 60 | public Dictionary links; 61 | } 62 | } -------------------------------------------------------------------------------- /Editor/Services/UnityCloudService/UnityCloudAPI/UnityCloudTarget.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f60ad087acd01734081cbf7fe9f181ae 3 | timeCreated: 1626425399 -------------------------------------------------------------------------------- /Editor/Services/UnityCloudService/UnityCloudBuildUI.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 891b15f44b8a2554cb665cc648334cdb 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Services/UnityCloudService/UnityCloudService.Preferences.cs: -------------------------------------------------------------------------------- 1 | using UnityEditor; 2 | using UnityEngine; 3 | 4 | namespace Wireframe 5 | { 6 | internal partial class UnityCloudService 7 | { 8 | public override void PreferencesGUI() 9 | { 10 | GUILayout.Label("Unity Cloud", EditorStyles.boldLabel); 11 | using (new EditorGUILayout.VerticalScope("box")) 12 | { 13 | UnityCloud.Enabled = GUILayout.Toggle(UnityCloud.Enabled, "Enabled"); 14 | using (new EditorGUI.DisabledScope(!UnityCloud.Enabled)) 15 | { 16 | DrawUnityCloud(); 17 | } 18 | } 19 | } 20 | 21 | private static void DrawUnityCloud() 22 | { 23 | using (new GUILayout.HorizontalScope()) 24 | { 25 | UnityCloud.Instance.Organization = PasswordField.Draw( 26 | "Organization:", 27 | "The organization/account that owns the project", 28 | 105, 29 | UnityCloud.Instance.Organization); 30 | } 31 | 32 | using (new GUILayout.HorizontalScope()) 33 | { 34 | UnityCloud.Instance.Project = PasswordField.Draw( 35 | "Project ID:", 36 | "The project ID owned by the organization. eg: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", 37 | 105, 38 | UnityCloud.Instance.Project); 39 | } 40 | 41 | using (new GUILayout.HorizontalScope()) 42 | { 43 | UnityCloud.Instance.Secret = PasswordField.Draw( 44 | "Dev Ops API Key:", 45 | "The secret key used to access Unity Cloud via the API", 46 | 105, 47 | UnityCloud.Instance.Secret); 48 | } 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /Editor/Services/UnityCloudService/UnityCloudService.Preferences.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 503376b91f69412b82f3fae37767e549 3 | timeCreated: 1740306655 -------------------------------------------------------------------------------- /Editor/Services/UnityCloudService/UnityCloudService.cs: -------------------------------------------------------------------------------- 1 | namespace Wireframe 2 | { 3 | /// 4 | /// Used by reflection 5 | /// 6 | internal partial class UnityCloudService : AService 7 | { 8 | internal override WindowTab WindowTabType => new UnityCloudWindowTab(); 9 | 10 | public UnityCloudService() 11 | { 12 | // Needed for reflection 13 | } 14 | 15 | public override bool IsReadyToStartBuild(out string reason) 16 | { 17 | if (!UnityCloud.Enabled) 18 | { 19 | reason = "Unity Cloud is not enabled in Preferences"; 20 | return false; 21 | } 22 | 23 | if (string.IsNullOrEmpty(UnityCloud.Instance.Organization)) 24 | { 25 | reason = "Organization is not set in Preferences"; 26 | return false; 27 | } 28 | 29 | if (string.IsNullOrEmpty(UnityCloud.Instance.Project)) 30 | { 31 | reason = "Project is not set in Preferences"; 32 | return false; 33 | } 34 | 35 | if (string.IsNullOrEmpty(UnityCloud.Instance.Secret)) 36 | { 37 | reason = "Secret is not set in Preferences"; 38 | return false; 39 | } 40 | 41 | 42 | reason = ""; 43 | return true; 44 | } 45 | 46 | public override void ProjectSettingsGUI() 47 | { 48 | // None 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /Editor/Services/UnityCloudService/UnityCloudService.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a0e6308fd1826f549bd8fbdad2c9efb9 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Services/UnityCloudService/UnityCloudSource.GUI.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using UnityEditor; 3 | using UnityEngine; 4 | 5 | namespace Wireframe 6 | { 7 | public partial class UnityCloudSource 8 | { 9 | public override void OnGUIExpanded(ref bool isDirty) 10 | { 11 | using (new EditorGUILayout.HorizontalScope()) 12 | { 13 | GUILayout.Label("Target:", GUILayout.Width(120)); 14 | isDirty |= UnityCloudAPIEditorUtil.TargetPopup.DrawPopup(ref sourceTarget); 15 | } 16 | 17 | using (new EditorGUILayout.HorizontalScope()) 18 | { 19 | GUILayout.Label("Build:", GUILayout.Width(120)); 20 | using (new EditorGUI.DisabledScope(UnityCloudAPI.IsSyncing)) 21 | { 22 | if (GUILayout.Button("Refresh", GUILayout.Width(75))) 23 | { 24 | UnityCloudAPI.SyncBuilds(); 25 | //UnityCloudAPIEditorUtil.TargetPopup.Refresh(); 26 | isDirty = true;; 27 | } 28 | } 29 | 30 | buildScrollPosition = EditorGUILayout.BeginScrollView(buildScrollPosition, GUILayout.MaxHeight(100)); 31 | using (new EditorGUILayout.VerticalScope()) 32 | { 33 | List builds = UnityCloudAPI.GetBuildsForTarget(sourceTarget); 34 | if (builds != null) 35 | { 36 | for (int i = 0; i < builds.Count; i++) 37 | { 38 | UnityCloudBuild build = builds[i]; 39 | bool isSelected = sourceBuild != null && 40 | sourceBuild.CreateBuildName() == build.CreateBuildName(); 41 | using (new EditorGUI.DisabledScope(isSelected || UnityCloudAPI.IsSyncing)) 42 | { 43 | using (new EditorGUILayout.HorizontalScope()) 44 | { 45 | if (GUILayout.Button(build.CreateBuildName())) 46 | { 47 | sourceBuild = build; 48 | isDirty = true; 49 | } 50 | } 51 | } 52 | } 53 | } 54 | } 55 | 56 | EditorGUILayout.EndScrollView(); 57 | } 58 | } 59 | 60 | public override void OnGUICollapsed(ref bool isDirty, float maxWidth) 61 | { 62 | if (UnityCloudAPIEditorUtil.TargetPopup.DrawPopup(ref sourceTarget)) 63 | { 64 | isDirty = true; 65 | } 66 | 67 | if (UnityCloudAPIEditorUtil.BuildPopup.DrawPopup(sourceTarget, ref sourceBuild)) 68 | { 69 | isDirty = true; 70 | } 71 | } 72 | } 73 | } -------------------------------------------------------------------------------- /Editor/Services/UnityCloudService/UnityCloudSource.GUI.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 688e08bd709e4ccf9b5dcbb467bb6901 3 | timeCreated: 1745561972 -------------------------------------------------------------------------------- /Editor/Services/UnityCloudService/UnityCloudSource.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 68f8fd5962dfdb44eb2d2f93b98e3621 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Services/UnityCloudService/UnityCloudWindowTab.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2cbf43c8b8035fa47ac679f20628f7fa 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/veugeljame.builduploader.editor.asmdef: -------------------------------------------------------------------------------- 1 | { 2 | "name": "VeugelJame.BuildUploader.Editor", 3 | "rootNamespace": "", 4 | "references": [], 5 | "includePlatforms": [ 6 | "Editor" 7 | ], 8 | "excludePlatforms": [], 9 | "allowUnsafeCode": false, 10 | "overrideReferences": false, 11 | "precompiledReferences": [], 12 | "autoReferenced": true, 13 | "defineConstraints": [ 14 | "UNITY_EDITOR" 15 | ], 16 | "versionDefines": [], 17 | "noEngineReferences": false 18 | } -------------------------------------------------------------------------------- /Editor/veugeljame.builduploader.editor.asmdef.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e02a14ac71925b840aa054b2af0d6d18 3 | AssemblyDefinitionImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JamesVeug/UnitySteamBuildUploader/2e6df95625a9ad1f0fe70a93a6b1287d71c1c778/Icon.png -------------------------------------------------------------------------------- /Icon.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ccfa435ba2be13c4ba66674f1f3326d6 3 | TextureImporter: 4 | internalIDToNameTable: [] 5 | externalObjects: {} 6 | serializedVersion: 12 7 | mipmaps: 8 | mipMapMode: 0 9 | enableMipMap: 1 10 | sRGBTexture: 1 11 | linearTexture: 0 12 | fadeOut: 0 13 | borderMipMap: 0 14 | mipMapsPreserveCoverage: 0 15 | alphaTestReferenceValue: 0.5 16 | mipMapFadeDistanceStart: 1 17 | mipMapFadeDistanceEnd: 3 18 | bumpmap: 19 | convertToNormalMap: 0 20 | externalNormalMap: 0 21 | heightScale: 0.25 22 | normalMapFilter: 0 23 | flipGreenChannel: 0 24 | isReadable: 0 25 | streamingMipmaps: 0 26 | streamingMipmapsPriority: 0 27 | vTOnly: 0 28 | ignoreMipmapLimit: 0 29 | grayScaleToAlpha: 0 30 | generateCubemap: 6 31 | cubemapConvolution: 0 32 | seamlessCubemap: 0 33 | textureFormat: 1 34 | maxTextureSize: 2048 35 | textureSettings: 36 | serializedVersion: 2 37 | filterMode: 1 38 | aniso: 1 39 | mipBias: 0 40 | wrapU: 0 41 | wrapV: 0 42 | wrapW: 0 43 | nPOTScale: 1 44 | lightmap: 0 45 | compressionQuality: 50 46 | spriteMode: 0 47 | spriteExtrude: 1 48 | spriteMeshType: 1 49 | alignment: 0 50 | spritePivot: {x: 0.5, y: 0.5} 51 | spritePixelsToUnits: 100 52 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 53 | spriteGenerateFallbackPhysicsShape: 1 54 | alphaUsage: 1 55 | alphaIsTransparency: 0 56 | spriteTessellationDetail: -1 57 | textureType: 0 58 | textureShape: 1 59 | singleChannelComponent: 0 60 | flipbookRows: 1 61 | flipbookColumns: 1 62 | maxTextureSizeSet: 0 63 | compressionQualitySet: 0 64 | textureFormatSet: 0 65 | ignorePngGamma: 0 66 | applyGammaDecoding: 0 67 | swizzle: 50462976 68 | cookieLightType: 0 69 | platformSettings: 70 | - serializedVersion: 3 71 | buildTarget: DefaultTexturePlatform 72 | maxTextureSize: 2048 73 | resizeAlgorithm: 0 74 | textureFormat: -1 75 | textureCompression: 1 76 | compressionQuality: 50 77 | crunchedCompression: 0 78 | allowsAlphaSplitting: 0 79 | overridden: 0 80 | ignorePlatformSupport: 0 81 | androidETC2FallbackOverride: 0 82 | forceMaximumCompressionQuality_BC6H_BC7: 0 83 | - serializedVersion: 3 84 | buildTarget: Standalone 85 | maxTextureSize: 2048 86 | resizeAlgorithm: 0 87 | textureFormat: -1 88 | textureCompression: 1 89 | compressionQuality: 50 90 | crunchedCompression: 0 91 | allowsAlphaSplitting: 0 92 | overridden: 0 93 | ignorePlatformSupport: 0 94 | androidETC2FallbackOverride: 0 95 | forceMaximumCompressionQuality_BC6H_BC7: 0 96 | - serializedVersion: 3 97 | buildTarget: Windows Store Apps 98 | maxTextureSize: 2048 99 | resizeAlgorithm: 0 100 | textureFormat: -1 101 | textureCompression: 1 102 | compressionQuality: 50 103 | crunchedCompression: 0 104 | allowsAlphaSplitting: 0 105 | overridden: 0 106 | ignorePlatformSupport: 0 107 | androidETC2FallbackOverride: 0 108 | forceMaximumCompressionQuality_BC6H_BC7: 0 109 | - serializedVersion: 3 110 | buildTarget: Server 111 | maxTextureSize: 2048 112 | resizeAlgorithm: 0 113 | textureFormat: -1 114 | textureCompression: 1 115 | compressionQuality: 50 116 | crunchedCompression: 0 117 | allowsAlphaSplitting: 0 118 | overridden: 0 119 | ignorePlatformSupport: 0 120 | androidETC2FallbackOverride: 0 121 | forceMaximumCompressionQuality_BC6H_BC7: 0 122 | spriteSheet: 123 | serializedVersion: 2 124 | sprites: [] 125 | outline: [] 126 | physicsShape: [] 127 | bones: [] 128 | spriteID: 129 | internalID: 0 130 | vertices: [] 131 | indices: 132 | edges: [] 133 | weights: [] 134 | secondaryTextures: [] 135 | nameFileIdTable: {} 136 | mipmapLimitGroupName: 137 | pSDRemoveMatte: 0 138 | userData: 139 | assetBundleName: 140 | assetBundleVariant: 141 | -------------------------------------------------------------------------------- /LICENSE.md.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: bd19526a38afbeb4bad252577d06fc73 3 | TextScriptImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /LargeIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JamesVeug/UnitySteamBuildUploader/2e6df95625a9ad1f0fe70a93a6b1287d71c1c778/LargeIcon.png -------------------------------------------------------------------------------- /LargeIcon.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 12eadd5a94b47cc48a6b2c42be460afc 3 | TextureImporter: 4 | internalIDToNameTable: [] 5 | externalObjects: {} 6 | serializedVersion: 12 7 | mipmaps: 8 | mipMapMode: 0 9 | enableMipMap: 0 10 | sRGBTexture: 1 11 | linearTexture: 0 12 | fadeOut: 0 13 | borderMipMap: 0 14 | mipMapsPreserveCoverage: 0 15 | alphaTestReferenceValue: 0.5 16 | mipMapFadeDistanceStart: 1 17 | mipMapFadeDistanceEnd: 3 18 | bumpmap: 19 | convertToNormalMap: 0 20 | externalNormalMap: 0 21 | heightScale: 0.25 22 | normalMapFilter: 0 23 | flipGreenChannel: 0 24 | isReadable: 0 25 | streamingMipmaps: 0 26 | streamingMipmapsPriority: 0 27 | vTOnly: 0 28 | ignoreMipmapLimit: 0 29 | grayScaleToAlpha: 0 30 | generateCubemap: 6 31 | cubemapConvolution: 0 32 | seamlessCubemap: 0 33 | textureFormat: 1 34 | maxTextureSize: 2048 35 | textureSettings: 36 | serializedVersion: 2 37 | filterMode: 1 38 | aniso: 1 39 | mipBias: 0 40 | wrapU: 1 41 | wrapV: 1 42 | wrapW: 1 43 | nPOTScale: 0 44 | lightmap: 0 45 | compressionQuality: 50 46 | spriteMode: 1 47 | spriteExtrude: 1 48 | spriteMeshType: 1 49 | alignment: 0 50 | spritePivot: {x: 0.5, y: 0.5} 51 | spritePixelsToUnits: 100 52 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 53 | spriteGenerateFallbackPhysicsShape: 1 54 | alphaUsage: 1 55 | alphaIsTransparency: 1 56 | spriteTessellationDetail: -1 57 | textureType: 8 58 | textureShape: 1 59 | singleChannelComponent: 0 60 | flipbookRows: 1 61 | flipbookColumns: 1 62 | maxTextureSizeSet: 0 63 | compressionQualitySet: 0 64 | textureFormatSet: 0 65 | ignorePngGamma: 0 66 | applyGammaDecoding: 0 67 | swizzle: 50462976 68 | cookieLightType: 0 69 | platformSettings: 70 | - serializedVersion: 3 71 | buildTarget: DefaultTexturePlatform 72 | maxTextureSize: 2048 73 | resizeAlgorithm: 0 74 | textureFormat: -1 75 | textureCompression: 1 76 | compressionQuality: 50 77 | crunchedCompression: 0 78 | allowsAlphaSplitting: 0 79 | overridden: 0 80 | ignorePlatformSupport: 0 81 | androidETC2FallbackOverride: 0 82 | forceMaximumCompressionQuality_BC6H_BC7: 0 83 | - serializedVersion: 3 84 | buildTarget: Standalone 85 | maxTextureSize: 2048 86 | resizeAlgorithm: 0 87 | textureFormat: -1 88 | textureCompression: 1 89 | compressionQuality: 50 90 | crunchedCompression: 0 91 | allowsAlphaSplitting: 0 92 | overridden: 0 93 | ignorePlatformSupport: 0 94 | androidETC2FallbackOverride: 0 95 | forceMaximumCompressionQuality_BC6H_BC7: 0 96 | - serializedVersion: 3 97 | buildTarget: Windows Store Apps 98 | maxTextureSize: 2048 99 | resizeAlgorithm: 0 100 | textureFormat: -1 101 | textureCompression: 1 102 | compressionQuality: 50 103 | crunchedCompression: 0 104 | allowsAlphaSplitting: 0 105 | overridden: 0 106 | ignorePlatformSupport: 0 107 | androidETC2FallbackOverride: 0 108 | forceMaximumCompressionQuality_BC6H_BC7: 0 109 | spriteSheet: 110 | serializedVersion: 2 111 | sprites: [] 112 | outline: [] 113 | physicsShape: [] 114 | bones: [] 115 | spriteID: 5e97eb03825dee720800000000000000 116 | internalID: 0 117 | vertices: [] 118 | indices: 119 | edges: [] 120 | weights: [] 121 | secondaryTextures: [] 122 | nameFileIdTable: {} 123 | mipmapLimitGroupName: 124 | pSDRemoveMatte: 0 125 | userData: 126 | assetBundleName: 127 | assetBundleVariant: 128 | -------------------------------------------------------------------------------- /README.md.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 736a41a42fa9e1a4a98fe2a25a4ae771 3 | TextScriptImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Scripts.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e327d793638545ad897b4ec900a0112a 3 | timeCreated: 1740441019 -------------------------------------------------------------------------------- /Scripts/UnityCloudService.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 46a58627d1564e4393d9037e858ecd39 3 | timeCreated: 1740441031 -------------------------------------------------------------------------------- /Scripts/UnityCloudService/CloudBuildManifest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using UnityEngine; 4 | 5 | namespace Wireframe 6 | { 7 | /// 8 | /// Manifest containing all the information about the build if it was made using UnityCloud 9 | /// UnityCloud makes one of these for every build and puts it saves it as Resources/UnityCloudBuildManifest.json 10 | /// 11 | [Serializable] 12 | public class CloudBuildManifest 13 | { 14 | public static CloudBuildManifest Instance 15 | { 16 | get 17 | { 18 | if (m_instance == null) 19 | { 20 | // Get Manifest created by Unity Cloud 21 | var manifest = Resources.Load("UnityCloudBuildManifest"); // UnityCloud default 22 | if (manifest != null) 23 | { 24 | Debug.Log("[CloudUtil] Found Manifest"); 25 | m_instance = JsonUtility.FromJson(manifest.text); 26 | Debug.Log("[CloudUtil] Build: " + m_instance.buildNumber); 27 | } 28 | else 29 | { 30 | Debug.LogError("[CloudUtil] Could not find Manifest"); 31 | m_instance = new CloudBuildManifest(); 32 | m_instance.Save(); 33 | } 34 | } 35 | 36 | return m_instance; 37 | } 38 | } 39 | 40 | private static CloudBuildManifest m_instance; 41 | 42 | // Commit or changelist built by UCB 43 | public string CommitID 44 | { 45 | get => scmCommitId; 46 | set => scmCommitId = value; 47 | } 48 | 49 | // Name of the branch that was built 50 | public string Branch 51 | { 52 | get => scmBranch; 53 | set => scmBranch = value; 54 | } 55 | 56 | // The Unity Cloud Build number corresponding to this build 57 | public int BuildNumber 58 | { 59 | get => buildNumber; 60 | set => buildNumber = value; 61 | } 62 | 63 | // The UTC timestamp when the build process was started 64 | public string StartTime 65 | { 66 | get => buildStartTime; 67 | set => buildStartTime = value; 68 | } 69 | 70 | // The UCB project identifier 71 | public string ProjectId 72 | { 73 | get => projectId; 74 | set => projectId = value; 75 | } 76 | 77 | // (iOS and Android only) The bundleIdentifier configured in Unity Cloud Build 78 | public string BundleId 79 | { 80 | get => bundleId; 81 | set => bundleId = value; 82 | } 83 | 84 | // The version of Unity used by UCB to create the build 85 | public string UnityVersion 86 | { 87 | get => unityVersion; 88 | set => unityVersion = value; 89 | } 90 | 91 | // (iOS only) The version of XCode used to build the project 92 | public string XCodeVersion 93 | { 94 | get => xcodeVersion; 95 | set => xcodeVersion = value; 96 | } 97 | 98 | // The name of the project build target that was built. Currently, this will correspond to the platform, as either "default-web”, “default-ios”, or “default-android" 99 | public string CloudBuildTargetName 100 | { 101 | get => cloudBuildTargetName; 102 | set => cloudBuildTargetName = value; 103 | } 104 | 105 | [SerializeField] private string scmCommitId; 106 | [SerializeField] private string scmBranch; 107 | [SerializeField] private int buildNumber; 108 | [SerializeField] private string buildStartTime; 109 | [SerializeField] private string projectId; 110 | [SerializeField] private string bundleId; 111 | [SerializeField] private string unityVersion; 112 | [SerializeField] private string xcodeVersion; 113 | [SerializeField] private string cloudBuildTargetName; 114 | 115 | public void Save() 116 | { 117 | string json = JsonUtility.ToJson(m_instance); 118 | File.WriteAllText($"{Application.dataPath}/Resources/UnityCloudBuildManifest.json", json); 119 | } 120 | } 121 | } -------------------------------------------------------------------------------- /Scripts/UnityCloudService/CloudBuildManifest.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 97c18f953b71b204f9d960588d34c5d8 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Scripts/veugeljame.builduploader.asmdef: -------------------------------------------------------------------------------- 1 | { 2 | "name": "VeugelJame.BuildUploader", 3 | "rootNamespace": "", 4 | "references": [], 5 | "includePlatforms": [], 6 | "excludePlatforms": [], 7 | "allowUnsafeCode": false, 8 | "overrideReferences": false, 9 | "precompiledReferences": [], 10 | "autoReferenced": true, 11 | "defineConstraints": [], 12 | "versionDefines": [], 13 | "noEngineReferences": false 14 | } -------------------------------------------------------------------------------- /Scripts/veugeljame.builduploader.asmdef.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 4c800362d85ec4145b19593ffacc0990 3 | AssemblyDefinitionImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "displayName": "Build Uploader", 3 | "name": "com.veugeljame.builduploader", 4 | "unity": "2022.3", 5 | "description": "Open Source Editor tool that streamlines uploading builds to online services such as Steam.\nOptional Unity Cloud support.", 6 | "category": "Tool", 7 | "keywords": [ 8 | "steam", 9 | "build", 10 | "cloud", 11 | "unitycloud", 12 | "upload", 13 | "pipeline", 14 | "steampipe", 15 | "depot" 16 | ], 17 | "version": "2.2.0", 18 | "dependencies": {} 19 | } -------------------------------------------------------------------------------- /package.json.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 45c2deeb62ce8574fade35fe68955044 3 | PackageManifestImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /warningicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JamesVeug/UnitySteamBuildUploader/2e6df95625a9ad1f0fe70a93a6b1287d71c1c778/warningicon.png -------------------------------------------------------------------------------- /warningicon.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d42d60f38db48914dbd20e12844ae990 3 | TextureImporter: 4 | internalIDToNameTable: [] 5 | externalObjects: {} 6 | serializedVersion: 12 7 | mipmaps: 8 | mipMapMode: 0 9 | enableMipMap: 0 10 | sRGBTexture: 1 11 | linearTexture: 0 12 | fadeOut: 0 13 | borderMipMap: 0 14 | mipMapsPreserveCoverage: 0 15 | alphaTestReferenceValue: 0.5 16 | mipMapFadeDistanceStart: 1 17 | mipMapFadeDistanceEnd: 3 18 | bumpmap: 19 | convertToNormalMap: 0 20 | externalNormalMap: 0 21 | heightScale: 0.25 22 | normalMapFilter: 0 23 | flipGreenChannel: 0 24 | isReadable: 0 25 | streamingMipmaps: 0 26 | streamingMipmapsPriority: 0 27 | vTOnly: 0 28 | ignoreMipmapLimit: 0 29 | grayScaleToAlpha: 0 30 | generateCubemap: 6 31 | cubemapConvolution: 0 32 | seamlessCubemap: 0 33 | textureFormat: 1 34 | maxTextureSize: 2048 35 | textureSettings: 36 | serializedVersion: 2 37 | filterMode: 1 38 | aniso: 1 39 | mipBias: 0 40 | wrapU: 1 41 | wrapV: 1 42 | wrapW: 1 43 | nPOTScale: 0 44 | lightmap: 0 45 | compressionQuality: 50 46 | spriteMode: 1 47 | spriteExtrude: 1 48 | spriteMeshType: 1 49 | alignment: 0 50 | spritePivot: {x: 0.5, y: 0.5} 51 | spritePixelsToUnits: 100 52 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 53 | spriteGenerateFallbackPhysicsShape: 1 54 | alphaUsage: 1 55 | alphaIsTransparency: 1 56 | spriteTessellationDetail: -1 57 | textureType: 8 58 | textureShape: 1 59 | singleChannelComponent: 0 60 | flipbookRows: 1 61 | flipbookColumns: 1 62 | maxTextureSizeSet: 0 63 | compressionQualitySet: 0 64 | textureFormatSet: 0 65 | ignorePngGamma: 0 66 | applyGammaDecoding: 0 67 | swizzle: 50462976 68 | cookieLightType: 0 69 | platformSettings: 70 | - serializedVersion: 3 71 | buildTarget: DefaultTexturePlatform 72 | maxTextureSize: 2048 73 | resizeAlgorithm: 0 74 | textureFormat: -1 75 | textureCompression: 1 76 | compressionQuality: 50 77 | crunchedCompression: 0 78 | allowsAlphaSplitting: 0 79 | overridden: 0 80 | ignorePlatformSupport: 0 81 | androidETC2FallbackOverride: 0 82 | forceMaximumCompressionQuality_BC6H_BC7: 0 83 | - serializedVersion: 3 84 | buildTarget: Standalone 85 | maxTextureSize: 2048 86 | resizeAlgorithm: 0 87 | textureFormat: -1 88 | textureCompression: 1 89 | compressionQuality: 50 90 | crunchedCompression: 0 91 | allowsAlphaSplitting: 0 92 | overridden: 0 93 | ignorePlatformSupport: 0 94 | androidETC2FallbackOverride: 0 95 | forceMaximumCompressionQuality_BC6H_BC7: 0 96 | - serializedVersion: 3 97 | buildTarget: Windows Store Apps 98 | maxTextureSize: 2048 99 | resizeAlgorithm: 0 100 | textureFormat: -1 101 | textureCompression: 1 102 | compressionQuality: 50 103 | crunchedCompression: 0 104 | allowsAlphaSplitting: 0 105 | overridden: 0 106 | ignorePlatformSupport: 0 107 | androidETC2FallbackOverride: 0 108 | forceMaximumCompressionQuality_BC6H_BC7: 0 109 | spriteSheet: 110 | serializedVersion: 2 111 | sprites: [] 112 | outline: [] 113 | physicsShape: [] 114 | bones: [] 115 | spriteID: 5e97eb03825dee720800000000000000 116 | internalID: 0 117 | vertices: [] 118 | indices: 119 | edges: [] 120 | weights: [] 121 | secondaryTextures: [] 122 | nameFileIdTable: {} 123 | mipmapLimitGroupName: 124 | pSDRemoveMatte: 0 125 | userData: 126 | assetBundleName: 127 | assetBundleVariant: 128 | --------------------------------------------------------------------------------