maint: hotreload updated to 1.13.7

This commit is contained in:
Chris
2026-01-06 22:42:15 -05:00
parent 796dbca5d8
commit 105da8850a
128 changed files with 3538 additions and 738 deletions

View File

@@ -1,10 +1,11 @@
using UnityEditor;
using SingularityGroup.HotReload.Editor.Localization;
using UnityEditor;
namespace SingularityGroup.HotReload.Editor {
internal class AllowAndroidAppToMakeHttpRequestsOption : ProjectOptionBase {
public override string ShortSummary {
get {
return "Allow app to make HTTP requests";
return Translations.Settings.OptionAllowHttpRequests;
}
}
@@ -41,7 +42,7 @@ namespace SingularityGroup.HotReload.Editor {
}
public override void InnerOnGUI(SerializedObject so) {
var description = "For Hot Reload to work on-device, please allow HTTP requests";
var description = Translations.Settings.OptionAllowHttpRequestsDescription;
EditorGUILayout.LabelField(description, HotReloadWindowStyles.WrapStyle);
}
}

View File

@@ -1,20 +1,21 @@
using System;
using System.Threading.Tasks;
using SingularityGroup.HotReload.Editor.Cli;
using SingularityGroup.HotReload.Editor.Localization;
using UnityEditor;
namespace SingularityGroup.HotReload.Editor {
internal sealed class ExposeServerOption : ComputerOptionBase {
public override string ShortSummary => "Allow Devices to Connect";
public override string Summary => "Allow Devices to Connect (WiFi)";
public override string ShortSummary => Translations.Settings.OptionExposeServerShort;
public override string Summary => Translations.Settings.OptionExposeServerFull;
public override void InnerOnGUI() {
string description;
if (GetValue()) {
description = "The HotReload server is reachable from devices on the same Wifi network";
description = Translations.Settings.OptionExposeServerDescriptionEnabled;
} else {
description = "The HotReload server is available to your computer only. Other devices cannot connect to it.";
description = Translations.Settings.OptionExposeServerDescriptionDisabled;
}
EditorGUILayout.LabelField(description, HotReloadWindowStyles.WrapStyle);
}
@@ -38,10 +39,9 @@ namespace SingularityGroup.HotReload.Editor {
RunOnMainThreadSync(() => {
var isRunningResult = ServerHealthCheck.I.IsServerHealthy;
if (isRunningResult) {
var restartServer = EditorUtility.DisplayDialog("Hot Reload",
$"When changing '{Summary}', the Hot Reload server must be restarted for this to take effect." +
"\nDo you want to restart it now?",
"Restart server", "Don't restart");
var restartServer = EditorUtility.DisplayDialog(Translations.Dialogs.DialogTitleHotReload,
string.Format(Translations.Dialogs.DialogMessageRestartExposeServer, Summary),
Translations.Dialogs.DialogButtonRestartServer, Translations.Dialogs.DialogButtonDontRestart);
if (restartServer) {
CodePatcher.I.ClearPatchedMethods();
EditorCodePatcher.RestartCodePatcher().Forget();

View File

@@ -1,10 +1,11 @@
using UnityEditor;
using SingularityGroup.HotReload.Editor.Localization;
using UnityEditor;
namespace SingularityGroup.HotReload.Editor {
internal class IncludeInBuildOption : ProjectOptionBase, ISerializedProjectOption {
static IncludeInBuildOption _I;
public static IncludeInBuildOption I = _I ?? (_I = new IncludeInBuildOption());
public override string ShortSummary => "Include Hot Reload in player builds";
public override string ShortSummary => Translations.Settings.OptionIncludeInBuild;
public override string Summary => ShortSummary;
public override string ObjectPropertyName =>
@@ -13,11 +14,11 @@ namespace SingularityGroup.HotReload.Editor {
public override void InnerOnGUI(SerializedObject so) {
string description;
if (GetValue(so)) {
description = "The Hot Reload runtime is included in development builds that use the Mono scripting backend.";
description = Translations.Settings.OptionIncludeInBuildDescriptionEnabled;
} else {
description = "The Hot Reload runtime will not be included in any build. Use this option to disable HotReload without removing it from your project.";
description = Translations.Settings.OptionIncludeInBuildDescriptionDisabled;
}
description += " This option does not affect Hot Reload usage in Playmode";
description += Translations.Settings.OptionIncludeInBuildDescriptionSuffix;
EditorGUILayout.LabelField(description, HotReloadWindowStyles.WrapStyle);
}
}

View File

@@ -6,6 +6,7 @@ using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using SingularityGroup.HotReload.DTO;
using SingularityGroup.HotReload.Editor.Localization;
using SingularityGroup.HotReload.Newtonsoft.Json;
using UnityEditor;
using UnityEngine;
@@ -44,7 +45,6 @@ namespace SingularityGroup.HotReload.Editor {
const string statusSuccess = "success";
const string statusAlreadyClaimed = "already redeemed by this user/device";
const string unknownError = "We apologize, an error happened while redeeming your license. Please reach out to customer support for assistance.";
private GUILayoutOption[] secondaryButtonLayoutOptions = new[] { GUILayout.MaxWidth(100) };
@@ -64,7 +64,7 @@ namespace SingularityGroup.HotReload.Editor {
}
}
} catch (Exception e) {
Log.Warning($"Failed determining registration outcome with {e.GetType().Name}: {e.Message}");
Log.Warning(Translations.Errors.WarningFailedDeterminingRegistration, e.GetType().Name, e.Message);
}
}
@@ -80,8 +80,8 @@ namespace SingularityGroup.HotReload.Editor {
private void RenderRegistration() {
var message = PackageConst.IsAssetStoreBuild
? "Unity Pro users are required to obtain an additional license. You are eligible to redeem one if your company has ten or fewer employees. Please enter your company details below."
: "The licensing model for Unity Pro users varies depending on the number of employees in your company. Please enter your company details below.";
? Translations.Registration.MessageRegistrationProUsers
: Translations.Registration.MessageRegistrationLicensingModel;
if (error != null) {
EditorGUILayout.HelpBox(error, MessageType.Warning);
} else {
@@ -90,15 +90,15 @@ namespace SingularityGroup.HotReload.Editor {
EditorGUILayout.Space();
EditorGUILayout.Space();
EditorGUILayout.LabelField("Company size (number of employees)");
EditorGUILayout.LabelField(Translations.Common.LabelCompanySize);
GUI.SetNextControlName("company_size");
_pendingCompanySize = EditorGUILayout.TextField(_pendingCompanySize)?.Trim();
EditorGUILayout.Space();
if (GUILayout.Button("Proceed")) {
if (GUILayout.Button(Translations.Common.ButtonProceed)) {
int companySize;
if (!int.TryParse(_pendingCompanySize, out companySize)) {
error = "Please enter a number.";
error = Translations.Errors.ErrorEnterNumber;
} else {
error = null;
HandleRegistration(companySize);
@@ -123,23 +123,23 @@ namespace SingularityGroup.HotReload.Editor {
if (error != null) {
EditorGUILayout.HelpBox(error, MessageType.Warning);
} else {
EditorGUILayout.HelpBox("To enable us to verify your purchase, please enter your invoice number/order ID. Additionally, provide the email address that you intend to use for managing your credentials.", MessageType.Info);
EditorGUILayout.HelpBox(Translations.Registration.MessageRedeemInstructions, MessageType.Info);
}
EditorGUILayout.Space();
EditorGUILayout.Space();
EditorGUILayout.LabelField("Invoice number/Order ID");
EditorGUILayout.LabelField(Translations.Common.LabelInvoiceNumber);
GUI.SetNextControlName("invoice_number");
_pendingInvoiceNumber = EditorGUILayout.TextField(_pendingInvoiceNumber ?? HotReloadPrefs.RedeemLicenseInvoice)?.Trim();
EditorGUILayout.Space();
EditorGUILayout.LabelField("Email");
EditorGUILayout.LabelField(Translations.Common.LabelEmail);
GUI.SetNextControlName("email_redeem");
_pendingRedeemEmail = EditorGUILayout.TextField(_pendingRedeemEmail ?? HotReloadPrefs.RedeemLicenseEmail);
EditorGUILayout.Space();
using (new EditorGUI.DisabledScope(requestingRedeem)) {
if (GUILayout.Button("Redeem", HotReloadRunTab.bigButtonHeight)) {
if (GUILayout.Button(Translations.Common.ButtonRedeem, HotReloadRunTab.bigButtonHeight)) {
RedeemLicense(email: _pendingRedeemEmail, invoiceNumber: _pendingInvoiceNumber).Forget();
}
}
@@ -148,7 +148,7 @@ namespace SingularityGroup.HotReload.Editor {
using (new EditorGUILayout.HorizontalScope()) {
GUILayout.FlexibleSpace();
if (GUILayout.Button("Skip", secondaryButtonLayoutOptions)) {
if (GUILayout.Button(Translations.Common.ButtonSkip, secondaryButtonLayoutOptions)) {
SwitchToStage(RedeemStage.Login);
}
GUILayout.FlexibleSpace();
@@ -158,7 +158,7 @@ namespace SingularityGroup.HotReload.Editor {
async Task RedeemLicense(string email, string invoiceNumber) {
string validationError;
if (string.IsNullOrEmpty(invoiceNumber)) {
validationError = "Please enter invoice number / order ID.";
validationError = Translations.Errors.ErrorEnterInvoiceNumber;
} else {
validationError = HotReloadRunTab.ValidateEmail(email);
}
@@ -170,8 +170,8 @@ namespace SingularityGroup.HotReload.Editor {
status = resp?.status;
if (status != null) {
if (status != statusSuccess && status != statusAlreadyClaimed) {
Log.Error("Redeeming license failed: unknown status received");
error = unknownError;
Log.Error(Translations.Errors.WarningRedeemStatusUnknown);
error = Translations.Registration.UnknownRedeemError;
} else {
HotReloadPrefs.RedeemLicenseEmail = email;
HotReloadPrefs.RedeemLicenseInvoice = invoiceNumber;
@@ -182,31 +182,31 @@ namespace SingularityGroup.HotReload.Editor {
SwitchToStage(RedeemStage.Login);
}
} else if (resp?.error != null) {
Log.Warning($"Redeeming a license failed with error: {resp.error}");
Log.Warning(Translations.Errors.WarningRedeemingLicenseFailed, resp.error);
error = GetPrettyError(resp);
} else {
Log.Warning("Redeeming a license failed: uknown error encountered");
error = unknownError;
Log.Warning(Translations.Errors.WarningRedeemUnknownError);
error = Translations.Registration.UnknownRedeemError;
}
}
string GetPrettyError(RedeemResponse response) {
var err = response?.error;
if (err == null) {
return unknownError;
return Translations.Registration.UnknownRedeemError;
}
if (err.Contains("Invalid email")) {
return "Please enter a valid email address.";
return Translations.Errors.ErrorInvalidEmailAddress;
} else if (err.Contains("License invoice already redeemed")) {
return "The invoice number/order ID you're trying to use has already been applied to redeem a license. Please enter a different invoice number/order ID. If you have already redeemed a license for another email, you may proceed to the next step.";
return Translations.Errors.ErrorLicenseInvoiceRedeemed;
} else if (err.Contains("Different license already redeemed by given email")) {
return "The provided email has already been used to redeem a license. If you have previously redeemed a license, you can proceed to the next step and use your existing credentials. If not, please input a different email address.";
return Translations.Errors.ErrorEmailAlreadyUsed;
} else if (err.Contains("Invoice not found")) {
return "The invoice was not found. Please ensure that you've entered the correct invoice number/order ID.";
return Translations.Errors.ErrorInvoiceNotFound;
} else if (err.Contains("Invoice refunded")) {
return "The purchase has been refunded. Please enter a different invoice number/order ID.";
return Translations.Errors.ErrorInvoiceRefunded;
} else {
return unknownError;
return Translations.Registration.UnknownRedeemError;
}
}
@@ -222,17 +222,17 @@ namespace SingularityGroup.HotReload.Editor {
var content = new StringContent(JsonConvert.SerializeObject(input), Encoding.UTF8, "application/json");
using (var resp = await redeemClient.PostAsync(redeemUrl, content, HotReloadWindow.Current.cancelToken).ConfigureAwait(false)) {
if (resp.StatusCode != HttpStatusCode.OK) {
return new RedeemResponse(null, $"Redeem request failed. Status code: {(int)resp.StatusCode}, reason: {resp.ReasonPhrase}");
return new RedeemResponse(null, string.Format(Translations.Errors.ErrorRedeemRequestFailed, (int)resp.StatusCode, resp.ReasonPhrase));
}
var str = await resp.Content.ReadAsStringAsync().ConfigureAwait(false);
try {
return JsonConvert.DeserializeObject<RedeemResponse>(str);
} catch (Exception ex) {
return new RedeemResponse(null, $"Failed deserializing redeem response with exception: {ex.GetType().Name}: {ex.Message}");
return new RedeemResponse(null, string.Format(Translations.Errors.ErrorFailedDeserializingRedeem, ex.GetType().Name, ex.Message));
}
}
} catch (WebException ex) {
return new RedeemResponse(null, $"Redeeming license failed: WebException encountered {ex.Message}");
return new RedeemResponse(null, string.Format(Translations.Errors.ErrorRedeemingWebException, ex.Message));
} finally {
requestingRedeem = false;
}
@@ -250,9 +250,9 @@ namespace SingularityGroup.HotReload.Editor {
private void RenderLogin(HotReloadRunTabState state) {
if (status == statusSuccess) {
EditorGUILayout.HelpBox("Success! You will receive an email containing your license password shortly. Once you receive it, please enter the received password in the designated field below to complete your registration.", MessageType.Info);
EditorGUILayout.HelpBox(Translations.Registration.MessageRedeemSuccess, MessageType.Info);
} else if (status == statusAlreadyClaimed) {
EditorGUILayout.HelpBox("Your license has already been redeemed. Please enter your existing password below.", MessageType.Info);
EditorGUILayout.HelpBox(Translations.Registration.MessageRedeemAlreadyClaimed, MessageType.Info);
}
EditorGUILayout.Space();
EditorGUILayout.Space();
@@ -263,7 +263,7 @@ namespace SingularityGroup.HotReload.Editor {
using (new EditorGUILayout.HorizontalScope()) {
GUILayout.FlexibleSpace();
if (GUILayout.Button("Go Back", secondaryButtonLayoutOptions)) {
if (GUILayout.Button(Translations.Common.ButtonGoBack, secondaryButtonLayoutOptions)) {
SwitchToStage(RedeemStage.Redeem);
}
GUILayout.FlexibleSpace();

View File

@@ -4,6 +4,7 @@ using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using SingularityGroup.HotReload.Editor.Localization;
using UnityEditor;
using UnityEngine;
using System.Threading.Tasks;
@@ -35,12 +36,12 @@ namespace SingularityGroup.HotReload.Editor {
}
internal class HotReloadAboutTab : HotReloadTabBase {
internal static readonly OpenURLButton seeMore = new OpenURLButton("See More", Constants.ChangelogURL);
internal static readonly OpenDialogueButton manageLicenseButton = new OpenDialogueButton("Manage License", Constants.ManageLicenseURL, "Manage License", "Upgrade/downgrade/edit your subscription and edit payment info.", "Open in browser", "Cancel");
internal static readonly OpenDialogueButton manageAccountButton = new OpenDialogueButton("Manage Account", Constants.ManageAccountURL, "Manage Account", "Login with company code 'naughtycult'. Use the email you signed up with. Your initial password was sent to you by email.", "Open in browser", "Cancel");
internal static readonly OpenURLButton contactButton = new OpenURLButton("Contact", Constants.ContactURL);
internal static readonly OpenURLButton discordButton = new OpenURLButton("Join Discord", Constants.DiscordInviteUrl);
internal static readonly OpenDialogueButton reportIssueButton = new OpenDialogueButton("Report issue", Constants.ReportIssueURL, "Report issue", "Report issue in our public issue tracker. Requires gitlab.com account (if you don't have one and are not willing to make it, please contact us by other means such as our website).", "Open in browser", "Cancel");
internal static readonly OpenURLButton seeMore = new OpenURLButton(Translations.About.ButtonSeeMore, Constants.ChangelogURL);
internal static readonly OpenDialogueButton manageLicenseButton = new OpenDialogueButton(Translations.About.ButtonManageLicense, Constants.ManageLicenseURL, Translations.About.ButtonManageLicense, Translations.Dialogs.DialogManageLicenseMessage, Translations.Common.ButtonOpenInBrowser, Translations.Common.ButtonCancel);
internal static readonly OpenDialogueButton manageAccountButton = new OpenDialogueButton(Translations.About.ButtonManageAccount, Constants.ManageAccountURL, Translations.About.ButtonManageAccount, Translations.Dialogs.DialogManageAccountMessage, Translations.Common.ButtonOpenInBrowser, Translations.Common.ButtonCancel);
internal static readonly OpenURLButton contactButton = new OpenURLButton(Translations.About.ButtonContact, Constants.ContactURL);
internal static readonly OpenURLButton discordButton = new OpenURLButton(Translations.About.ButtonJoinDiscord, Constants.DiscordInviteUrl);
internal static readonly OpenDialogueButton reportIssueButton = new OpenDialogueButton(Translations.About.ButtonReportIssue, Constants.ReportIssueURL, Translations.About.ButtonReportIssue, Translations.Dialogs.DialogReportIssueMessage, Translations.Common.ButtonOpenInBrowser, Translations.Common.ButtonCancel);
private Vector2 _changelogScroll;
private IReadOnlyList<ChangelogVersion> _changelog = new List<ChangelogVersion>();
@@ -88,7 +89,7 @@ namespace SingularityGroup.HotReload.Editor {
}
}
public HotReloadAboutTab(HotReloadWindow window) : base(window, "Help", "_Help", "Info and support for Hot Reload for Unity.") { }
public HotReloadAboutTab(HotReloadWindow window) : base(window, Translations.About.AboutTitle, "_Help", Translations.About.AboutDescription) { }
string GetRelativeDate(DateTime givenDate) {
const int second = 1;
@@ -101,20 +102,20 @@ namespace SingularityGroup.HotReload.Editor {
var delta = Math.Abs(ts.TotalSeconds);
if (delta < 24 * hour)
return "Today";
return Translations.About.AboutToday;
if (delta < 48 * hour)
return "Yesterday";
return Translations.About.AboutYesterday;
if (delta < 30 * day)
return ts.Days + " days ago";
return string.Format(Translations.About.AboutDaysAgo, ts.Days);
if (delta < 12 * month) {
var months = Convert.ToInt32(Math.Floor((double)ts.Days / 30));
return months <= 1 ? "one month ago" : months + " months ago";
return months <= 1 ? Translations.About.AboutOneMonthAgo : string.Format(Translations.About.AboutMonthsAgo, months);
}
var years = Convert.ToInt32(Math.Floor((double)ts.Days / 365));
return years <= 1 ? "one year ago" : years + " years ago";
return years <= 1 ? Translations.About.AboutOneYearAgo : string.Format(Translations.About.AboutYearsAgo, years);
}
void RenderVersion(ChangelogVersion version) {
@@ -130,7 +131,7 @@ namespace SingularityGroup.HotReload.Editor {
//features
if (version.features != null) {
EditorGUILayout.TextArea("Features:", HotReloadWindowStyles.H2TitleStyle);
EditorGUILayout.TextArea(Translations.About.AboutFeatures, HotReloadWindowStyles.H2TitleStyle);
tempTextString = "";
foreach (var feature in version.features) {
tempTextString += "• " + feature + "\n";
@@ -140,7 +141,7 @@ namespace SingularityGroup.HotReload.Editor {
//improvements
if (version.improvements != null) {
EditorGUILayout.TextArea("Improvements:", HotReloadWindowStyles.H2TitleStyle);
EditorGUILayout.TextArea(Translations.About.AboutImprovements, HotReloadWindowStyles.H2TitleStyle);
tempTextString = "";
foreach (var improvement in version.improvements) {
tempTextString += "• " + improvement + "\n";
@@ -150,7 +151,7 @@ namespace SingularityGroup.HotReload.Editor {
//fixes
if (version.fixes != null) {
EditorGUILayout.TextArea("Fixes:", HotReloadWindowStyles.H2TitleStyle);
EditorGUILayout.TextArea(Translations.About.AboutFixes, HotReloadWindowStyles.H2TitleStyle);
tempTextString = "";
foreach (var fix in version.fixes) {
tempTextString += "• " + fix + "\n";
@@ -170,7 +171,7 @@ namespace SingularityGroup.HotReload.Editor {
FetchChangelog().Forget();
using (new EditorGUILayout.HorizontalScope(HotReloadWindowStyles.SectionInnerBoxWide)) {
using (new EditorGUILayout.VerticalScope()) {
HotReloadPrefs.ShowChangeLog = EditorGUILayout.Foldout(HotReloadPrefs.ShowChangeLog, "Changelog", true, HotReloadWindowStyles.FoldoutStyle);
HotReloadPrefs.ShowChangeLog = EditorGUILayout.Foldout(HotReloadPrefs.ShowChangeLog, Translations.Miscellaneous.ChangelogTitle, true, HotReloadWindowStyles.FoldoutStyle);
if (!HotReloadPrefs.ShowChangeLog) {
return;
}
@@ -224,7 +225,7 @@ namespace SingularityGroup.HotReload.Editor {
RenderLogButtons();
EditorGUILayout.Space();
EditorGUILayout.HelpBox($" Hot Reload version {PackageConst.Version}. ", MessageType.Info);
EditorGUILayout.HelpBox(string.Format(Translations.About.AboutVersionInfo, PackageConst.Version), MessageType.Info);
EditorGUILayout.Space();
RenderHelpButtons();
@@ -248,7 +249,7 @@ namespace SingularityGroup.HotReload.Editor {
var buttonHeight = 19;
var bigButtonRect = new Rect(labelRect.x + 3, labelRect.y + 5, labelRect.width - 6, buttonHeight);
OpenURLButton.RenderRaw(bigButtonRect, "Documentation", Constants.DocumentationURL, HotReloadWindowStyles.HelpTabButton);
OpenURLButton.RenderRaw(bigButtonRect, Translations.About.ButtonDocumentation, Constants.DocumentationURL, HotReloadWindowStyles.HelpTabButton);
var firstLayerX = bigButtonRect.x;
var firstLayerY = bigButtonRect.y + buttonHeight + 3;
@@ -260,7 +261,7 @@ namespace SingularityGroup.HotReload.Editor {
using (new EditorGUILayout.HorizontalScope()) {
OpenURLButton.RenderRaw(new Rect { x = firstLayerX, y = firstLayerY, width = firstLayerWidth, height = buttonHeight }, contactButton.text, contactButton.url, HotReloadWindowStyles.HelpTabButton);
OpenURLButton.RenderRaw(new Rect { x = secondLayerX, y = firstLayerY, width = secondLayerWidth, height = buttonHeight }, "Unity Forum", Constants.ForumURL, HotReloadWindowStyles.HelpTabButton);
OpenURLButton.RenderRaw(new Rect { x = secondLayerX, y = firstLayerY, width = secondLayerWidth, height = buttonHeight }, Translations.About.ButtonUnityForum, Constants.ForumURL, HotReloadWindowStyles.HelpTabButton);
}
using (new EditorGUILayout.HorizontalScope()) {
OpenDialogueButton.RenderRaw(rect: new Rect { x = firstLayerX, y = secondLayerY, width = firstLayerWidth, height = buttonHeight }, text: reportIssueButton.text, url: reportIssueButton.url, title: reportIssueButton.title, message: reportIssueButton.message, ok: reportIssueButton.ok, cancel: reportIssueButton.cancel, style: HotReloadWindowStyles.HelpTabButton);
@@ -276,31 +277,32 @@ namespace SingularityGroup.HotReload.Editor {
EditorGUILayout.Space();
EditorGUILayout.BeginHorizontal();
GUILayout.FlexibleSpace();
if (GUILayout.Button("Open Log File")) {
if (GUILayout.Button(Translations.Common.ButtonOpenLogFile)) {
var mostRecentFile = LogsHelper.FindRecentLog(logsPath);
if (mostRecentFile == null) {
Log.Info("No logs found");
Log.Info(Translations.About.LogNoLogsFound);
} else {
try {
Process.Start($"\"{Path.Combine(logsPath, mostRecentFile)}\"");
} catch (Win32Exception e) {
// TODO: is this the same for chinese?
if (e.Message.Contains("Application not found")) {
try {
Process.Start("notepad.exe", $"\"{Path.Combine(logsPath, mostRecentFile)}\"");
} catch {
// Fallback to opening folder with all logs
Process.Start($"\"{logsPath}\"");
Log.Info("Failed opening log file.");
Log.Info(Translations.About.LogFailedOpeningLogFile);
}
}
} catch {
// Fallback to opening folder with all logs
Process.Start($"\"{logsPath}\"");
Log.Info("Failed opening log file.");
Log.Info(Translations.About.LogFailedOpeningLogFile);
}
}
}
if (GUILayout.Button("Browse all logs")) {
if (GUILayout.Button(Translations.Common.ButtonBrowseAllLogs)) {
Process.Start($"\"{logsPath}\"");
}
EditorGUILayout.EndHorizontal();

View File

@@ -1,5 +1,6 @@
using UnityEditor;
using UnityEngine;
using SingularityGroup.HotReload.Editor.Localization;
namespace SingularityGroup.HotReload.Editor {
internal class HotReloadOptionsSection {
@@ -23,7 +24,7 @@ namespace SingularityGroup.HotReload.Editor {
// This does not save the asset, user has to do that by saving assets in Unity (e.g. press hotkey Ctrl + S)
var target = so.targetObject as HotReloadSettingsObject;
if (target == null) {
Log.Warning("Unexpected problem unable to save HotReloadSettingsObject");
Log.Warning(Translations.Errors.WarningUnexpectedSaveProblem);
} else {
// when one of the project options changed then we ensure the asset file exists.
HotReloadSettingsEditor.EnsureSettingsCreated(target);

View File

@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.IO;
using SingularityGroup.HotReload.DTO;
using SingularityGroup.HotReload.EditorDependencies;
using SingularityGroup.HotReload.Editor.Localization;
using UnityEditor;
using UnityEditor.Compilation;
using UnityEngine;
@@ -51,12 +52,12 @@ namespace SingularityGroup.HotReload.Editor {
} catch {
// ignore
}
fileName = fileName ?? "Tap to show stacktrace";
fileName = fileName ?? Translations.UI.TapToShowStacktrace;
// Get the error
string error = (errorString.Contains("error CS")
? "Compile error, "
: "Unsupported change detected, ") + "tap here to see more.";
? Translations.UI.CompileErrorMessage + ", "
: Translations.UI.UnsupportedChangeMessage + ", ") + Translations.UI.TapHereToSeeMore;
int endOfError = errorString.IndexOf(". in ", StringComparison.Ordinal);
string specialChars = "\"'/\\";
char[] characters = specialChars.ToCharArray();
@@ -258,7 +259,7 @@ namespace SingularityGroup.HotReload.Editor {
private MessageType promoCodeErrorType;
private bool promoCodeActivatedThisSession;
public HotReloadRunTab(HotReloadWindow window) : base(window, "Run", "forward", "Run and monitor the current Hot Reload session.") { }
public HotReloadRunTab(HotReloadWindow window) : base(window, Translations.UI.RunTabTitle, "forward", Translations.UI.RunTabTooltip) { }
public override void OnGUI() {
using(new EditorGUILayout.VerticalScope()) {
@@ -405,7 +406,7 @@ namespace SingularityGroup.HotReload.Editor {
GUI.Label(startRect, new GUIContent(title, icon), style);
}
bool clickableDescription = (alertEntry.title == "Unsupported change" || alertEntry.title == "Compile error" || alertEntry.title == "Failed applying patch to method") && alertEntry.alertData.alertEntryType != AlertEntryType.InlinedMethod;
bool clickableDescription = (alertEntry.title == Translations.Utility.UnsupportedChange || alertEntry.title == Translations.Utility.CompileError || alertEntry.title == Translations.Timeline.EventTitleFailedApplyingPatch) && alertEntry.alertData.alertEntryType != AlertEntryType.InlinedMethod;
if (HotReloadTimelineHelper.expandedEntries.Contains(alertEntry) || alertEntry.alertType == AlertType.CompileError) {
using (new EditorGUILayout.VerticalScope()) {
@@ -504,7 +505,7 @@ namespace SingularityGroup.HotReload.Editor {
using (new EditorGUILayout.VerticalScope()) {
HotReloadPrefs.RunTabEventsSuggestionsFoldout = EditorGUILayout.Foldout(HotReloadPrefs.RunTabEventsSuggestionsFoldout, "", true, HotReloadWindowStyles.CustomFoldoutStyle);
GUILayout.Space(-23);
if (GUILayout.Button($"Suggestions ({currentState.suggestionCount.ToString()})", HotReloadWindowStyles.ClickableLabelBoldStyle, GUILayout.Height(27))) {
if (GUILayout.Button(string.Format(Translations.Timeline.LabelSuggestionsFormat, currentState.suggestionCount.ToString()), HotReloadWindowStyles.ClickableLabelBoldStyle, GUILayout.Height(27))) {
HotReloadPrefs.RunTabEventsSuggestionsFoldout = !HotReloadPrefs.RunTabEventsSuggestionsFoldout;
}
if (HotReloadPrefs.RunTabEventsSuggestionsFoldout) {
@@ -521,7 +522,7 @@ namespace SingularityGroup.HotReload.Editor {
using (new EditorGUILayout.VerticalScope()) {
HotReloadPrefs.RunTabEventsTimelineFoldout = EditorGUILayout.Foldout(HotReloadPrefs.RunTabEventsTimelineFoldout, "", true, HotReloadWindowStyles.CustomFoldoutStyle);
GUILayout.Space(-23);
if (GUILayout.Button("Timeline", HotReloadWindowStyles.ClickableLabelBoldStyle, timelineButtonOptions)) {
if (GUILayout.Button(Translations.Timeline.LabelTimeline, HotReloadWindowStyles.ClickableLabelBoldStyle, timelineButtonOptions)) {
HotReloadPrefs.RunTabEventsTimelineFoldout = !HotReloadPrefs.RunTabEventsTimelineFoldout;
}
if (HotReloadPrefs.RunTabEventsTimelineFoldout) {
@@ -534,20 +535,20 @@ namespace SingularityGroup.HotReload.Editor {
GUILayout.Space(2f);
string text;
if (currentState.redeemStage != RedeemStage.None) {
text = "Complete registration before using Hot Reload";
text = Translations.Timeline.MessageCompleteRegistration;
} else if (!currentState.running) {
text = "Use the Start button to activate Hot Reload";
text = Translations.Timeline.MessageUseStartButton;
} else if (enabledFilters.Count < 4 && HotReloadTimelineHelper.EventsTimeline.Count != 0) {
text = "Enable filters to see events";
text = Translations.Timeline.MessageEnableFilters;
} else {
text = "Make code changes to see events";
text = Translations.Timeline.MessageMakeCodeChanges;
}
GUILayout.Label(text, HotReloadWindowStyles.EmptyListText);
}
GUILayout.FlexibleSpace();
} else {
GUILayout.FlexibleSpace();
if (HotReloadTimelineHelper.EventsTimeline.Count > 0 && GUILayout.Button("Clear")) {
if (HotReloadTimelineHelper.EventsTimeline.Count > 0 && GUILayout.Button(Translations.Common.ButtonClear)) {
HotReloadTimelineHelper.ClearEntries();
if (HotReloadWindow.Current) {
HotReloadWindow.Current.Repaint();
@@ -573,23 +574,27 @@ namespace SingularityGroup.HotReload.Editor {
}
EditorGUILayout.Space();
EditorGUILayout.LabelField($"Hot Reload Limited", HotReloadWindowStyles.H3CenteredTitleStyle);
EditorGUILayout.LabelField(Translations.License.TitleHotReloadLimited, HotReloadWindowStyles.H3CenteredTitleStyle);
EditorGUILayout.Space();
if (loginStatus.consumptionsUnavailableReason == ConsumptionsUnavailableReason.NetworkUnreachable) {
EditorGUILayout.HelpBox("Something went wrong. Please check your internet connection.", MessageType.Warning);
EditorGUILayout.HelpBox(Translations.Errors.ErrorNetworkIssue, MessageType.Warning);
} else if (loginStatus.consumptionsUnavailableReason == ConsumptionsUnavailableReason.UnrecoverableError) {
EditorGUILayout.HelpBox("Something went wrong. Please contact support if the issue persists.", MessageType.Error);
EditorGUILayout.HelpBox(Translations.Errors.ErrorContactSupport, MessageType.Error);
} else if (loginStatus.freeSessionFinished) {
var now = DateTime.UtcNow;
var sessionRefreshesAt = (now.AddDays(1).Date - now).Add(TimeSpan.FromMinutes(5));
var sessionRefreshString = $"Next Session: {(sessionRefreshesAt.Hours > 0 ? $"{sessionRefreshesAt.Hours}h " : "")}{sessionRefreshesAt.Minutes}min";
var sessionRefreshString = sessionRefreshesAt.Hours > 0 ?
string.Format(Translations.Miscellaneous.DailySessionNextSessionHours, sessionRefreshesAt.Hours, sessionRefreshesAt.Minutes) :
string.Format(Translations.Miscellaneous.DailySessionNextSessionMinutes, sessionRefreshesAt.Minutes);
HotReloadGUIHelper.HelpBox(sessionRefreshString, MessageType.Warning, fontSize: 11);
} else if (loginStatus.freeSessionRunning && loginStatus.freeSessionEndTime != null) {
var sessionEndsAt = loginStatus.freeSessionEndTime.Value - DateTime.Now;
var sessionString = $"Daily Session: {(sessionEndsAt.Hours > 0 ? $"{sessionEndsAt.Hours}h " : "")}{sessionEndsAt.Minutes}min Left";
var sessionString = sessionEndsAt.Hours > 0 ?
string.Format(Translations.Miscellaneous.DailySessionTimeHoursLeft, sessionEndsAt.Hours, sessionEndsAt.Minutes) :
string.Format(Translations.Miscellaneous.DailySessionTimeMinutesLeft, sessionEndsAt.Minutes);
HotReloadGUIHelper.HelpBox(sessionString, MessageType.Info, fontSize: 11);
} else if (loginStatus.freeSessionEndTime == null) {
HotReloadGUIHelper.HelpBox("Daily Session: Make code changes to start", MessageType.Info, fontSize: 11);
HotReloadGUIHelper.HelpBox(Translations.Miscellaneous.DailySessionStart, MessageType.Info, fontSize: 11);
}
}
@@ -645,7 +650,7 @@ namespace SingularityGroup.HotReload.Editor {
}
private void RenderRecompileButton() {
string recompileText = HotReloadWindowStyles.windowScreenWidth > Constants.RecompileButtonTextHideWidth ? " Recompile" : "";
string recompileText = HotReloadWindowStyles.windowScreenWidth > Constants.RecompileButtonTextHideWidth ? Translations.UI.RecompileButtonLabel : "";
var recompileButton = new GUIContent(recompileText, GUIHelper.GetInvertibleIcon(InvertibleIcon.Recompile));
if (!GUILayout.Button(recompileButton, HotReloadWindowStyles.RecompileButton)) {
return;
@@ -656,15 +661,15 @@ namespace SingularityGroup.HotReload.Editor {
public static void RecompileWithChecks() {
var firstDialoguePass = HotReloadPrefs.RecompileDialogueShown
|| EditorUtility.DisplayDialog(
title: "Hot Reload auto-applies changes",
message: "Using the Recompile button is only necessary when Hot Reload fails to apply your changes. \n\nDo you wish to proceed?",
ok: "Recompile",
cancel: "Not now");
title: Translations.Dialogs.DialogTitleRecompile,
message: Translations.Dialogs.DialogMessageRecompile,
ok: Translations.Common.ButtonRecompile.Trim(),
cancel: Translations.Common.ButtonNotNow);
HotReloadPrefs.RecompileDialogueShown = true;
if (!firstDialoguePass) {
return;
}
if (!ConfirmExitPlaymode("Using the Recompile button will stop Play Mode.\n\nDo you wish to proceed?")) {
if (!ConfirmExitPlaymode(Translations.Dialogs.DialogMessageStopPlayMode)) {
return;
}
Recompile();
@@ -681,10 +686,10 @@ namespace SingularityGroup.HotReload.Editor {
public static bool ConfirmExitPlaymode(string message) {
return !Application.isPlaying
|| EditorUtility.DisplayDialog(
title: "Stop Play Mode and Recompile?",
title: Translations.Dialogs.DialogTitleStopPlayMode,
message: message,
ok: "Stop and Recompile",
cancel: "Cancel");
ok: Translations.Common.ButtonStopAndRecompile,
cancel: Translations.Common.ButtonCancel);
}
public static bool recompiling;
@@ -708,7 +713,7 @@ namespace SingularityGroup.HotReload.Editor {
}
if (!currentState.running && (currentState.startupProgress?.Item1 ?? 0) == 0) {
string startText = HotReloadWindowStyles.windowScreenWidth > Constants.StartButtonTextHideWidth ? " Start" : "";
string startText = HotReloadWindowStyles.windowScreenWidth > Constants.StartButtonTextHideWidth ? Translations.UI.StartButtonLabel : "";
if (GUILayout.Button(new GUIContent(startText, GUIHelper.GetInvertibleIcon(InvertibleIcon.Start)), HotReloadWindowStyles.StartButton)) {
EditorCodePatcher.DownloadAndRun().Forget();
}
@@ -716,7 +721,7 @@ namespace SingularityGroup.HotReload.Editor {
if (HotReloadWindowStyles.windowScreenWidth > 150) {
RenderRecompileButton();
}
string stopText = HotReloadWindowStyles.windowScreenWidth > Constants.StartButtonTextHideWidth ? " Stop" : "";
string stopText = HotReloadWindowStyles.windowScreenWidth > Constants.StartButtonTextHideWidth ? Translations.UI.StopButtonLabel : "";
if (GUILayout.Button(new GUIContent(stopText, GUIHelper.GetInvertibleIcon(InvertibleIcon.Stop)), HotReloadWindowStyles.StopButton)) {
if (!EditorCodePatcher.StoppedServerRecently()) {
EditorCodePatcher.StopCodePatcher().Forget();
@@ -818,15 +823,15 @@ namespace SingularityGroup.HotReload.Editor {
messageType = !loginStatus.freeSessionFinished ? MessageType.Warning : MessageType.Error;
message = GetMessageFromError(currentState, loginStatus.lastLicenseError);
} else if (loginStatus.isTrial && !PackageConst.IsAssetStoreBuild) {
message = $"Using Trial license, valid until {loginStatus.licenseExpiresAt.ToShortDateString()}";
message = string.Format(Translations.UI.TrialLicenseMessage, loginStatus.licenseExpiresAt.ToShortDateString());
messageType = MessageType.Info;
} else if (loginStatus.isIndieLicense) {
if (verbose) {
message = " Indie license active";
message = Translations.UI.IndieLicenseMessage;
messageType = MessageType.Info;
customGUI = () => {
if (loginStatus.licenseExpiresAt.Date != DateTime.MaxValue.Date) {
EditorGUILayout.LabelField($"License will renew on {loginStatus.licenseExpiresAt.ToShortDateString()}.");
EditorGUILayout.LabelField(string.Format(Translations.UI.LicenseRenewalMessage, loginStatus.licenseExpiresAt.ToShortDateString()));
EditorGUILayout.Space();
}
using (new GUILayout.HorizontalScope()) {
@@ -842,7 +847,7 @@ namespace SingularityGroup.HotReload.Editor {
}
} else if (loginStatus.isBusinessLicense) {
if (verbose) {
message = " Business license active";
message = Translations.UI.BusinessLicenseMessage;
messageType = MessageType.Info;
if (businessLicenseContent == null) {
businessLicenseContent = new GUIContent(message, EditorGUIUtility.FindTexture("TestPassed"));
@@ -870,7 +875,7 @@ namespace SingularityGroup.HotReload.Editor {
style.fixedHeight = GUILayoutUtility.GetLastRect().height;
}
if (allowHide) {
if (GUILayout.Button("Hide", style)) {
if (GUILayout.Button(Translations.Common.ButtonHide, style)) {
HotReloadPrefs.ErrorHidden = true;
}
}
@@ -886,71 +891,58 @@ namespace SingularityGroup.HotReload.Editor {
}
}
const string assetStoreProInfo = "Unity Pro/Enterprise users from company with your number of employees require a Business license. Please upgrade your license on our website.";
internal static void RenderBusinessLicenseInfo(GUIStyle style) {
GUILayout.Space(8);
using (new EditorGUILayout.HorizontalScope()) {
EditorGUILayout.HelpBox(assetStoreProInfo, MessageType.Info);
EditorGUILayout.HelpBox(Translations.License.LicenseErrorAssetStorePro, MessageType.Info);
if (Event.current.type == EventType.Repaint) {
style.fixedHeight = GUILayoutUtility.GetLastRect().height;
}
if (GUILayout.Button("Upgrade", style)) {
if (GUILayout.Button(Translations.Common.ButtonUpgrade, style)) {
Application.OpenURL(Constants.ProductPurchaseBusinessURL);
}
}
}
internal static void RenderIndieLicenseInfo(GUIStyle style) {
string message;
if (EditorCodePatcher.licenseType == UnityLicenseType.UnityPersonalPlus) {
message = "Unity Plus users require an Indie license. Please upgrade your license on our website.";
} else if (EditorCodePatcher.licenseType == UnityLicenseType.UnityPro) {
message = "Unity Pro/Enterprise users from company with your number of employees require an Indie license. Please upgrade your license on our website.";
} else {
return;
}
GUILayout.Space(8);
using (new EditorGUILayout.HorizontalScope()) {
EditorGUILayout.HelpBox(message, MessageType.Info);
EditorGUILayout.HelpBox(Translations.License.LicenseErrorUnityPlusIndie, MessageType.Info);
if (Event.current.type == EventType.Repaint) {
style.fixedHeight = GUILayoutUtility.GetLastRect().height;
}
if (GUILayout.Button("Upgrade", style)) {
if (GUILayout.Button(Translations.Common.ButtonUpgrade, style)) {
Application.OpenURL(Constants.ProductPurchaseURL);
}
}
}
const string GetLicense = "Get License";
const string ContactSupport = "Contact Support";
const string UpgradeLicense = "Upgrade License";
const string ManageLicense = "Manage License";
internal static Dictionary<string, LicenseErrorData> _licenseErrorData;
internal static Dictionary<string, LicenseErrorData> LicenseErrorData => _licenseErrorData ?? (_licenseErrorData = new Dictionary<string, LicenseErrorData> {
{ "DeviceNotLicensedException", new LicenseErrorData(description: "Another device is using your license. Please reach out to customer support for assistance.", showSupportButton: true, supportButtonText: ContactSupport) },
{ "DeviceBlacklistedException", new LicenseErrorData(description: "You device has been blacklisted.") },
{ "DateHeaderInvalidException", new LicenseErrorData(description: $"Your license is not working because your computer's clock is incorrect. Please set the clock to the correct time to restore your license.") },
{ "DateTimeCheatingException", new LicenseErrorData(description: $"Your license is not working because your computer's clock is incorrect. Please set the clock to the correct time to restore your license.") },
{ "LicenseActivationException", new LicenseErrorData(description: "An error has occured while activating your license. Please contact customer support for assistance.", showSupportButton: true, supportButtonText: ContactSupport) },
{ "LicenseDeletedException", new LicenseErrorData(description: $"Your license has been deleted. Please contact customer support for assistance.", showBuyButton: true, buyButtonText: GetLicense, showSupportButton: true, supportButtonText: ContactSupport) },
{ "LicenseDisabledException", new LicenseErrorData(description: $"Your license has been disabled. Please contact customer support for assistance.", showBuyButton: true, buyButtonText: GetLicense, showSupportButton: true, supportButtonText: ContactSupport) },
{ "LicenseExpiredException", new LicenseErrorData(description: $"Your license has expired. Please renew your license subscription using the 'Upgrade License' button below and login with your email/password to activate your license.", showBuyButton: true, buyButtonText: UpgradeLicense, showManageLicenseButton: true, manageLicenseButtonText: ManageLicense) },
{ "LicenseInactiveException", new LicenseErrorData(description: $"Your license is currenty inactive. Please login with your email/password to activate your license.") },
{ "LocalLicenseException", new LicenseErrorData(description: $"Your license file was damaged or corrupted. Please login with your email/password to refresh your license file.") },
{ "DeviceNotLicensedException", new LicenseErrorData(description: Translations.License.LicenseErrorDeviceInUse, showSupportButton: true, supportButtonText: Translations.License.LicenseButtonContactSupport) },
{ "DeviceBlacklistedException", new LicenseErrorData(description: Translations.License.LicenseErrorDeviceBlacklisted) },
{ "DateHeaderInvalidException", new LicenseErrorData(description: Translations.License.LicenseErrorIncorrectClock) },
{ "DateTimeCheatingException", new LicenseErrorData(description: Translations.License.LicenseErrorIncorrectClock) },
{ "LicenseActivationException", new LicenseErrorData(description: Translations.License.LicenseErrorActivation, showSupportButton: true, supportButtonText: Translations.License.LicenseButtonContactSupport) },
{ "LicenseDeletedException", new LicenseErrorData(description: Translations.License.LicenseErrorDeleted, showBuyButton: true, buyButtonText: Translations.License.LicenseButtonGetLicense, showSupportButton: true, supportButtonText: Translations.License.LicenseButtonContactSupport) },
{ "LicenseDisabledException", new LicenseErrorData(description: Translations.License.LicenseErrorDisabled, showBuyButton: true, buyButtonText: Translations.License.LicenseButtonGetLicense, showSupportButton: true, supportButtonText: Translations.License.LicenseButtonContactSupport) },
{ "LicenseExpiredException", new LicenseErrorData(description: Translations.License.LicenseErrorExpired, showBuyButton: true, buyButtonText: Translations.License.LicenseButtonUpgradeLicense, showManageLicenseButton: true, manageLicenseButtonText: Translations.License.LicenseButtonManageLicense) },
{ "LicenseInactiveException", new LicenseErrorData(description: Translations.License.LicenseErrorInactive) },
{ "LocalLicenseException", new LicenseErrorData(description: Translations.License.LicenseErrorCorrupted) },
// Note: obsolete
{ "MissingParametersException", new LicenseErrorData(description: "An account already exists for this device. Please login with your existing email/password.", showBuyButton: true, buyButtonText: GetLicense) },
{ "NetworkException", new LicenseErrorData(description: "There is an issue connecting to our servers. Please check your internet connection or contact customer support if the issue persists.", showSupportButton: true, supportButtonText: ContactSupport) },
{ "TrialLicenseExpiredException", new LicenseErrorData(description: $"Your trial has expired. Activate a license with unlimited usage or continue using the Free version. View available plans on our website.", showBuyButton: true, buyButtonText: UpgradeLicense) },
{ "InvalidCredentialException", new LicenseErrorData(description: "Incorrect email/password. You can find your initial password in the sign-up email.") },
{ "MissingParametersException", new LicenseErrorData(description: "An account already exists for this device. Please login with your existing email/password.", showBuyButton: true, buyButtonText: Translations.License.LicenseButtonGetLicense) },
{ "NetworkException", new LicenseErrorData(description: Translations.License.LicenseErrorNetwork, showSupportButton: true, supportButtonText: Translations.License.LicenseButtonContactSupport) },
{ "TrialLicenseExpiredException", new LicenseErrorData(description: Translations.License.LicenseErrorTrialExpired, showBuyButton: true, buyButtonText: Translations.License.LicenseButtonUpgradeLicense) },
{ "InvalidCredentialException", new LicenseErrorData(description: Translations.License.LicenseErrorInvalidCredentials) },
// Note: activating free trial with email is not supported anymore. This error shouldn't happen which is why we should rather user the fallback
// { "LicenseNotFoundException", new LicenseErrorData(description: "The account you're trying to access doesn't seem to exist yet. Please enter your email address to create a new account and receive a trial license.", showLoginButton: true, loginButtonText: CreateAccount) },
{ "LicenseIncompatibleException", new LicenseErrorData(description: "Please upgrade your license to continue using hotreload with Unity Pro.", showManageLicenseButton: true, manageLicenseButtonText: ManageLicense) },
{ "LicenseIncompatibleException", new LicenseErrorData(description: Translations.License.LicenseErrorIncompatible, showManageLicenseButton: true, manageLicenseButtonText: Translations.License.LicenseButtonManageLicense) },
});
internal static LicenseErrorData defaultLicenseErrorData = new LicenseErrorData(description: "We apologize, an error happened while verifying your license. Please reach out to customer support for assistance.", showSupportButton: true, supportButtonText: ContactSupport);
internal static LicenseErrorData defaultLicenseErrorData = new LicenseErrorData(description: Translations.License.LicenseErrorDefault, showSupportButton: true, supportButtonText: Translations.License.LicenseButtonContactSupport);
internal static string GetMessageFromError(HotReloadRunTabState currentState, string error) {
if (PackageConst.IsAssetStoreBuild && error == "TrialLicenseExpiredException") {
return assetStoreProInfo;
return Translations.License.LicenseErrorAssetStorePro;
}
return GetLicenseErrorDataOrDefault(currentState, error).description;
}
@@ -960,7 +952,7 @@ namespace SingularityGroup.HotReload.Editor {
return default(LicenseErrorData);
}
if (currentState.loginStatus == null || string.IsNullOrEmpty(error) && (!currentState.loginStatus.isLicensed || currentState.loginStatus.isTrial)) {
return new LicenseErrorData(null, showBuyButton: true, buyButtonText: GetLicense);
return new LicenseErrorData(null, showBuyButton: true, buyButtonText: Translations.License.LicenseButtonGetLicense);
}
if (string.IsNullOrEmpty(error)) {
return default(LicenseErrorData);
@@ -1001,7 +993,7 @@ namespace SingularityGroup.HotReload.Editor {
}
internal static void RenderLicenseInfo(HotReloadRunTabState currentState, LoginStatusResponse loginStatus, bool verbose = false, bool allowHide = true, string overrideActionButton = null, bool showConsumptions = false) {
HotReloadPrefs.ShowLogin = EditorGUILayout.Foldout(HotReloadPrefs.ShowLogin, "Hot Reload License", true, HotReloadWindowStyles.FoldoutStyle);
HotReloadPrefs.ShowLogin = EditorGUILayout.Foldout(HotReloadPrefs.ShowLogin, Translations.License.TitleHotReloadLicense, true, HotReloadWindowStyles.FoldoutStyle);
if (HotReloadPrefs.ShowLogin) {
EditorGUILayout.Space();
if ((loginStatus?.isLicensed != true && showConsumptions) && !(loginStatus == null || loginStatus.isFree)) {
@@ -1017,22 +1009,22 @@ namespace SingularityGroup.HotReload.Editor {
}
internal void RenderPromoCodes() {
HotReloadPrefs.ShowPromoCodes = EditorGUILayout.Foldout(HotReloadPrefs.ShowPromoCodes, "Promo Codes", true, HotReloadWindowStyles.FoldoutStyle);
HotReloadPrefs.ShowPromoCodes = EditorGUILayout.Foldout(HotReloadPrefs.ShowPromoCodes, Translations.License.PromoCodesTitle, true, HotReloadWindowStyles.FoldoutStyle);
if (!HotReloadPrefs.ShowPromoCodes) {
return;
}
if (promoCodeActivatedThisSession) {
EditorGUILayout.HelpBox($"Your promo code has been successfully activated. Free trial has been extended by 3 months.", MessageType.Info);
EditorGUILayout.HelpBox(Translations.License.MessagePromoCodeActivated, MessageType.Info);
} else {
if (promoCodeError != null && promoCodeErrorType != MessageType.None) {
EditorGUILayout.HelpBox(promoCodeError, promoCodeErrorType);
}
EditorGUILayout.LabelField("Promo code");
EditorGUILayout.LabelField(Translations.Common.LabelPromoCode);
_pendingPromoCode = EditorGUILayout.TextField(_pendingPromoCode);
EditorGUILayout.Space();
using (new EditorGUI.DisabledScope(_requestingActivatePromoCode)) {
if (GUILayout.Button("Activate promo code", HotReloadRunTab.bigButtonHeight)) {
if (GUILayout.Button(Translations.Common.ButtonActivatePromoCode, HotReloadRunTab.bigButtonHeight)) {
RequestActivatePromoCode().Forget();
}
}
@@ -1083,7 +1075,7 @@ namespace SingularityGroup.HotReload.Editor {
}
string ToPrettyErrorMessage(PromoCodeErrorType errorType) {
var defaultMsg = "We apologize, an error happened while activating your promo code. Please reach out to customer support for assistance.";
var defaultMsg = Translations.Errors.ErrorPromoCodeActivation;
switch (errorType) {
case PromoCodeErrorType.MISSING_INPUT:
case PromoCodeErrorType.INVALID_HTTP_METHOD:
@@ -1094,12 +1086,12 @@ namespace SingularityGroup.HotReload.Editor {
case PromoCodeErrorType.UPDATING_LICENSE_FAILED:
case PromoCodeErrorType.LICENSE_NOT_TRIAL:
return defaultMsg;
case PromoCodeErrorType.PROMO_CODE_NOT_FOUND: return "Your promo code is invalid. Please ensure that you have entered the correct promo code.";
case PromoCodeErrorType.PROMO_CODE_CLAIMED: return "Your promo code has already been used.";
case PromoCodeErrorType.PROMO_CODE_EXPIRED: return "Your promo code has expired.";
case PromoCodeErrorType.LICENSE_ALREADY_EXTENDED: return "Your license has already been activated with a promo code. Only one promo code activation per license is allowed.";
case PromoCodeErrorType.CONDITIONAL_CHECK_FAILED: return "We encountered an error while activating your promo code. Please try again. If the issue persists, please contact our customer support team for assistance.";
case PromoCodeErrorType.NONE: return "There is an issue connecting to our servers. Please check your internet connection or contact customer support if the issue persists.";
case PromoCodeErrorType.PROMO_CODE_NOT_FOUND: return Translations.Errors.ErrorPromoCodeInvalid;
case PromoCodeErrorType.PROMO_CODE_CLAIMED: return Translations.Errors.ErrorPromoCodeUsed;
case PromoCodeErrorType.PROMO_CODE_EXPIRED: return Translations.Errors.ErrorPromoCodeExpired;
case PromoCodeErrorType.LICENSE_ALREADY_EXTENDED: return Translations.Errors.ErrorLicenseExtended;
case PromoCodeErrorType.CONDITIONAL_CHECK_FAILED: return Translations.Errors.ErrorPromoCodeActivation;
case PromoCodeErrorType.NONE: return Translations.Errors.ErrorPromoCodeNetwork;
default: return defaultMsg;
}
}
@@ -1129,12 +1121,12 @@ namespace SingularityGroup.HotReload.Editor {
}
internal static void RenderLicenseInnerPanel(HotReloadRunTabState currentState, string overrideActionButton = null, bool renderLogout = true) {
EditorGUILayout.LabelField("Email");
EditorGUILayout.LabelField(Translations.Common.LabelEmail);
GUI.SetNextControlName("email");
_pendingEmail = EditorGUILayout.TextField(string.IsNullOrEmpty(_pendingEmail) ? HotReloadPrefs.LicenseEmail : _pendingEmail);
_pendingEmail = _pendingEmail.Trim();
EditorGUILayout.LabelField("Password");
EditorGUILayout.LabelField(Translations.Common.LabelPassword);
GUI.SetNextControlName("password");
_pendingPassword = EditorGUILayout.PasswordField(string.IsNullOrEmpty(_pendingPassword) ? HotReloadPrefs.LicensePassword : _pendingPassword);
@@ -1144,7 +1136,7 @@ namespace SingularityGroup.HotReload.Editor {
using(new EditorGUI.DisabledScope(currentState.requestingLoginInfo)) {
var btnLabel = overrideActionButton;
if (String.IsNullOrEmpty(overrideActionButton)) {
btnLabel = "Login";
btnLabel = Translations.Common.ButtonLogin;
}
using (new EditorGUILayout.HorizontalScope()) {
var focusedControl = GUI.GetNameOfFocusedControl();
@@ -1159,7 +1151,7 @@ namespace SingularityGroup.HotReload.Editor {
if (!string.IsNullOrEmpty(error)) {
_activateInfoMessage = new Tuple<string, MessageType>(error, MessageType.Warning);
} else if (string.IsNullOrEmpty(_pendingPassword)) {
_activateInfoMessage = new Tuple<string, MessageType>("Please enter your password.", MessageType.Warning);
_activateInfoMessage = new Tuple<string, MessageType>(Translations.Errors.ErrorEnterPassword, MessageType.Warning);
} else {
HotReloadWindow.Current.SelectTab(typeof(HotReloadRunTab));
@@ -1186,11 +1178,11 @@ namespace SingularityGroup.HotReload.Editor {
public static string ValidateEmail(string email) {
if (string.IsNullOrEmpty(email)) {
return "Please enter your email address.";
return Translations.Errors.ErrorEnterEmail;
} else if (!EditorWindowHelper.IsValidEmailAddress(email)) {
return "Please enter a valid email address.";
return Translations.Errors.ErrorValidEmail;
} else if (email.Contains("+")) {
return "Mail extensions (in a form of 'username+suffix@example.com') are not supported yet. Please provide your original email address (such as 'username@example.com' without '+suffix' part) as we're working on resolving this issue.";
return Translations.Errors.ErrorMailExtensions;
}
return null;
}
@@ -1199,7 +1191,7 @@ namespace SingularityGroup.HotReload.Editor {
if (currentState.loginStatus?.isLicensed != true) {
return;
}
if (GUILayout.Button("Logout", bigButtonHeight)) {
if (GUILayout.Button(Translations.Common.ButtonLogout, bigButtonHeight)) {
HotReloadWindow.Current.SelectTab(typeof(HotReloadRunTab));
if (!EditorCodePatcher.RequestingDownloadAndRun && !EditorCodePatcher.Running) {
LogoutOnDownloadAndRun().Forget();
@@ -1240,8 +1232,8 @@ namespace SingularityGroup.HotReload.Editor {
private static void RenderSwitchAuthMode() {
var color = EditorGUIUtility.isProSkin ? new Color32(0x3F, 0x9F, 0xFF, 0xFF) : new Color32(0x0F, 0x52, 0xD7, 0xFF);
if (HotReloadGUIHelper.LinkLabel("Forgot password?", 12, FontStyle.Normal, TextAnchor.MiddleLeft, color)) {
if (EditorUtility.DisplayDialog("Recover password", "Use company code 'naughtycult' and the email you signed up with in order to recover your account.", "Open in browser", "Cancel")) {
if (HotReloadGUIHelper.LinkLabel(Translations.Miscellaneous.LinkForgotPassword, 12, FontStyle.Normal, TextAnchor.MiddleLeft, color)) {
if (EditorUtility.DisplayDialog(Translations.Dialogs.DialogTitleRecoverPassword, Translations.Dialogs.DialogMessageRecoverPassword, Translations.Common.ButtonOpenInBrowser, Translations.Common.ButtonCancel)) {
Application.OpenURL(Constants.ForgotPasswordURL);
}
}

View File

@@ -2,6 +2,7 @@ using System;
using System.Diagnostics.CodeAnalysis;
using SingularityGroup.HotReload.DTO;
using SingularityGroup.HotReload.Editor.Cli;
using SingularityGroup.HotReload.Editor.Localization;
using UnityEditor;
using UnityEngine;
using EditorGUI = UnityEditor.EditorGUI;
@@ -49,9 +50,9 @@ namespace SingularityGroup.HotReload.Editor {
[SuppressMessage("ReSharper", "Unity.UnknownResource")] // Rider doesn't check packages
public HotReloadSettingsTab(HotReloadWindow window) : base(window,
"Settings",
Translations.Settings.SettingsTitle,
"_Popup",
"Make changes to a build running on-device.") {
Translations.OnDevice.OnDeviceHeadline) {
optionsSection = new HotReloadOptionsSection();
}
@@ -98,7 +99,7 @@ namespace SingularityGroup.HotReload.Editor {
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);
HotReloadPrefs.ShowConfiguration = EditorGUILayout.Foldout(HotReloadPrefs.ShowConfiguration, Translations.Settings.SettingsConfiguration, true, HotReloadWindowStyles.FoldoutStyle);
if (HotReloadPrefs.ShowConfiguration) {
EditorGUILayout.Space();
@@ -111,8 +112,10 @@ namespace SingularityGroup.HotReload.Editor {
RenderAutoRecompileUnsupportedChangesImmediately();
RenderAutoRecompileUnsupportedChangesOnExitPlayMode();
RenderAutoRecompileUnsupportedChangesInPlayMode();
RenderAutoRecompileInspectorFieldEdits();
RenderAutoRecompilePartiallyUnsupportedChanges();
RenderDisplayNewMonobehaviourMethodsAsPartiallySupported();
RenderAutoRecompileUnsupportedChangesInEditMode();
}
}
EditorGUILayout.Space();
@@ -186,12 +189,13 @@ namespace SingularityGroup.HotReload.Editor {
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);
HotReloadPrefs.ShowAdvanced = EditorGUILayout.Foldout(HotReloadPrefs.ShowAdvanced, Translations.Settings.SettingsAdvanced, true, HotReloadWindowStyles.FoldoutStyle);
if (HotReloadPrefs.ShowAdvanced) {
EditorGUILayout.Space();
DeactivateHotReload();
DisableDetailedErrorReporting();
PauseHotReloadInEditMode();
}
}
}
@@ -201,15 +205,15 @@ namespace SingularityGroup.HotReload.Editor {
}
void RenderUnityAutoRefresh() {
var newSettings = EditorGUILayout.BeginToggleGroup(new GUIContent("Manage Unity auto-refresh (recommended)"), HotReloadPrefs.AllowDisableUnityAutoRefresh);
var newSettings = EditorGUILayout.BeginToggleGroup(new GUIContent(Translations.Settings.ToggleManageAutoRefresh), 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";
toggleDescription = Translations.Settings.SettingsManageAutoRefreshOn;
} else {
toggleDescription = "Enabled this setting to auto-manage Unity's Auto Refresh and Script Compilation settings. This reduces unncessary recompiling";
toggleDescription = Translations.Settings.SettingsManageAutoRefreshOff;
}
EditorGUILayout.LabelField(toggleDescription, HotReloadWindowStyles.WrapStyle);
EditorGUILayout.EndToggleGroup();
@@ -217,15 +221,14 @@ namespace SingularityGroup.HotReload.Editor {
}
void RenderAssetRefresh() {
var newSettings = EditorGUILayout.BeginToggleGroup(new GUIContent("Asset refresh (recommended)"), HotReloadPrefs.AllAssetChanges);
var newSettings = EditorGUILayout.BeginToggleGroup(new GUIContent(Translations.Settings.ToggleAssetRefresh), 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");
var restartServer = EditorUtility.DisplayDialog(Translations.Dialogs.DialogTitleRestartServer,
Translations.Dialogs.DialogMessageRestartAssetRefresh,
Translations.Dialogs.DialogButtonRestartHotReload, Translations.Dialogs.DialogButtonDontRestart);
if (restartServer) {
EditorCodePatcher.RestartCodePatcher().Forget();
}
@@ -233,9 +236,9 @@ namespace SingularityGroup.HotReload.Editor {
}
string toggleDescription;
if (HotReloadPrefs.AllAssetChanges) {
toggleDescription = "Hot Reload will refresh changed assets such as sprites, prefabs, etc";
toggleDescription = Translations.Settings.SettingsAssetRefreshOn;
} else {
toggleDescription = "Enable to allow Hot Reload to refresh changed assets in the project. All asset types are supported including sprites, prefabs, shaders etc";
toggleDescription = Translations.Settings.SettingsAssetRefreshOff;
}
EditorGUILayout.LabelField(toggleDescription, HotReloadWindowStyles.WrapStyle);
EditorGUILayout.EndToggleGroup();
@@ -243,16 +246,16 @@ namespace SingularityGroup.HotReload.Editor {
}
void RenderDebuggerCompatibility() {
var newSettings = EditorGUILayout.BeginToggleGroup(new GUIContent("Auto-disable Hot Reload while a debugger is attached (recommended)"), HotReloadPrefs.AutoDisableHotReloadWithDebugger);
var newSettings = EditorGUILayout.BeginToggleGroup(new GUIContent(Translations.Settings.ToggleDebuggerCompatibility), 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.";
toggleDescription = Translations.Settings.SettingsDebuggerCompatibilityOn;
} 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.";
toggleDescription = Translations.Settings.SettingsDebuggerCompatibilityOff;
}
EditorGUILayout.LabelField(toggleDescription, HotReloadWindowStyles.WrapStyle);
EditorGUILayout.EndToggleGroup();
@@ -260,12 +263,12 @@ namespace SingularityGroup.HotReload.Editor {
}
void RenderIncludeShaderChanges() {
HotReloadPrefs.IncludeShaderChanges = EditorGUILayout.BeginToggleGroup(new GUIContent("Refresh shaders"), HotReloadPrefs.IncludeShaderChanges);
HotReloadPrefs.IncludeShaderChanges = EditorGUILayout.BeginToggleGroup(new GUIContent(Translations.Settings.ToggleRefreshShaders), HotReloadPrefs.IncludeShaderChanges);
string toggleDescription;
if (HotReloadPrefs.IncludeShaderChanges) {
toggleDescription = "Hot Reload will auto refresh shaders. Note that enabling this setting might impact performance.";
toggleDescription = Translations.Settings.SettingsRefreshShadersOn;
} else {
toggleDescription = "Enable to auto-refresh shaders. Note that enabling this setting might impact performance";
toggleDescription = Translations.Settings.SettingsRefreshShadersOff;
}
EditorGUILayout.LabelField(toggleDescription, HotReloadWindowStyles.WrapStyle);
EditorGUILayout.EndToggleGroup();
@@ -275,15 +278,14 @@ namespace SingularityGroup.HotReload.Editor {
if (!HotReloadCli.CanOpenInBackground) {
return;
}
var newSettings = EditorGUILayout.BeginToggleGroup(new GUIContent("Hide console window on start"), HotReloadPrefs.DisableConsoleWindow);
var newSettings = EditorGUILayout.BeginToggleGroup(new GUIContent(Translations.Settings.ToggleHideConsole), 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");
var restartServer = EditorUtility.DisplayDialog(Translations.Dialogs.DialogTitleRestartServer,
Translations.Dialogs.DialogMessageRestartConsoleWindow,
Translations.Dialogs.DialogButtonRestartServer, Translations.Dialogs.DialogButtonDontRestart);
if (restartServer) {
EditorCodePatcher.RestartCodePatcher().Forget();
}
@@ -291,9 +293,9 @@ namespace SingularityGroup.HotReload.Editor {
}
string toggleDescription;
if (HotReloadPrefs.DisableConsoleWindow) {
toggleDescription = "Hot Reload will start without creating a console window. Logs can be accessed through \"Help\" tab.";
toggleDescription = Translations.Settings.SettingsHideConsoleOn;
} else {
toggleDescription = "Enable to start Hot Reload without creating a console window.";
toggleDescription = Translations.Settings.SettingsHideConsoleOff;
}
EditorGUILayout.LabelField(toggleDescription, HotReloadWindowStyles.WrapStyle);
EditorGUILayout.EndToggleGroup();
@@ -301,15 +303,15 @@ namespace SingularityGroup.HotReload.Editor {
}
void DeactivateHotReload() {
var newSettings = EditorGUILayout.BeginToggleGroup(new GUIContent("Deactivate Hot Reload"), HotReloadPrefs.DeactivateHotReload);
var newSettings = EditorGUILayout.BeginToggleGroup(new GUIContent(Translations.Settings.ToggleDeactivate), HotReloadPrefs.DeactivateHotReload);
if (newSettings != HotReloadPrefs.DeactivateHotReload) {
DeactivateHotReloadInner(newSettings);
}
string toggleDescription;
if (HotReloadPrefs.DeactivateHotReload) {
toggleDescription = "Hot Reload is deactivated.";
toggleDescription = Translations.Settings.SettingsDeactivatedOn;
} else {
toggleDescription = "Enable to deactivate Hot Reload.";
toggleDescription = Translations.Settings.SettingsDeactivatedOff;
}
EditorGUILayout.LabelField(toggleDescription, HotReloadWindowStyles.WrapStyle);
EditorGUILayout.EndToggleGroup();
@@ -317,13 +319,26 @@ namespace SingularityGroup.HotReload.Editor {
}
void DisableDetailedErrorReporting() {
var newSettings = EditorGUILayout.BeginToggleGroup(new GUIContent("Disable Detailed Error Reporting"), HotReloadPrefs.DisableDetailedErrorReporting);
var newSettings = EditorGUILayout.BeginToggleGroup(new GUIContent(Translations.Settings.ToggleDisableErrorReporting), HotReloadPrefs.DisableDetailedErrorReporting);
DisableDetailedErrorReportingInner(newSettings);
string toggleDescription;
if (HotReloadPrefs.DisableDetailedErrorReporting) {
toggleDescription = "Detailed error reporting is disabled.";
toggleDescription = Translations.Settings.SettingsDisableErrorReportingOn;
} else {
toggleDescription = "Toggle on to disable detailed error reporting.";
toggleDescription = Translations.Settings.SettingsDisableErrorReportingOff;
}
EditorGUILayout.LabelField(toggleDescription, HotReloadWindowStyles.WrapStyle);
EditorGUILayout.EndToggleGroup();
EditorGUILayout.Space(6f);
}
void PauseHotReloadInEditMode() {
HotReloadPrefs.PauseHotReloadInEditMode = EditorGUILayout.BeginToggleGroup(new GUIContent(Translations.Settings.TogglePauseEditMode), HotReloadPrefs.PauseHotReloadInEditMode);
string toggleDescription;
if (HotReloadPrefs.PauseHotReloadInEditMode) {
toggleDescription = Translations.Settings.SettingsPauseEditModeOn;
} else {
toggleDescription = Translations.Settings.SettingsPauseEditModeOff;
}
EditorGUILayout.LabelField(toggleDescription, HotReloadWindowStyles.WrapStyle);
EditorGUILayout.EndToggleGroup();
@@ -337,10 +352,9 @@ namespace SingularityGroup.HotReload.Editor {
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");
var restartServer = EditorUtility.DisplayDialog(Translations.Dialogs.DialogTitleRestartServer,
Translations.Dialogs.DialogMessageRestartErrorReporting,
Translations.Dialogs.DialogButtonRestartServer, Translations.Dialogs.DialogButtonDontRestart);
if (restartServer) {
EditorCodePatcher.RestartCodePatcher().Forget();
}
@@ -348,10 +362,9 @@ namespace SingularityGroup.HotReload.Editor {
}
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");
var confirmed = !deactivate || EditorUtility.DisplayDialog(Translations.Dialogs.DialogTitleDeactivate,
Translations.Dialogs.DialogMessageDeactivate,
Translations.Dialogs.DialogButtonDeactivate, Translations.Common.ButtonCancel);
if (confirmed) {
HotReloadPrefs.DeactivateHotReload = deactivate;
if (deactivate) {
@@ -363,15 +376,15 @@ namespace SingularityGroup.HotReload.Editor {
}
void RenderAutostart() {
var newSettings = EditorGUILayout.BeginToggleGroup(new GUIContent("Autostart on Unity open"), HotReloadPrefs.LaunchOnEditorStart);
var newSettings = EditorGUILayout.BeginToggleGroup(new GUIContent(Translations.Settings.ToggleAutostart), HotReloadPrefs.LaunchOnEditorStart);
if (newSettings != HotReloadPrefs.LaunchOnEditorStart) {
HotReloadPrefs.LaunchOnEditorStart = newSettings;
}
string toggleDescription;
if (HotReloadPrefs.LaunchOnEditorStart) {
toggleDescription = "Hot Reload will be launched when Unity project opens.";
toggleDescription = Translations.Settings.SettingsAutostartOn;
} else {
toggleDescription = "Enable to launch Hot Reload when Unity project opens.";
toggleDescription = Translations.Settings.SettingsAutostartOff;
}
EditorGUILayout.LabelField(toggleDescription, HotReloadWindowStyles.WrapStyle);
EditorGUILayout.EndToggleGroup();
@@ -380,11 +393,11 @@ namespace SingularityGroup.HotReload.Editor {
void RenderShowNotifications() {
EditorGUILayout.Space(10f);
GUILayout.Label("Visual Feedback", HotReloadWindowStyles.NotificationsTitleStyle);
GUILayout.Label(Translations.Settings.SettingsVisualFeedback, HotReloadWindowStyles.NotificationsTitleStyle);
EditorGUILayout.Space(10f);
if (!EditorWindowHelper.supportsNotifications && !UnitySettingsHelper.I.playmodeTintSupported) {
var toggleDescription = "Indications are not supported in the Unity version you use.";
var toggleDescription = Translations.Settings.SettingsIndicationsUnsupported;
EditorGUILayout.LabelField(toggleDescription, HotReloadWindowStyles.WrapStyle);
}
}
@@ -396,19 +409,19 @@ namespace SingularityGroup.HotReload.Editor {
void RenderMiscHeader() {
EditorGUILayout.Space(10f);
GUILayout.Label("Misc", HotReloadWindowStyles.NotificationsTitleStyle);
GUILayout.Label(Translations.Settings.SettingsMisc, HotReloadWindowStyles.NotificationsTitleStyle);
EditorGUILayout.Space(10f);
}
void RenderShowPatchingNotifications() {
HotReloadPrefs.ShowPatchingNotifications = EditorGUILayout.BeginToggleGroup(new GUIContent("Patching Indication"), HotReloadPrefs.ShowPatchingNotifications);
HotReloadPrefs.ShowPatchingNotifications = EditorGUILayout.BeginToggleGroup(new GUIContent(Translations.Settings.TogglePatchingIndication), HotReloadPrefs.ShowPatchingNotifications);
string toggleDescription;
if (!EditorWindowHelper.supportsNotifications) {
toggleDescription = "Patching Notification is not supported in the Unity version you use.";
toggleDescription = Translations.Settings.SettingsPatchingIndicationUnsupported;
} else if (!HotReloadPrefs.ShowPatchingNotifications) {
toggleDescription = "Enable to show GameView and SceneView indications when Patching.";
toggleDescription = Translations.Settings.SettingsPatchingIndicationOff;
} else {
toggleDescription = "Indications will be shown in GameView and SceneView when Patching.";
toggleDescription = Translations.Settings.SettingsPatchingIndicationOn;
}
EditorGUILayout.LabelField(toggleDescription, HotReloadWindowStyles.WrapStyle);
EditorGUILayout.EndToggleGroup();
@@ -427,16 +440,15 @@ namespace SingularityGroup.HotReload.Editor {
// EditorGUILayout.EndToggleGroup();
// }
[Obsolete("Not implemented")]
[Obsolete(Translations.MenuItems.NotImplementedObsolete)]
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");
var restartServer = EditorUtility.DisplayDialog(Translations.Dialogs.DialogTitleRestartServer,
Translations.Dialogs.DialogMessageRestartFieldInitializer,
Translations.Dialogs.DialogButtonRestartServer, Translations.Dialogs.DialogButtonDontRestart);
if (restartServer) {
EditorCodePatcher.RestartCodePatcher().Forget();
}
@@ -445,95 +457,128 @@ namespace SingularityGroup.HotReload.Editor {
}
void RenderShowCompilingUnsupportedNotifications() {
HotReloadPrefs.ShowCompilingUnsupportedNotifications = EditorGUILayout.BeginToggleGroup(new GUIContent("Compiling Unsupported Changes Indication"), HotReloadPrefs.ShowCompilingUnsupportedNotifications);
HotReloadPrefs.ShowCompilingUnsupportedNotifications = EditorGUILayout.BeginToggleGroup(new GUIContent(Translations.Settings.ToggleCompilingIndication), HotReloadPrefs.ShowCompilingUnsupportedNotifications);
string toggleDescription;
if (!EditorWindowHelper.supportsNotifications) {
toggleDescription = "Compiling Unsupported Changes Notification is not supported in the Unity version you use.";
toggleDescription = Translations.Settings.SettingsCompilingIndicationUnsupported;
} else if (!HotReloadPrefs.ShowCompilingUnsupportedNotifications) {
toggleDescription = "Enable to show GameView and SceneView indications when compiling unsupported changes.";
toggleDescription = Translations.Settings.SettingsCompilingIndicationOff;
} else {
toggleDescription = "Indications will be shown in GameView and SceneView when compiling unsupported changes.";
toggleDescription = Translations.Settings.SettingsCompilingIndicationOn;
}
EditorGUILayout.LabelField(toggleDescription, HotReloadWindowStyles.WrapStyle);
EditorGUILayout.EndToggleGroup();
}
void RenderAutoRecompileUnsupportedChanges() {
HotReloadPrefs.AutoRecompileUnsupportedChanges = EditorGUILayout.BeginToggleGroup(new GUIContent("Auto recompile unsupported changes (recommended)"), HotReloadPrefs.AutoRecompileUnsupportedChanges && EditorCodePatcher.autoRecompileUnsupportedChangesSupported);
HotReloadPrefs.AutoRecompileUnsupportedChanges = EditorGUILayout.BeginToggleGroup(new GUIContent(Translations.Settings.ToggleAutoRecompile), HotReloadPrefs.AutoRecompileUnsupportedChanges && EditorCodePatcher.autoRecompileUnsupportedChangesSupported);
string toggleDescription;
if (!EditorCodePatcher.autoRecompileUnsupportedChangesSupported) {
toggleDescription = "Auto recompiling unsupported changes is not supported in the Unity version you use.";
toggleDescription = Translations.Settings.SettingsAutoRecompileUnsupported;
} else if (HotReloadPrefs.AutoRecompileUnsupportedChanges) {
toggleDescription = "Hot Reload will recompile automatically after code changes that Hot Reload doesn't support.";
toggleDescription = Translations.Settings.SettingsAutoRecompileOn;
} else {
toggleDescription = "When enabled, recompile happens automatically after code changes that Hot Reload doesn't support.";
toggleDescription = Translations.Settings.SettingsAutoRecompileOff;
}
if (!HotReloadPrefs.AutoRecompileUnsupportedChangesInEditMode && !HotReloadPrefs.AutoRecompileUnsupportedChangesInPlayMode) {
HotReloadPrefs.AutoRecompileUnsupportedChangesInEditMode = true;
}
EditorGUILayout.LabelField(toggleDescription, HotReloadWindowStyles.WrapStyle);
EditorGUILayout.EndToggleGroup();
}
void RenderAutoRecompileInspectorFieldEdits() {
HotReloadPrefs.AutoRecompileInspectorFieldsEdit = EditorGUILayout.BeginToggleGroup(new GUIContent(Translations.Settings.ToggleAutoRecompileInspector), HotReloadPrefs.AutoRecompileInspectorFieldsEdit);
string toggleDescription;
if (HotReloadPrefs.AutoRecompileInspectorFieldsEdit) {
toggleDescription = Translations.Settings.SettingsAutoRecompileInspectorOn;
} else {
toggleDescription = Translations.Settings.SettingsAutoRecompileInspectorOff;
}
EditorGUILayout.LabelField(toggleDescription, HotReloadWindowStyles.WrapStyle);
EditorGUILayout.EndToggleGroup();
}
void RenderAutoRecompilePartiallyUnsupportedChanges() {
HotReloadPrefs.AutoRecompilePartiallyUnsupportedChanges = EditorGUILayout.BeginToggleGroup(new GUIContent("Include partially unsupported changes"), HotReloadPrefs.AutoRecompilePartiallyUnsupportedChanges);
HotReloadPrefs.AutoRecompilePartiallyUnsupportedChanges = EditorGUILayout.BeginToggleGroup(new GUIContent(Translations.Settings.ToggleAutoRecompilePartial), HotReloadPrefs.AutoRecompilePartiallyUnsupportedChanges);
string toggleDescription;
if (HotReloadPrefs.AutoRecompilePartiallyUnsupportedChanges) {
toggleDescription = "Hot Reload will recompile partially unsupported changes.";
toggleDescription = Translations.Settings.SettingsAutoRecompilePartialOn;
} else {
toggleDescription = "Enable to recompile partially unsupported changes.";
toggleDescription = Translations.Settings.SettingsAutoRecompilePartialOff;
}
EditorGUILayout.LabelField(toggleDescription, HotReloadWindowStyles.WrapStyle);
EditorGUILayout.EndToggleGroup();
}
void RenderDisplayNewMonobehaviourMethodsAsPartiallySupported() {
HotReloadPrefs.DisplayNewMonobehaviourMethodsAsPartiallySupported = EditorGUILayout.BeginToggleGroup(new GUIContent("Display new Monobehaviour methods as partially supported"), HotReloadPrefs.DisplayNewMonobehaviourMethodsAsPartiallySupported);
HotReloadPrefs.DisplayNewMonobehaviourMethodsAsPartiallySupported = EditorGUILayout.BeginToggleGroup(new GUIContent(Translations.Settings.ToggleDisplayMonobehaviour), HotReloadPrefs.DisplayNewMonobehaviourMethodsAsPartiallySupported);
string toggleDescription;
if (HotReloadPrefs.DisplayNewMonobehaviourMethodsAsPartiallySupported) {
toggleDescription = "Hot Reload will display new monobehaviour methods as partially unsupported.";
toggleDescription = Translations.Settings.SettingsDisplayMonobehaviourOn;
} else {
toggleDescription = "Enable to display new monobehaviour methods as partially unsupported.";
toggleDescription = Translations.Settings.SettingsDisplayMonobehaviourOff;
}
EditorGUILayout.LabelField(toggleDescription, HotReloadWindowStyles.WrapStyle);
EditorGUILayout.EndToggleGroup();
}
void RenderAutoRecompileUnsupportedChangesImmediately() {
HotReloadPrefs.AutoRecompileUnsupportedChangesImmediately = EditorGUILayout.BeginToggleGroup(new GUIContent("Recompile immediately"), HotReloadPrefs.AutoRecompileUnsupportedChangesImmediately);
HotReloadPrefs.AutoRecompileUnsupportedChangesImmediately = EditorGUILayout.BeginToggleGroup(new GUIContent(Translations.Settings.ToggleRecompileImmediately), HotReloadPrefs.AutoRecompileUnsupportedChangesImmediately);
string toggleDescription;
if (HotReloadPrefs.AutoRecompileUnsupportedChangesImmediately) {
toggleDescription = "Unsupported changes will be recompiled immediately.";
toggleDescription = Translations.Settings.SettingsRecompileImmediatelyOn;
} else {
toggleDescription = "Unsupported changes will be recompiled when editor is focused. Enable to recompile immediately.";
toggleDescription = Translations.Settings.SettingsRecompileImmediatelyOff;
}
EditorGUILayout.LabelField(toggleDescription, HotReloadWindowStyles.WrapStyle);
EditorGUILayout.EndToggleGroup();
}
void RenderAutoRecompileUnsupportedChangesInPlayMode() {
HotReloadPrefs.AutoRecompileUnsupportedChangesInPlayMode = EditorGUILayout.BeginToggleGroup(new GUIContent("Recompile in Play Mode"), HotReloadPrefs.AutoRecompileUnsupportedChangesInPlayMode);
HotReloadPrefs.AutoRecompileUnsupportedChangesInPlayMode = EditorGUILayout.BeginToggleGroup(new GUIContent(Translations.Settings.ToggleRecompilePlayMode), HotReloadPrefs.AutoRecompileUnsupportedChangesInPlayMode);
string toggleDescription;
if (HotReloadPrefs.AutoRecompileUnsupportedChangesInPlayMode) {
toggleDescription = "Hot Reload will exit Play Mode to recompile unsupported changes.";
toggleDescription = Translations.Settings.SettingsRecompilePlayModeOn;
} else {
toggleDescription = "Enable to auto exit Play Mode to recompile unsupported changes.";
toggleDescription = Translations.Settings.SettingsRecompilePlayModeOff;
}
if (!HotReloadPrefs.AutoRecompileUnsupportedChangesInEditMode && !HotReloadPrefs.AutoRecompileUnsupportedChangesInPlayMode) {
HotReloadPrefs.AutoRecompileUnsupportedChanges = false;
}
EditorGUILayout.LabelField(toggleDescription, HotReloadWindowStyles.WrapStyle);
EditorGUILayout.EndToggleGroup();
}
void RenderAutoRecompileUnsupportedChangesInEditMode() {
HotReloadPrefs.AutoRecompileUnsupportedChangesInEditMode = EditorGUILayout.BeginToggleGroup(new GUIContent(Translations.Settings.ToggleRecompileEditMode), HotReloadPrefs.AutoRecompileUnsupportedChangesInEditMode);
string toggleDescription;
if (HotReloadPrefs.AutoRecompileUnsupportedChangesInEditMode) {
toggleDescription = Translations.Settings.SettingsRecompileEditModeOn;
} else {
toggleDescription = Translations.Settings.SettingsRecompileEditModeOff;
}
if (!HotReloadPrefs.AutoRecompileUnsupportedChangesInEditMode && !HotReloadPrefs.AutoRecompileUnsupportedChangesInPlayMode) {
HotReloadPrefs.AutoRecompileUnsupportedChanges = false;
}
EditorGUILayout.LabelField(toggleDescription, HotReloadWindowStyles.WrapStyle);
EditorGUILayout.EndToggleGroup();
}
void RenderAutoRecompileUnsupportedChangesOnExitPlayMode() {
HotReloadPrefs.AutoRecompileUnsupportedChangesOnExitPlayMode = EditorGUILayout.BeginToggleGroup(new GUIContent("Recompile on exit Play Mode"), HotReloadPrefs.AutoRecompileUnsupportedChangesOnExitPlayMode);
HotReloadPrefs.AutoRecompileUnsupportedChangesOnExitPlayMode = EditorGUILayout.BeginToggleGroup(new GUIContent(Translations.Settings.ToggleRecompileExitPlayMode), HotReloadPrefs.AutoRecompileUnsupportedChangesOnExitPlayMode);
string toggleDescription;
if (HotReloadPrefs.AutoRecompileUnsupportedChangesOnExitPlayMode) {
toggleDescription = "Hot Reload will recompile unsupported changes when exiting Play Mode.";
toggleDescription = Translations.Settings.SettingsRecompileExitPlayModeOn;
} else {
toggleDescription = "Enable to recompile unsupported changes when exiting Play Mode.";
toggleDescription = Translations.Settings.SettingsRecompileExitPlayModeOff;
}
EditorGUILayout.LabelField(toggleDescription, HotReloadWindowStyles.WrapStyle);
EditorGUILayout.EndToggleGroup();
}
void RenderOnDevice() {
HotReloadPrefs.ShowOnDevice = EditorGUILayout.Foldout(HotReloadPrefs.ShowOnDevice, "On-Device", true, HotReloadWindowStyles.FoldoutStyle);
HotReloadPrefs.ShowOnDevice = EditorGUILayout.Foldout(HotReloadPrefs.ShowOnDevice, Translations.Settings.SettingsOnDevice, true, HotReloadWindowStyles.FoldoutStyle);
if (!HotReloadPrefs.ShowOnDevice) {
return;
}
@@ -559,7 +604,7 @@ namespace SingularityGroup.HotReload.Editor {
}
GUILayout.Space(9f); // space between logo and headline
GUILayout.Label("Make changes to a build running on-device",
GUILayout.Label(Translations.OnDevice.OnDeviceHeadline,
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);
@@ -571,7 +616,7 @@ namespace SingularityGroup.HotReload.Editor {
//ButtonToOpenBuildSettings();
{
GUILayout.Label("Manual connect", HotReloadWindowStyles.H3TitleStyle);
GUILayout.Label(Translations.Settings.SettingsManualConnect, HotReloadWindowStyles.H3TitleStyle);
EditorGUILayout.Space();
GUILayout.BeginHorizontal();
@@ -583,22 +628,21 @@ namespace SingularityGroup.HotReload.Editor {
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}'";
text = string.Format(Translations.OnDevice.OnDeviceManualConnectFormat, 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";
text = string.Format(Translations.OnDevice.OnDeviceManualConnectWithIP, ip, RequestHelper.port);
}
GUILayout.Label(text, HotReloadWindowStyles.H3TitleWrapStyle);
if (!currentState.isServerHealthy) {
DrawHorizontalCheck(ServerHealthCheck.I.IsServerHealthy,
"Hot Reload is running",
"Hot Reload is not running",
Translations.OnDevice.OnDeviceCheckHotReloadRunning,
Translations.OnDevice.OnDeviceCheckHotReloadNotRunning,
hasFix: false);
}
if (!HotReloadPrefs.ExposeServerToLocalNetwork) {
var summary = $"Enable '{new ExposeServerOption().ShortSummary}'";
var summary = string.Format(Translations.OnDevice.OnDeviceCheckEnableExposeServer, new ExposeServerOption().ShortSummary);
DrawHorizontalCheck(HotReloadPrefs.ExposeServerToLocalNetwork,
summary,
summary);
@@ -620,10 +664,10 @@ namespace SingularityGroup.HotReload.Editor {
{
EditorGUILayout.BeginHorizontal();
GUILayout.Label("Build Settings Checklist", HotReloadWindowStyles.H3TitleStyle);
GUILayout.Label(Translations.Settings.SettingsBuildSettingsChecklist, HotReloadWindowStyles.H3TitleStyle);
EditorGUI.BeginDisabledGroup(isSupported);
// One-click to change each setting to the supported value
if (GUILayout.Button("Fix All", GUILayout.MaxWidth(90f))) {
if (GUILayout.Button(Translations.Common.ButtonFixAll, GUILayout.MaxWidth(90f))) {
FixAllUnsupportedSettings(so);
}
EditorGUI.EndDisabledGroup();
@@ -641,7 +685,7 @@ namespace SingularityGroup.HotReload.Editor {
// Settings checkboxes (Hot Reload options)
{
GUILayout.Label("Options", HotReloadWindowStyles.H3TitleStyle);
GUILayout.Label(Translations.Settings.SettingsOptions, HotReloadWindowStyles.H3TitleStyle);
if (settingsObject) {
optionsSection.DrawGUI(so);
}
@@ -655,7 +699,7 @@ namespace SingularityGroup.HotReload.Editor {
currentState.loginStatus,
verbose: true,
allowHide: false,
overrideActionButton: "Activate License",
overrideActionButton:Translations.Common.ButtonActivateLicense,
showConsumptions: true
);
}
@@ -731,12 +775,12 @@ namespace SingularityGroup.HotReload.Editor {
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");
var confirmed = EditorUtility.DisplayDialog(Translations.Dialogs.DialogTitleSwitchBuildTarget,
Translations.Dialogs.DialogMessageSwitchBuildTarget,
Translations.Dialogs.DialogButtonSwitchToStandalone, Translations.Common.ButtonCancel);
if (confirmed) {
EditorUserBuildSettings.SwitchActiveBuildTargetAsync(BuildTargetGroup.Standalone, buildTarget);
Log.Info($"Build target is switching to {buildTarget}.");
Log.Info(Translations.About.LogBuildTargetSwitching, buildTarget);
return true;
} else {
return false;
@@ -755,28 +799,28 @@ namespace SingularityGroup.HotReload.Editor {
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");
string.Format(Translations.OnDevice.OnDeviceCheckPlatformSelected, selectedPlatform.ToString()),
string.Format(Translations.OnDevice.OnDeviceCheckPlatformNotSupported, selectedPlatform.ToString()));
using (new EditorGUI.DisabledScope(!isCurrentBuildTargetSupported.Value)) {
foreach (var option in allOptions) {
DrawHorizontalCheck(option.GetValue(so),
$"Enable \"{option.ShortSummary}\"",
$"Enable \"{option.ShortSummary}\"");
string.Format(Translations.OnDevice.OnDeviceCheckEnableExposeServer, option.ShortSummary),
string.Format(Translations.OnDevice.OnDeviceCheckEnableExposeServer, option.ShortSummary));
}
DrawHorizontalCheck(EditorUserBuildSettings.development,
"Development Build is enabled",
"Enable \"Development Build\"");
Translations.OnDevice.OnDeviceCheckDevelopmentEnabled,
Translations.OnDevice.OnDeviceCheckEnableDevelopment);
DrawHorizontalCheck(ScriptingBackend == ScriptingImplementation.Mono2x,
$"Scripting Backend is set to Mono",
$"Set Scripting Backend to Mono");
Translations.OnDevice.OnDeviceCheckMonoBackend,
Translations.OnDevice.OnDeviceCheckSetMonoBackend);
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."
string.Format(Translations.OnDevice.OnDeviceCheckStrippingLevel, StrippingLevel),
string.Format(Translations.OnDevice.OnDeviceCheckStrippingLevel, StrippingLevel),
suggestedSolutionText: Translations.OnDevice.OnDeviceCheckStrippingSolution
);
}
}