123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863 |
- using System;
- using System.Diagnostics.CodeAnalysis;
- using SingularityGroup.HotReload.DTO;
- using SingularityGroup.HotReload.Editor.Cli;
- using UnityEditor;
- using UnityEngine;
- using EditorGUI = UnityEditor.EditorGUI;
- namespace SingularityGroup.HotReload.Editor {
- internal struct HotReloadSettingsTabState {
- public readonly bool running;
- public readonly bool trialLicense;
- public readonly LoginStatusResponse loginStatus;
- public readonly bool isServerHealthy;
- public readonly bool registrationRequired;
-
- public HotReloadSettingsTabState(
- bool running,
- bool trialLicense,
- LoginStatusResponse loginStatus,
- bool isServerHealthy,
- bool registrationRequired
- ) {
- this.running = running;
- this.trialLicense = trialLicense;
- this.loginStatus = loginStatus;
- this.isServerHealthy = isServerHealthy;
- this.registrationRequired = registrationRequired;
- }
- }
- internal class HotReloadSettingsTab : HotReloadTabBase {
- private readonly HotReloadOptionsSection optionsSection;
- // cached because changing built target triggers C# domain reload
- // Also I suspect selectedBuildTargetGroup has chance to freeze Unity for several seconds (unconfirmed).
- private readonly Lazy<BuildTargetGroup> currentBuildTarget = new Lazy<BuildTargetGroup>(
- () => BuildPipeline.GetBuildTargetGroup(EditorUserBuildSettings.activeBuildTarget));
- private readonly Lazy<bool> isCurrentBuildTargetSupported = new Lazy<bool>(() => {
- var target = BuildPipeline.GetBuildTargetGroup(EditorUserBuildSettings.activeBuildTarget);
- return HotReloadBuildHelper.IsMonoSupported(target);
- });
- // Resources.Load uses cache, so it's safe to call it every frame.
- // Retrying Load every time fixes an issue where you import the package and constructor runs, but resources aren't loadable yet.
- private Texture iconCheck => Resources.Load<Texture>("icon_check_circle");
- private Texture iconWarning => Resources.Load<Texture>("icon_warning_circle");
- [SuppressMessage("ReSharper", "Unity.UnknownResource")] // Rider doesn't check packages
- public HotReloadSettingsTab(HotReloadWindow window) : base(window,
- "Settings",
- "_Popup",
- "Make changes to a build running on-device.") {
- optionsSection = new HotReloadOptionsSection();
- }
- private GUIStyle headlineStyle;
- private GUIStyle paddedStyle;
-
- private Vector2 _settingsTabScrollPos;
-
- HotReloadSettingsTabState currentState;
- public override void OnGUI() {
- // HotReloadAboutTabState ensures rendering is consistent between Layout and Repaint calls
- // Without it errors like this happen:
- // ArgumentException: Getting control 2's position in a group with only 2 controls when doing repaint
- // See thread for more context: https://answers.unity.com/questions/17718/argumentexception-getting-control-2s-position-in-a.html
- if (Event.current.type == EventType.Layout) {
- currentState = new HotReloadSettingsTabState(
- running: EditorCodePatcher.Running,
- trialLicense: EditorCodePatcher.Status != null && (EditorCodePatcher.Status?.isTrial == true),
- loginStatus: EditorCodePatcher.Status,
- isServerHealthy: ServerHealthCheck.I.IsServerHealthy,
- registrationRequired: RedeemLicenseHelper.I.RegistrationRequired
- );
- }
- using (var scope = new EditorGUILayout.ScrollViewScope(_settingsTabScrollPos, GUI.skin.horizontalScrollbar, GUI.skin.verticalScrollbar, GUILayout.MaxHeight(Math.Max(HotReloadWindowStyles.windowScreenHeight, 800)), GUILayout.MaxWidth(Math.Max(HotReloadWindowStyles.windowScreenWidth, 800)))) {
- _settingsTabScrollPos.x = scope.scrollPosition.x;
- _settingsTabScrollPos.y = scope.scrollPosition.y;
- using (new EditorGUILayout.VerticalScope(HotReloadWindowStyles.DynamicSectionHelpTab)) {
- GUILayout.Space(10);
- if (!EditorCodePatcher.LoginNotRequired
- && !currentState.registrationRequired
- // Delay showing login in settings to not confuse users that they need to login to use Free trial
- && (HotReloadPrefs.RateAppShown
- || PackageConst.IsAssetStoreBuild)
- ) {
- using (new EditorGUILayout.HorizontalScope(HotReloadWindowStyles.SectionOuterBoxCompact)) {
- using (new EditorGUILayout.HorizontalScope(HotReloadWindowStyles.SectionInnerBoxWide)) {
- using (new EditorGUILayout.VerticalScope()) {
- RenderLicenseInfoSection();
- }
- }
- }
- }
- using (new EditorGUILayout.HorizontalScope(HotReloadWindowStyles.SectionOuterBoxCompact)) {
- using (new EditorGUILayout.HorizontalScope(HotReloadWindowStyles.SectionInnerBoxWide)) {
- using (new EditorGUILayout.VerticalScope()) {
- HotReloadPrefs.ShowConfiguration = EditorGUILayout.Foldout(HotReloadPrefs.ShowConfiguration, "Settings", true, HotReloadWindowStyles.FoldoutStyle);
- if (HotReloadPrefs.ShowConfiguration) {
- EditorGUILayout.Space();
- // main section
- RenderUnityAutoRefresh();
- using (new EditorGUI.DisabledScope(!EditorCodePatcher.autoRecompileUnsupportedChangesSupported)) {
- RenderAutoRecompileUnsupportedChanges();
- if (HotReloadPrefs.AutoRecompileUnsupportedChanges && EditorCodePatcher.autoRecompileUnsupportedChangesSupported) {
- using (new EditorGUILayout.VerticalScope(paddedStyle ?? (paddedStyle = new GUIStyle { padding = new RectOffset(20, 0, 0, 0) }))) {
- RenderAutoRecompileUnsupportedChangesImmediately();
- RenderAutoRecompileUnsupportedChangesOnExitPlayMode();
- RenderAutoRecompileUnsupportedChangesInPlayMode();
- RenderAutoRecompilePartiallyUnsupportedChanges();
- RenderDisplayNewMonobehaviourMethodsAsPartiallySupported();
- }
- }
- EditorGUILayout.Space();
- }
- RenderAssetRefresh();
- if (HotReloadPrefs.AllAssetChanges) {
- using (new EditorGUILayout.VerticalScope(paddedStyle ?? (paddedStyle = new GUIStyle { padding = new RectOffset(20, 0, 0, 0) }))) {
- RenderIncludeShaderChanges();
- }
- EditorGUILayout.Space();
- }
- RenderDebuggerCompatibility();
- // // fields
- // RenderShowFeatures();
- // using (new EditorGUILayout.VerticalScope(paddedStyle ?? (paddedStyle = new GUIStyle { padding = new RectOffset(20, 0, 0, 0) }))) {
- // RenderShowApplyfieldInitializerEditsToExistingClassInstances();
- //
- // EditorGUILayout.Space();
- // }
- // visual feedback
- if (EditorWindowHelper.supportsNotifications) {
- RenderShowNotifications();
- using (new EditorGUILayout.VerticalScope(paddedStyle ?? (paddedStyle = new GUIStyle { padding = new RectOffset(20, 0, 0, 0) }))) {
- RenderShowPatchingNotifications();
- RenderShowCompilingUnsupportedNotifications();
- }
- EditorGUILayout.Space();
- }
- // misc
- RenderMiscHeader();
- using (new EditorGUILayout.VerticalScope(paddedStyle ?? (paddedStyle = new GUIStyle { padding = new RectOffset(20, 0, 0, 0) }))) {
- RenderAutostart();
- RenderConsoleWindow();
- EditorGUILayout.Space();
- }
- EditorGUILayout.Space();
- using (new EditorGUILayout.HorizontalScope()) {
- GUILayout.FlexibleSpace();
- HotReloadWindow.RenderShowOnStartup();
- }
- }
- }
- }
- }
- if (!EditorCodePatcher.LoginNotRequired && currentState.trialLicense && currentState.running) {
- using (new EditorGUILayout.HorizontalScope(HotReloadWindowStyles.SectionOuterBoxCompact)) {
- using (new EditorGUILayout.HorizontalScope(HotReloadWindowStyles.SectionInnerBoxWide)) {
- using (new EditorGUILayout.VerticalScope()) {
- RenderPromoCodeSection();
- }
- }
- }
- }
- using (new EditorGUILayout.HorizontalScope(HotReloadWindowStyles.SectionOuterBoxCompact)) {
- using (new EditorGUILayout.HorizontalScope(HotReloadWindowStyles.SectionInnerBoxWide)) {
- using (new EditorGUILayout.VerticalScope()) {
- RenderOnDevice();
- }
- }
- }
-
- using (new EditorGUILayout.HorizontalScope(HotReloadWindowStyles.SectionOuterBoxCompact)) {
- using (new EditorGUILayout.HorizontalScope(HotReloadWindowStyles.SectionInnerBoxWide)) {
- using (new EditorGUILayout.VerticalScope()) {
- HotReloadPrefs.ShowAdvanced = EditorGUILayout.Foldout(HotReloadPrefs.ShowAdvanced, "Advanced", true, HotReloadWindowStyles.FoldoutStyle);
- if (HotReloadPrefs.ShowAdvanced) {
- EditorGUILayout.Space();
- DeactivateHotReload();
- DisableDetailedErrorReporting();
- }
- }
- }
- }
- }
- }
- }
- void RenderUnityAutoRefresh() {
- var newSettings = EditorGUILayout.BeginToggleGroup(new GUIContent("Manage Unity auto-refresh (recommended)"), HotReloadPrefs.AllowDisableUnityAutoRefresh);
- if (newSettings != HotReloadPrefs.AllowDisableUnityAutoRefresh) {
- HotReloadPrefs.AllowDisableUnityAutoRefresh = newSettings;
- }
- string toggleDescription;
- if (HotReloadPrefs.AllowDisableUnityAutoRefresh) {
- toggleDescription = "To avoid unnecessary recompiling, Hot Reload will automatically change Unity's Auto Refresh and Script Compilation settings. Previous settings will be restored when Hot Reload is stopped";
- } else {
- toggleDescription = "Enabled this setting to auto-manage Unity's Auto Refresh and Script Compilation settings. This reduces unncessary recompiling";
- }
- EditorGUILayout.LabelField(toggleDescription, HotReloadWindowStyles.WrapStyle);
- EditorGUILayout.EndToggleGroup();
- EditorGUILayout.Space(6f);
- }
-
- void RenderAssetRefresh() {
- var newSettings = EditorGUILayout.BeginToggleGroup(new GUIContent("Asset refresh (recommended)"), HotReloadPrefs.AllAssetChanges);
- if (newSettings != HotReloadPrefs.AllAssetChanges) {
- HotReloadPrefs.AllAssetChanges = newSettings;
- // restart when setting changes
- if (ServerHealthCheck.I.IsServerHealthy) {
- var restartServer = EditorUtility.DisplayDialog("Hot Reload",
- $"When changing 'Asset refresh', the Hot Reload server must be restarted for this to take effect." +
- "\nDo you want to restart it now?",
- "Restart Hot Reload", "Don't restart");
- if (restartServer) {
- EditorCodePatcher.RestartCodePatcher().Forget();
- }
- }
- }
- string toggleDescription;
- if (HotReloadPrefs.AllAssetChanges) {
- toggleDescription = "Hot Reload will refresh changed assets such as sprites, prefabs, etc";
- } else {
- toggleDescription = "Enable to allow Hot Reload to refresh changed assets in the project. All asset types are supported including sprites, prefabs, shaders etc";
- }
- EditorGUILayout.LabelField(toggleDescription, HotReloadWindowStyles.WrapStyle);
- EditorGUILayout.EndToggleGroup();
- EditorGUILayout.Space(6f);
- }
-
- void RenderDebuggerCompatibility() {
- var newSettings = EditorGUILayout.BeginToggleGroup(new GUIContent("Auto-disable Hot Reload while a debugger is attached (recommended)"), HotReloadPrefs.AutoDisableHotReloadWithDebugger);
- if (newSettings != HotReloadPrefs.AutoDisableHotReloadWithDebugger) {
- HotReloadPrefs.AutoDisableHotReloadWithDebugger = newSettings;
- CodePatcher.I.debuggerCompatibilityEnabled = !HotReloadPrefs.AutoDisableHotReloadWithDebugger;
- }
- string toggleDescription;
- if (HotReloadPrefs.AutoDisableHotReloadWithDebugger) {
- toggleDescription = "Hot Reload automatically disables itself while a debugger is attached, as it can otherwise interfere with certain debugger features. Please read the documentation if you consider disabling this setting.";
- } else {
- toggleDescription = "When a debugger is attached, Hot Reload will be active, but certain debugger features might not work as expected. Please read our documentation to learn about the limitations.";
- }
- EditorGUILayout.LabelField(toggleDescription, HotReloadWindowStyles.WrapStyle);
- EditorGUILayout.EndToggleGroup();
- EditorGUILayout.Space(6f);
- }
-
- void RenderIncludeShaderChanges() {
- HotReloadPrefs.IncludeShaderChanges = EditorGUILayout.BeginToggleGroup(new GUIContent("Refresh shaders"), HotReloadPrefs.IncludeShaderChanges);
- string toggleDescription;
- if (HotReloadPrefs.IncludeShaderChanges) {
- toggleDescription = "Hot Reload will auto refresh shaders. Note that enabling this setting might impact performance.";
- } else {
- toggleDescription = "Enable to auto-refresh shaders. Note that enabling this setting might impact performance";
- }
- EditorGUILayout.LabelField(toggleDescription, HotReloadWindowStyles.WrapStyle);
- EditorGUILayout.EndToggleGroup();
- }
- void RenderConsoleWindow() {
- if (!HotReloadCli.CanOpenInBackground) {
- return;
- }
- var newSettings = EditorGUILayout.BeginToggleGroup(new GUIContent("Hide console window on start"), HotReloadPrefs.DisableConsoleWindow);
- if (newSettings != HotReloadPrefs.DisableConsoleWindow) {
- HotReloadPrefs.DisableConsoleWindow = newSettings;
- // restart when setting changes
- if (ServerHealthCheck.I.IsServerHealthy) {
- var restartServer = EditorUtility.DisplayDialog("Hot Reload",
- $"When changing 'Hide console window on start', the Hot Reload server must be restarted for this to take effect." +
- "\nDo you want to restart it now?",
- "Restart server", "Don't restart");
- if (restartServer) {
- EditorCodePatcher.RestartCodePatcher().Forget();
- }
- }
- }
- string toggleDescription;
- if (HotReloadPrefs.DisableConsoleWindow) {
- toggleDescription = "Hot Reload will start without creating a console window. Logs can be accessed through \"Help\" tab.";
- } else {
- toggleDescription = "Enable to start Hot Reload without creating a console window.";
- }
- EditorGUILayout.LabelField(toggleDescription, HotReloadWindowStyles.WrapStyle);
- EditorGUILayout.EndToggleGroup();
- EditorGUILayout.Space(6f);
- }
-
- void DeactivateHotReload() {
- var newSettings = EditorGUILayout.BeginToggleGroup(new GUIContent("Deactivate Hot Reload"), HotReloadPrefs.DeactivateHotReload);
- if (newSettings != HotReloadPrefs.DeactivateHotReload) {
- DeactivateHotReloadInner(newSettings);
- }
- string toggleDescription;
- if (HotReloadPrefs.DeactivateHotReload) {
- toggleDescription = "Hot Reload is deactivated.";
- } else {
- toggleDescription = "Enable to deactivate Hot Reload.";
- }
- EditorGUILayout.LabelField(toggleDescription, HotReloadWindowStyles.WrapStyle);
- EditorGUILayout.EndToggleGroup();
- EditorGUILayout.Space(6f);
- }
-
- void DisableDetailedErrorReporting() {
- var newSettings = EditorGUILayout.BeginToggleGroup(new GUIContent("Disable Detailed Error Reporting"), HotReloadPrefs.DisableDetailedErrorReporting);
- DisableDetailedErrorReportingInner(newSettings);
- string toggleDescription;
- if (HotReloadPrefs.DisableDetailedErrorReporting) {
- toggleDescription = "Detailed error reporting is disabled.";
- } else {
- toggleDescription = "Toggle on to disable detailed error reporting.";
- }
- EditorGUILayout.LabelField(toggleDescription, HotReloadWindowStyles.WrapStyle);
- EditorGUILayout.EndToggleGroup();
- EditorGUILayout.Space(6f);
- }
- public static void DisableDetailedErrorReportingInner(bool newSetting) {
- if (newSetting == HotReloadPrefs.DisableDetailedErrorReporting) {
- return;
- }
- HotReloadPrefs.DisableDetailedErrorReporting = newSetting;
- // restart when setting changes
- if (ServerHealthCheck.I.IsServerHealthy) {
- var restartServer = EditorUtility.DisplayDialog("Hot Reload",
- $"When changing 'Disable Detailed Error Reporting', the Hot Reload server must be restarted for this to take effect." +
- "\nDo you want to restart it now?",
- "Restart server", "Don't restart");
- if (restartServer) {
- EditorCodePatcher.RestartCodePatcher().Forget();
- }
- }
- }
- static void DeactivateHotReloadInner(bool deactivate) {
- var confirmed = !deactivate || EditorUtility.DisplayDialog("Hot Reload",
- $"Hot Reload will be completely deactivated (unusable) until you activate it again." +
- "\n\nDo you want to proceed?",
- "Deactivate", "Cancel");
- if (confirmed) {
- HotReloadPrefs.DeactivateHotReload = deactivate;
- if (deactivate) {
- EditorCodePatcher.StopCodePatcher(recompileOnDone: true).Forget();
- } else {
- HotReloadRunTab.Recompile();
- }
- }
- }
- void RenderAutostart() {
- var newSettings = EditorGUILayout.BeginToggleGroup(new GUIContent("Autostart on Unity open"), HotReloadPrefs.LaunchOnEditorStart);
- if (newSettings != HotReloadPrefs.LaunchOnEditorStart) {
- HotReloadPrefs.LaunchOnEditorStart = newSettings;
- }
- string toggleDescription;
- if (HotReloadPrefs.LaunchOnEditorStart) {
- toggleDescription = "Hot Reload will be launched when Unity project opens.";
- } else {
- toggleDescription = "Enable to launch Hot Reload when Unity project opens.";
- }
- EditorGUILayout.LabelField(toggleDescription, HotReloadWindowStyles.WrapStyle);
- EditorGUILayout.EndToggleGroup();
- EditorGUILayout.Space();
- }
- void RenderShowNotifications() {
- EditorGUILayout.Space(10f);
- GUILayout.Label("Visual Feedback", HotReloadWindowStyles.NotificationsTitleStyle);
- EditorGUILayout.Space(10f);
-
- if (!EditorWindowHelper.supportsNotifications && !UnitySettingsHelper.I.playmodeTintSupported) {
- var toggleDescription = "Indications are not supported in the Unity version you use.";
- EditorGUILayout.LabelField(toggleDescription, HotReloadWindowStyles.WrapStyle);
- }
- }
- // void RenderShowFields() {
- // EditorGUILayout.Space(14f);
- // GUILayout.Label("Fields", HotReloadWindowStyles.NotificationsTitleStyle);
- // }
- void RenderMiscHeader() {
- EditorGUILayout.Space(10f);
- GUILayout.Label("Misc", HotReloadWindowStyles.NotificationsTitleStyle);
- EditorGUILayout.Space(10f);
- }
- void RenderShowPatchingNotifications() {
- HotReloadPrefs.ShowPatchingNotifications = EditorGUILayout.BeginToggleGroup(new GUIContent("Patching Indication"), HotReloadPrefs.ShowPatchingNotifications);
- string toggleDescription;
- if (!EditorWindowHelper.supportsNotifications) {
- toggleDescription = "Patching Notification is not supported in the Unity version you use.";
- } else if (!HotReloadPrefs.ShowPatchingNotifications) {
- toggleDescription = "Enable to show GameView and SceneView indications when Patching.";
- } else {
- toggleDescription = "Indications will be shown in GameView and SceneView when Patching.";
- }
- EditorGUILayout.LabelField(toggleDescription, HotReloadWindowStyles.WrapStyle);
- EditorGUILayout.EndToggleGroup();
- }
-
- // void RenderShowApplyfieldInitializerEditsToExistingClassInstances() {
- // var newSetting = EditorGUILayout.BeginToggleGroup(new GUIContent("Apply field initializer edits to existing class instances"), HotReloadPrefs.ApplyFieldInitiailzerEditsToExistingClassInstances);
- // ApplyApplyFieldInitializerEditsToExistingClassInstances(newSetting);
- // string toggleDescription;
- // if (HotReloadPrefs.ApplyFieldInitiailzerEditsToExistingClassInstances) {
- // toggleDescription = "New field initializers with constant value will update field value of existing objects.";
- // } else {
- // toggleDescription = "New field initializers will not modify existing objects.";
- // }
- // EditorGUILayout.LabelField(toggleDescription, HotReloadWindowStyles.WrapStyle);
- // EditorGUILayout.EndToggleGroup();
- // }
- [Obsolete("Not implemented")]
- public static void ApplyApplyFieldInitializerEditsToExistingClassInstances(bool newSetting) {
- if (newSetting != HotReloadPrefs.ApplyFieldInitiailzerEditsToExistingClassInstances) {
- HotReloadPrefs.ApplyFieldInitiailzerEditsToExistingClassInstances = newSetting;
- // restart when setting changes
- if (ServerHealthCheck.I.IsServerHealthy) {
- var restartServer = EditorUtility.DisplayDialog("Hot Reload",
- $"When changing 'Apply field initializer edits to existing class instances' setting, the Hot Reload server must restart for it to take effect." +
- "\nDo you want to restart it now?",
- "Restart server", "Don't restart");
- if (restartServer) {
- EditorCodePatcher.RestartCodePatcher().Forget();
- }
- }
- }
- }
- void RenderShowCompilingUnsupportedNotifications() {
- HotReloadPrefs.ShowCompilingUnsupportedNotifications = EditorGUILayout.BeginToggleGroup(new GUIContent("Compiling Unsupported Changes Indication"), HotReloadPrefs.ShowCompilingUnsupportedNotifications);
- string toggleDescription;
- if (!EditorWindowHelper.supportsNotifications) {
- toggleDescription = "Compiling Unsupported Changes Notification is not supported in the Unity version you use.";
- } else if (!HotReloadPrefs.ShowCompilingUnsupportedNotifications) {
- toggleDescription = "Enable to show GameView and SceneView indications when compiling unsupported changes.";
- } else {
- toggleDescription = "Indications will be shown in GameView and SceneView when compiling unsupported changes.";
- }
- EditorGUILayout.LabelField(toggleDescription, HotReloadWindowStyles.WrapStyle);
- EditorGUILayout.EndToggleGroup();
- }
-
- void RenderAutoRecompileUnsupportedChanges() {
- HotReloadPrefs.AutoRecompileUnsupportedChanges = EditorGUILayout.BeginToggleGroup(new GUIContent("Auto recompile unsupported changes (recommended)"), HotReloadPrefs.AutoRecompileUnsupportedChanges && EditorCodePatcher.autoRecompileUnsupportedChangesSupported);
- string toggleDescription;
- if (!EditorCodePatcher.autoRecompileUnsupportedChangesSupported) {
- toggleDescription = "Auto recompiling unsupported changes is not supported in the Unity version you use.";
- } else if (HotReloadPrefs.AutoRecompileUnsupportedChanges) {
- toggleDescription = "Hot Reload will recompile automatically after code changes that Hot Reload doesn't support.";
- } else {
- toggleDescription = "When enabled, recompile happens automatically after code changes that Hot Reload doesn't support.";
- }
- EditorGUILayout.LabelField(toggleDescription, HotReloadWindowStyles.WrapStyle);
- EditorGUILayout.EndToggleGroup();
- }
-
- void RenderAutoRecompilePartiallyUnsupportedChanges() {
- HotReloadPrefs.AutoRecompilePartiallyUnsupportedChanges = EditorGUILayout.BeginToggleGroup(new GUIContent("Include partially unsupported changes"), HotReloadPrefs.AutoRecompilePartiallyUnsupportedChanges);
- string toggleDescription;
- if (HotReloadPrefs.AutoRecompilePartiallyUnsupportedChanges) {
- toggleDescription = "Hot Reload will recompile partially unsupported changes.";
- } else {
- toggleDescription = "Enable to recompile partially unsupported changes.";
- }
- EditorGUILayout.LabelField(toggleDescription, HotReloadWindowStyles.WrapStyle);
- EditorGUILayout.EndToggleGroup();
- }
-
- void RenderDisplayNewMonobehaviourMethodsAsPartiallySupported() {
- HotReloadPrefs.DisplayNewMonobehaviourMethodsAsPartiallySupported = EditorGUILayout.BeginToggleGroup(new GUIContent("Display new Monobehaviour methods as partially supported"), HotReloadPrefs.DisplayNewMonobehaviourMethodsAsPartiallySupported);
- string toggleDescription;
- if (HotReloadPrefs.DisplayNewMonobehaviourMethodsAsPartiallySupported) {
- toggleDescription = "Hot Reload will display new monobehaviour methods as partially unsupported.";
- } else {
- toggleDescription = "Enable to display new monobehaviour methods as partially unsupported.";
- }
- EditorGUILayout.LabelField(toggleDescription, HotReloadWindowStyles.WrapStyle);
- EditorGUILayout.EndToggleGroup();
- }
-
- void RenderAutoRecompileUnsupportedChangesImmediately() {
- HotReloadPrefs.AutoRecompileUnsupportedChangesImmediately = EditorGUILayout.BeginToggleGroup(new GUIContent("Recompile immediately"), HotReloadPrefs.AutoRecompileUnsupportedChangesImmediately);
- string toggleDescription;
- if (HotReloadPrefs.AutoRecompileUnsupportedChangesImmediately) {
- toggleDescription = "Unsupported changes will be recompiled immediately.";
- } else {
- toggleDescription = "Unsupported changes will be recompiled when editor is focused. Enable to recompile immediately.";
- }
- EditorGUILayout.LabelField(toggleDescription, HotReloadWindowStyles.WrapStyle);
- EditorGUILayout.EndToggleGroup();
- }
-
- void RenderAutoRecompileUnsupportedChangesInPlayMode() {
- HotReloadPrefs.AutoRecompileUnsupportedChangesInPlayMode = EditorGUILayout.BeginToggleGroup(new GUIContent("Recompile in Play Mode"), HotReloadPrefs.AutoRecompileUnsupportedChangesInPlayMode);
- string toggleDescription;
- if (HotReloadPrefs.AutoRecompileUnsupportedChangesInPlayMode) {
- toggleDescription = "Hot Reload will exit Play Mode to recompile unsupported changes.";
- } else {
- toggleDescription = "Enable to auto exit Play Mode to recompile unsupported changes.";
- }
- EditorGUILayout.LabelField(toggleDescription, HotReloadWindowStyles.WrapStyle);
- EditorGUILayout.EndToggleGroup();
- }
-
- void RenderAutoRecompileUnsupportedChangesOnExitPlayMode() {
- HotReloadPrefs.AutoRecompileUnsupportedChangesOnExitPlayMode = EditorGUILayout.BeginToggleGroup(new GUIContent("Recompile on exit Play Mode"), HotReloadPrefs.AutoRecompileUnsupportedChangesOnExitPlayMode);
- string toggleDescription;
- if (HotReloadPrefs.AutoRecompileUnsupportedChangesOnExitPlayMode) {
- toggleDescription = "Hot Reload will recompile unsupported changes when exiting Play Mode.";
- } else {
- toggleDescription = "Enable to recompile unsupported changes when exiting Play Mode.";
- }
- EditorGUILayout.LabelField(toggleDescription, HotReloadWindowStyles.WrapStyle);
- EditorGUILayout.EndToggleGroup();
- }
- void RenderOnDevice() {
- HotReloadPrefs.ShowOnDevice = EditorGUILayout.Foldout(HotReloadPrefs.ShowOnDevice, "On-Device", true, HotReloadWindowStyles.FoldoutStyle);
- if (!HotReloadPrefs.ShowOnDevice) {
- return;
- }
- // header with explainer image
- {
- if (headlineStyle == null) {
- // start with textArea for the background and border colors
- headlineStyle = new GUIStyle(GUI.skin.label) {
- fontStyle = FontStyle.Bold,
- alignment = TextAnchor.MiddleLeft
- };
- headlineStyle.normal.textColor = HotReloadWindowStyles.H2TitleStyle.normal.textColor;
-
- // bg color
- if (HotReloadWindowStyles.IsDarkMode) {
- headlineStyle.normal.background = EditorTextures.DarkGray40;
- } else {
- headlineStyle.normal.background = EditorTextures.LightGray225;
- }
- // layout
- headlineStyle.padding = new RectOffset(8, 8, 0, 0);
- headlineStyle.margin = new RectOffset(6, 6, 6, 6);
- }
- GUILayout.Space(9f); // space between logo and headline
-
- GUILayout.Label("Make changes to a build running on-device",
- headlineStyle, GUILayout.MinHeight(EditorGUIUtility.singleLineHeight * 1.4f));
- // image showing how Hot Reload works with a phone
- // var bannerBox = GUILayoutUtility.GetRect(flowchart.width * 0.6f, flowchart.height * 0.6f);
- // GUI.DrawTexture(bannerBox, flowchart, ScaleMode.ScaleToFit);
- }
- GUILayout.Space(16f);
-
- //ButtonToOpenBuildSettings();
- {
- GUILayout.Label("Manual connect", HotReloadWindowStyles.H3TitleStyle);
- EditorGUILayout.Space();
-
- GUILayout.BeginHorizontal();
-
- // indent all controls (this works with non-labels)
- GUILayout.Space(16f);
- GUILayout.BeginVertical();
-
- string text;
- var ip = IpHelper.GetIpAddressCached();
- if (string.IsNullOrEmpty(ip)) {
- text = $"If auto-pair fails, find your local IP in OS settings, and use this format to connect: '{{ip}}:{RequestHelper.port}'";
- } else {
- text = $"If auto-pair fails, use this IP and port to connect: {ip}:{RequestHelper.port}" +
- "\nMake sure you are on the same LAN/WiFi network";
- }
- GUILayout.Label(text, HotReloadWindowStyles.H3TitleWrapStyle);
- if (!currentState.isServerHealthy) {
- DrawHorizontalCheck(ServerHealthCheck.I.IsServerHealthy,
- "Hot Reload is running",
- "Hot Reload is not running",
- hasFix: false);
- }
-
- if (!HotReloadPrefs.ExposeServerToLocalNetwork) {
- var summary = $"Enable '{new ExposeServerOption().ShortSummary}'";
- DrawHorizontalCheck(HotReloadPrefs.ExposeServerToLocalNetwork,
- summary,
- summary);
- }
-
- // explainer image that shows phone needs same wifi to auto connect ?
-
- GUILayout.EndVertical();
- GUILayout.EndHorizontal();
- }
-
- GUILayout.Space(16f);
-
- // loading again is smooth, pretty sure AssetDatabase.LoadAssetAtPath is caching -Troy
- var settingsObject = HotReloadSettingsEditor.LoadSettingsOrDefault();
- var so = new SerializedObject(settingsObject);
-
- // if you build for Android now, will Hot Reload work?
- {
-
- EditorGUILayout.BeginHorizontal();
- GUILayout.Label("Build Settings Checklist", HotReloadWindowStyles.H3TitleStyle);
- EditorGUI.BeginDisabledGroup(isSupported);
- // One-click to change each setting to the supported value
- if (GUILayout.Button("Fix All", GUILayout.MaxWidth(90f))) {
- FixAllUnsupportedSettings(so);
- }
- EditorGUI.EndDisabledGroup();
- EditorGUILayout.EndHorizontal();
-
-
- // NOTE: After user changed some build settings, window may not immediately repaint
- // (e.g. toggle Development Build in Build Settings window)
- // We could show a refresh button (to encourage the user to click the window which makes it repaint).
- DrawSectionCheckBuildSupport(so);
- }
-
- GUILayout.Space(16f);
- // Settings checkboxes (Hot Reload options)
- {
- GUILayout.Label("Options", HotReloadWindowStyles.H3TitleStyle);
- if (settingsObject) {
- optionsSection.DrawGUI(so);
- }
- }
- GUILayout.FlexibleSpace(); // needed otherwise vertical scrollbar is appearing for no reason (Unity 2021 glitch perhaps)
- }
-
- private void RenderLicenseInfoSection() {
- HotReloadRunTab.RenderLicenseInfo(
- _window.RunTabState,
- currentState.loginStatus,
- verbose: true,
- allowHide: false,
- overrideActionButton: "Activate License",
- showConsumptions: true
- );
- }
-
- private void RenderPromoCodeSection() {
- _window.RunTab.RenderPromoCodes();
- }
-
- public void FocusLicenseFoldout() {
- HotReloadPrefs.ShowLogin = true;
- }
- // note: changing scripting backend does not force Unity to recreate the GUI, so need to check it when drawing.
- private ScriptingImplementation ScriptingBackend => HotReloadBuildHelper.GetCurrentScriptingBackend();
- private ManagedStrippingLevel StrippingLevel => HotReloadBuildHelper.GetCurrentStrippingLevel();
- public bool isSupported = true;
- /// <summary>
- /// These options are drawn in the On-device tab
- /// </summary>
- // new on-device options should be added here
- public static readonly IOption[] allOptions = new IOption[] {
- new ExposeServerOption(),
- IncludeInBuildOption.I,
- new AllowAndroidAppToMakeHttpRequestsOption(),
- };
- /// <summary>
- /// Change each setting to the value supported by Hot Reload
- /// </summary>
- private void FixAllUnsupportedSettings(SerializedObject so) {
- if (!isCurrentBuildTargetSupported.Value) {
- // try switch to Android platform
- // (we also support Standalone but HotReload on mobile is a better selling point)
- if (!TrySwitchToStandalone()) {
- // skip changing other options (user won't readthe gray text) - user has to click Fix All again
- return;
- }
- }
-
- foreach (var buildOption in allOptions) {
- if (!buildOption.GetValue(so)) {
- buildOption.SetValue(so, true);
- }
- }
- so.ApplyModifiedProperties();
- var settingsObject = so.targetObject as HotReloadSettingsObject;
- if (settingsObject) {
- // when you click fix all, make sure to save the settings, otherwise ui does not update
- HotReloadSettingsEditor.EnsureSettingsCreated(settingsObject);
- }
-
- if (!EditorUserBuildSettings.development) {
- EditorUserBuildSettings.development = true;
- }
-
- HotReloadBuildHelper.SetCurrentScriptingBackend(ScriptingImplementation.Mono2x);
- HotReloadBuildHelper.SetCurrentStrippingLevel(ManagedStrippingLevel.Disabled);
- }
- public static bool TrySwitchToStandalone() {
- BuildTarget buildTarget;
- if (Application.platform == RuntimePlatform.LinuxEditor) {
- buildTarget = BuildTarget.StandaloneLinux64;
- } else if (Application.platform == RuntimePlatform.WindowsEditor) {
- buildTarget = BuildTarget.StandaloneWindows64;
- } else if (Application.platform == RuntimePlatform.OSXEditor) {
- buildTarget = BuildTarget.StandaloneOSX;
- } else {
- return false;
- }
- var current = EditorUserBuildSettings.activeBuildTarget;
- if (current == buildTarget) {
- return true;
- }
- var confirmed = EditorUtility.DisplayDialog("Switch Build Target",
- "Switching the build target can take a while depending on project size.",
- $"Switch to Standalone", "Cancel");
- if (confirmed) {
- EditorUserBuildSettings.SwitchActiveBuildTargetAsync(BuildTargetGroup.Standalone, buildTarget);
- Log.Info($"Build target is switching to {buildTarget}.");
- return true;
- } else {
- return false;
- }
- }
- /// <summary>
- /// Section that user can check before making a Unity Player build.
- /// </summary>
- /// <param name="so"></param>
- /// <remarks>
- /// This section is for confirming your build will work with Hot Reload.<br/>
- /// Options that can be changed after the build is made should be drawn elsewhere.
- /// </remarks>
- public void DrawSectionCheckBuildSupport(SerializedObject so) {
- isSupported = true;
- var selectedPlatform = currentBuildTarget.Value;
- DrawHorizontalCheck(isCurrentBuildTargetSupported.Value,
- $"The {selectedPlatform.ToString()} platform is selected",
- $"The current platform is {selectedPlatform.ToString()} which is not supported");
- using (new EditorGUI.DisabledScope(!isCurrentBuildTargetSupported.Value)) {
- foreach (var option in allOptions) {
- DrawHorizontalCheck(option.GetValue(so),
- $"Enable \"{option.ShortSummary}\"",
- $"Enable \"{option.ShortSummary}\"");
- }
- DrawHorizontalCheck(EditorUserBuildSettings.development,
- "Development Build is enabled",
- "Enable \"Development Build\"");
-
- DrawHorizontalCheck(ScriptingBackend == ScriptingImplementation.Mono2x,
- $"Scripting Backend is set to Mono",
- $"Set Scripting Backend to Mono");
-
- DrawHorizontalCheck(StrippingLevel == ManagedStrippingLevel.Disabled,
- $"Stripping Level = {StrippingLevel}",
- $"Stripping Level = {StrippingLevel}",
- suggestedSolutionText: "Code stripping needs to be disabled to ensure that all methods are available for patching."
- );
- }
- }
- /// <summary>
- /// Draw a box with a tick or warning icon on the left, with text describing the tick or warning
- /// </summary>
- /// <param name="condition">The condition to check. True to show a tick icon, False to show a warning.</param>
- /// <param name="okText">Shown when condition is true</param>
- /// <param name="notOkText">Shown when condition is false</param>
- /// <param name="suggestedSolutionText">Shown when <paramref name="condition"/> is false</param>
- void DrawHorizontalCheck(bool condition, string okText, string notOkText = null, string suggestedSolutionText = null, bool hasFix = true) {
- if (okText == null) {
- throw new ArgumentNullException(nameof(okText));
- }
- if (notOkText == null) {
- notOkText = okText;
- }
- // include some horizontal space around the icon
- var boxWidth = GUILayout.Width(EditorGUIUtility.singleLineHeight * 1.31f);
- var height = GUILayout.Height(EditorGUIUtility.singleLineHeight * 1.01f);
- GUILayout.BeginHorizontal(HotReloadWindowStyles.BoxStyle, height, GUILayout.ExpandWidth(true));
- var style = HotReloadWindowStyles.NoPaddingMiddleLeftStyle;
- var iconRect = GUILayoutUtility.GetRect(
- Mathf.Round(EditorGUIUtility.singleLineHeight * 1.31f),
- Mathf.Round(EditorGUIUtility.singleLineHeight * 1.01f),
- style, boxWidth, height, GUILayout.ExpandWidth(false));
- // rounded so we can have pixel perfect black circle bg
- iconRect.Set(Mathf.Round(iconRect.x), Mathf.Round(iconRect.y), Mathf.CeilToInt(iconRect.width),
- Mathf.CeilToInt(iconRect.height));
- var text = condition ? okText : notOkText;
- var icon = condition ? iconCheck : iconWarning;
- if (GUI.enabled) {
- DrawBlackCircle(iconRect);
- // resource can be null when building player (Editor Resources not available)
- if (icon) {
- GUI.DrawTexture(iconRect, icon, ScaleMode.ScaleToFit);
- }
- } else {
- // show something (instead of hiding) so that layout stays same size
- DrawDisabledCircle(iconRect);
- }
- GUILayout.Space(4f);
- GUILayout.Label(text, style, height);
- if (!condition && hasFix) {
- isSupported = false;
- }
- GUILayout.EndHorizontal();
- if (!condition && !String.IsNullOrEmpty(suggestedSolutionText)) {
- // suggest to the user how they can resolve the issue
- EditorGUI.indentLevel++;
- GUILayout.Label(suggestedSolutionText, HotReloadWindowStyles.WrapStyle);
- EditorGUI.indentLevel--;
- }
- }
- void DrawDisabledCircle(Rect rect) => DrawCircleIcon(rect,
- Resources.Load<Texture>("icon_circle_gray"),
- Color.clear); // smaller circle draws less attention
- void DrawBlackCircle(Rect rect) => DrawCircleIcon(rect,
- Resources.Load<Texture>("icon_circle_black"),
- new Color(0.14f, 0.14f, 0.14f)); // black is too dark in unity light theme
- void DrawCircleIcon(Rect rect, Texture circleIcon, Color borderColor) {
- // Note: drawing texture from resources is pixelated on the edges, so it has some transperancy around the edges.
- // While building for Android, Resources.Load returns null for our editor Resources.
- if (circleIcon != null) {
- GUI.DrawTexture(rect, circleIcon, ScaleMode.ScaleToFit);
- }
-
- // Draw smooth circle border
- const float borderWidth = 2f;
- GUI.DrawTexture(rect, EditorTextures.White, ScaleMode.ScaleToFit, true,
- 0f,
- borderColor,
- new Vector4(borderWidth, borderWidth, borderWidth, borderWidth),
- Mathf.Min(rect.height, rect.width) / 2f);
- }
- }
- }
|