From 503f1f796850984f77b0dac36ef7c2369d959405 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= Date: Sun, 31 Dec 2023 17:01:02 -0300 Subject: [PATCH 1/8] Allow storing data in exe folder rather than Appdata --- .../Game/UserInterface/FolderBrowser.cs | 17 +++- Assets/Scripts/Game/UserInterface/ListBox.cs | 11 +++ Assets/Scripts/SettingsManager.cs | 83 +++++++++++++++++-- 3 files changed, 104 insertions(+), 7 deletions(-) diff --git a/Assets/Scripts/Game/UserInterface/FolderBrowser.cs b/Assets/Scripts/Game/UserInterface/FolderBrowser.cs index 51419f011d..d73affc9da 100644 --- a/Assets/Scripts/Game/UserInterface/FolderBrowser.cs +++ b/Assets/Scripts/Game/UserInterface/FolderBrowser.cs @@ -166,7 +166,22 @@ void Setup() // Setup initial folder conditions RefreshDrives(); - RefreshFolders(); + + if(DaggerfallUnity.Settings.PortableInstall) + { // start browsing from exe path for portable installs + currentPath = AppDomain.CurrentDomain.BaseDirectory; + if(SystemInfo.operatingSystemFamily == OperatingSystemFamily.Windows) + { + var drive = Path.GetPathRoot(currentPath); + driveList.SelectIndexSilent(drives.FindIndex( d => d == drive )); + } + UpdatePathText(); + RefreshFolders(); + } + else + { + RefreshFolders(); + } // Setup events confirmButton.OnMouseClick += ConfirmButton_OnMouseClick; diff --git a/Assets/Scripts/Game/UserInterface/ListBox.cs b/Assets/Scripts/Game/UserInterface/ListBox.cs index ccbba4b42c..3aa207f4b4 100644 --- a/Assets/Scripts/Game/UserInterface/ListBox.cs +++ b/Assets/Scripts/Game/UserInterface/ListBox.cs @@ -767,6 +767,17 @@ public void SelectIndex(int index) } } + public void SelectIndexSilent(int index) + { + if (index < 0 || index >= listItems.Count) + return; + + if (listItems[index].Enabled) + { + selectedIndex = index; + } + } + public void SelectNone() { selectedIndex = -1; diff --git a/Assets/Scripts/SettingsManager.cs b/Assets/Scripts/SettingsManager.cs index e7b0727f6c..a4ec251a30 100644 --- a/Assets/Scripts/SettingsManager.cs +++ b/Assets/Scripts/SettingsManager.cs @@ -31,6 +31,39 @@ namespace DaggerfallWorkshop /// public class SettingsManager { + private static string GetFullPath(string basePath, string path) + { + if(string.IsNullOrEmpty(path) || Path.IsPathRooted(path)) + { + return path; + } + + Uri baseUri = new Uri(basePath); + Uri relUri = new Uri(path, UriKind.Relative); + Uri fullPath; + + if(Uri.TryCreate(baseUri, relUri, out fullPath)) + { + return fullPath.LocalPath; + } + else + { + return ""; + } + } + + private static string GetRelativePath(string basePath, string path) + { + if(string.IsNullOrEmpty(path)) + { + return path; + } + Uri baseUri = new Uri(basePath); + Uri relUri = baseUri.MakeRelativeUri(new Uri(path)); + + return Uri.UnescapeDataString(relUri.ToString()).Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar); + } + const string defaultsIniName = "defaults.ini"; const string settingsIniName = "settings.ini"; const string settingsBakExt = ".bak"; @@ -55,6 +88,20 @@ public class SettingsManager string persistentPath = null; string distributionSuffix = null; + + bool? isPortableInstall = null; + + public bool PortableInstall + { + get + { + if(isPortableInstall == null) + { + isPortableInstall = File.Exists(AppDomain.CurrentDomain.BaseDirectory + "\\Portable.txt"); + } + return (bool)isPortableInstall; + } + } public string PersistentDataPath { @@ -62,12 +109,20 @@ public string PersistentDataPath { if (string.IsNullOrEmpty(persistentPath)) { + if(PortableInstall) + { + persistentPath = AppDomain.CurrentDomain.BaseDirectory + "\\PortableAppdata"; + Directory.CreateDirectory(persistentPath); + } + else + { #if UNITY_EDITOR && SEPARATE_DEV_PERSISTENT_PATH - persistentPath = String.Concat(Application.persistentDataPath, ".devenv"); - Directory.CreateDirectory(persistentPath); + persistentPath = String.Concat(Application.persistentDataPath, ".devenv"); + Directory.CreateDirectory(persistentPath); #else - persistentPath = Application.persistentDataPath; + persistentPath = Application.persistentDataPath; #endif + } } return persistentPath; } @@ -353,6 +408,22 @@ public void LoadSettings() MyDaggerfallUnitySavePath = GetString(sectionDaggerfall, "MyDaggerfallUnitySavePath"); MyDaggerfallUnityScreenshotsPath = GetString(sectionDaggerfall, "MyDaggerfallUnityScreenshotsPath"); + if(PortableInstall) + { + if(!string.IsNullOrEmpty(MyDaggerfallPath)) + { + MyDaggerfallPath = GetFullPath(AppDomain.CurrentDomain.BaseDirectory + "\\", MyDaggerfallPath); + } + if(!string.IsNullOrEmpty(MyDaggerfallUnitySavePath)) + { + MyDaggerfallUnitySavePath = GetFullPath(AppDomain.CurrentDomain.BaseDirectory + "\\", MyDaggerfallUnitySavePath); + } + if(!string.IsNullOrEmpty(MyDaggerfallUnityScreenshotsPath)) + { + MyDaggerfallUnityScreenshotsPath = GetFullPath(AppDomain.CurrentDomain.BaseDirectory + "\\", MyDaggerfallUnityScreenshotsPath); + } + } + ResolutionWidth = GetInt(sectionVideo, "ResolutionWidth"); ResolutionHeight = GetInt(sectionVideo, "ResolutionHeight"); RetroRenderingMode = GetInt(sectionVideo, "RetroRenderingMode", 0, 2); @@ -536,9 +607,9 @@ public void LoadSettings() public void SaveSettings() { // Write property cache to ini data - SetString(sectionDaggerfall, "MyDaggerfallPath", MyDaggerfallPath); - SetString(sectionDaggerfall, "MyDaggerfallUnitySavePath", MyDaggerfallUnitySavePath); - SetString(sectionDaggerfall, "MyDaggerfallUnityScreenshotsPath", MyDaggerfallUnityScreenshotsPath); + SetString(sectionDaggerfall, "MyDaggerfallPath", PortableInstall ? GetRelativePath(AppDomain.CurrentDomain.BaseDirectory + "\\", MyDaggerfallPath) : MyDaggerfallPath); + SetString(sectionDaggerfall, "MyDaggerfallUnitySavePath", PortableInstall ? GetRelativePath(AppDomain.CurrentDomain.BaseDirectory + "\\", MyDaggerfallUnitySavePath) : MyDaggerfallUnitySavePath); + SetString(sectionDaggerfall, "MyDaggerfallUnityScreenshotsPath", PortableInstall ? GetRelativePath(AppDomain.CurrentDomain.BaseDirectory + "\\", MyDaggerfallUnityScreenshotsPath) : MyDaggerfallUnityScreenshotsPath); SetInt(sectionVideo, "ResolutionWidth", ResolutionWidth); SetInt(sectionVideo, "ResolutionHeight", ResolutionHeight); From 75f9e57f8f287f8c854c46cd23980c98f38bb320 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= Date: Wed, 7 Feb 2024 18:59:24 -0300 Subject: [PATCH 2/8] Fix return path the `RefreshFolders` call on `Update` also broke the return path, so i moved it into RefreshFolders itself --- Assets/Scripts/Game/UserInterface/FolderBrowser.cs | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/Assets/Scripts/Game/UserInterface/FolderBrowser.cs b/Assets/Scripts/Game/UserInterface/FolderBrowser.cs index d73affc9da..9f2f413d90 100644 --- a/Assets/Scripts/Game/UserInterface/FolderBrowser.cs +++ b/Assets/Scripts/Game/UserInterface/FolderBrowser.cs @@ -231,6 +231,10 @@ void RefreshFolders() } } + // Add return path + if (currentPath != drives[driveList.SelectedIndex]) + folderList.AddItem("..", 0); + folderScroller.TotalUnits = folderList.Count; folderScroller.DisplayUnits = folderList.RowsDisplayed; folderScroller.ScrollIndex = 0; @@ -356,14 +360,6 @@ private void FolderList_OnUseSelectedItem() currentPath = newPath; RefreshFolders(); RaisePathChangedEvent(); - - // Add return path - if (currentPath != drives[driveList.SelectedIndex]) - folderList.AddItem("..", 0); - - // Update scroller units - folderScroller.TotalUnits = folderList.Count; - UpdatePathText(); } } From 6c3bca333ab17a7c3108c99d2baec7017b25fb29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= Date: Wed, 7 Feb 2024 19:06:02 -0300 Subject: [PATCH 3/8] Don't check for portable installs if running from the unity editor --- Assets/Scripts/SettingsManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Assets/Scripts/SettingsManager.cs b/Assets/Scripts/SettingsManager.cs index a4ec251a30..62e376819c 100644 --- a/Assets/Scripts/SettingsManager.cs +++ b/Assets/Scripts/SettingsManager.cs @@ -97,7 +97,7 @@ public bool PortableInstall { if(isPortableInstall == null) { - isPortableInstall = File.Exists(AppDomain.CurrentDomain.BaseDirectory + "\\Portable.txt"); + isPortableInstall = Application.isEditor ? false : File.Exists(AppDomain.CurrentDomain.BaseDirectory + "\\Portable.txt"); } return (bool)isPortableInstall; } From 8ee63782b9a085d261a9f65a1920299515bacd84 Mon Sep 17 00:00:00 2001 From: kaboissonneault Date: Wed, 10 Apr 2024 21:58:44 -0400 Subject: [PATCH 4/8] Reimplement portable install with the new DaggerfallUnityApplication --- Assets/Scripts/DaggerfallUnityApplication.cs | 24 ++++++- .../Game/UserInterface/FolderBrowser.cs | 6 +- Assets/Scripts/SettingsManager.cs | 64 ++++++++++++++++++- 3 files changed, 87 insertions(+), 7 deletions(-) diff --git a/Assets/Scripts/DaggerfallUnityApplication.cs b/Assets/Scripts/DaggerfallUnityApplication.cs index 43fb0ae7a0..d8eb0d3472 100644 --- a/Assets/Scripts/DaggerfallUnityApplication.cs +++ b/Assets/Scripts/DaggerfallUnityApplication.cs @@ -18,6 +18,20 @@ public static class DaggerfallUnityApplication { static string persistentDataPath; + private static bool? isPortableInstall; + + public static bool IsPortableInstall + { + get + { + if (isPortableInstall == null) + { + isPortableInstall = !Application.isEditor && File.Exists(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Portable.txt")); + } + + return isPortableInstall.Value; + } + } public static string PersistentDataPath { @@ -38,7 +52,15 @@ private static void InitializePersistentPath() persistentDataPath = String.Concat(Application.persistentDataPath, ".devenv"); Directory.CreateDirectory(persistentDataPath); #else - persistentDataPath = Application.persistentDataPath; + if (IsPortableInstall) + { + persistentDataPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "PortableAppdata"); + Directory.CreateDirectory(persistentDataPath); + } + else + { + persistentDataPath = Application.persistentDataPath; + } #endif } diff --git a/Assets/Scripts/Game/UserInterface/FolderBrowser.cs b/Assets/Scripts/Game/UserInterface/FolderBrowser.cs index 80987746c0..2ffc15d637 100644 --- a/Assets/Scripts/Game/UserInterface/FolderBrowser.cs +++ b/Assets/Scripts/Game/UserInterface/FolderBrowser.cs @@ -176,9 +176,9 @@ void Setup() // Setup initial folder conditions RefreshDrives(); - - if(DaggerfallUnity.Settings.PortableInstall) - { + + if(DaggerfallUnityApplication.IsPortableInstall) + { // start browsing from exe path for portable installs currentPath = AppDomain.CurrentDomain.BaseDirectory; if(SystemInfo.operatingSystemFamily == OperatingSystemFamily.Windows) diff --git a/Assets/Scripts/SettingsManager.cs b/Assets/Scripts/SettingsManager.cs index f96b45041f..6a68378687 100644 --- a/Assets/Scripts/SettingsManager.cs +++ b/Assets/Scripts/SettingsManager.cs @@ -14,6 +14,7 @@ using System.Globalization; using System.Collections.Generic; using System.IO; +using System.Linq; using DaggerfallWorkshop.Game; using IniParser; using IniParser.Model; @@ -29,6 +30,35 @@ namespace DaggerfallWorkshop /// public class SettingsManager { + private static string GetFullPath(string basePath, string path) + { + if(string.IsNullOrEmpty(path) || Path.IsPathRooted(path)) + { + return path; + } + + return Path.GetFullPath(Path.Combine(basePath, path)); + } + + private static string GetRelativePath(string basePath, string path) + { + if(string.IsNullOrEmpty(path)) + { + return path; + } + + char lastChar = basePath.Last(); + if (lastChar != Path.DirectorySeparatorChar && lastChar != Path.AltDirectorySeparatorChar) + { + basePath += Path.DirectorySeparatorChar; + } + + Uri baseUri = new Uri(basePath); + Uri relUri = baseUri.MakeRelativeUri(new Uri(path)); + + return Uri.UnescapeDataString(relUri.ToString()).Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar); + } + const string defaultsIniName = "defaults.ini"; const string settingsIniName = "settings.ini"; const string settingsBakExt = ".bak"; @@ -342,6 +372,24 @@ public void LoadSettings() MyDaggerfallUnitySavePath = GetString(sectionDaggerfall, "MyDaggerfallUnitySavePath"); MyDaggerfallUnityScreenshotsPath = GetString(sectionDaggerfall, "MyDaggerfallUnityScreenshotsPath"); + // In Portable Install mode, we save those paths as relative to the current directory + // This allows users to move the directory around without breaking the settings + if(DaggerfallUnityApplication.IsPortableInstall) + { + if(!string.IsNullOrEmpty(MyDaggerfallPath)) + { + MyDaggerfallPath = GetFullPath(AppDomain.CurrentDomain.BaseDirectory, MyDaggerfallPath); + } + if(!string.IsNullOrEmpty(MyDaggerfallUnitySavePath)) + { + MyDaggerfallUnitySavePath = GetFullPath(AppDomain.CurrentDomain.BaseDirectory, MyDaggerfallUnitySavePath); + } + if(!string.IsNullOrEmpty(MyDaggerfallUnityScreenshotsPath)) + { + MyDaggerfallUnityScreenshotsPath = GetFullPath(AppDomain.CurrentDomain.BaseDirectory, MyDaggerfallUnityScreenshotsPath); + } + } + ResolutionWidth = GetInt(sectionVideo, "ResolutionWidth"); ResolutionHeight = GetInt(sectionVideo, "ResolutionHeight"); RetroRenderingMode = GetInt(sectionVideo, "RetroRenderingMode", 0, 2); @@ -525,9 +573,19 @@ public void LoadSettings() public void SaveSettings() { // Write property cache to ini data - SetString(sectionDaggerfall, "MyDaggerfallPath", MyDaggerfallPath); - SetString(sectionDaggerfall, "MyDaggerfallUnitySavePath", MyDaggerfallUnitySavePath); - SetString(sectionDaggerfall, "MyDaggerfallUnityScreenshotsPath", MyDaggerfallUnityScreenshotsPath); + if (DaggerfallUnityApplication.IsPortableInstall) + { + // Save relative paths + SetString(sectionDaggerfall, "MyDaggerfallPath", GetRelativePath(AppDomain.CurrentDomain.BaseDirectory, MyDaggerfallPath)); + SetString(sectionDaggerfall, "MyDaggerfallUnitySavePath", GetRelativePath(AppDomain.CurrentDomain.BaseDirectory, MyDaggerfallUnitySavePath)); + SetString(sectionDaggerfall, "MyDaggerfallUnityScreenshotsPath", GetRelativePath(AppDomain.CurrentDomain.BaseDirectory,MyDaggerfallUnityScreenshotsPath)); + } + else + { + SetString(sectionDaggerfall, "MyDaggerfallPath", MyDaggerfallPath); + SetString(sectionDaggerfall, "MyDaggerfallUnitySavePath", MyDaggerfallUnitySavePath); + SetString(sectionDaggerfall, "MyDaggerfallUnityScreenshotsPath", MyDaggerfallUnityScreenshotsPath); + } SetInt(sectionVideo, "ResolutionWidth", ResolutionWidth); SetInt(sectionVideo, "ResolutionHeight", ResolutionHeight); From 0bf0cecc13a9dddaa86ece11382943d1f5def4e3 Mon Sep 17 00:00:00 2001 From: kaboissonneault Date: Sun, 14 Apr 2024 15:13:15 -0400 Subject: [PATCH 5/8] Revert changes to FolderBrowser. If a Portable Install wants an embedded DF install, use the StreamingAssets/GameFiles folder --- Assets/Scripts/Game/UserInterface/FolderBrowser.cs | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/Assets/Scripts/Game/UserInterface/FolderBrowser.cs b/Assets/Scripts/Game/UserInterface/FolderBrowser.cs index 2ffc15d637..d3c760e8fb 100644 --- a/Assets/Scripts/Game/UserInterface/FolderBrowser.cs +++ b/Assets/Scripts/Game/UserInterface/FolderBrowser.cs @@ -176,19 +176,6 @@ void Setup() // Setup initial folder conditions RefreshDrives(); - - if(DaggerfallUnityApplication.IsPortableInstall) - { - // start browsing from exe path for portable installs - currentPath = AppDomain.CurrentDomain.BaseDirectory; - if(SystemInfo.operatingSystemFamily == OperatingSystemFamily.Windows) - { - var drive = Path.GetPathRoot(currentPath); - driveList.SelectIndexSilent(drives.FindIndex( d => d == drive )); - } - UpdatePathText(); - } - RefreshFolders(); // Setup events @@ -371,6 +358,7 @@ private void FolderList_OnUseSelectedItem() currentPath = newPath; RefreshFolders(); RaisePathChangedEvent(); + UpdatePathText(); } } From 85afcad0bd19999789a79abafe9cc1dadcf03348 Mon Sep 17 00:00:00 2001 From: kaboissonneault Date: Sun, 14 Apr 2024 15:40:21 -0400 Subject: [PATCH 6/8] Don't save paths outside the DFU installation as relative --- Assets/Scripts/SettingsManager.cs | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/Assets/Scripts/SettingsManager.cs b/Assets/Scripts/SettingsManager.cs index 6a68378687..bd0c24924d 100644 --- a/Assets/Scripts/SettingsManager.cs +++ b/Assets/Scripts/SettingsManager.cs @@ -40,7 +40,9 @@ private static string GetFullPath(string basePath, string path) return Path.GetFullPath(Path.Combine(basePath, path)); } - private static string GetRelativePath(string basePath, string path) + // Returns a relative path if embedded within the base path, + // returns the full path as is if outside the base path + private static string GetPortablePath(string basePath, string path) { if(string.IsNullOrEmpty(path)) { @@ -56,7 +58,13 @@ private static string GetRelativePath(string basePath, string path) Uri baseUri = new Uri(basePath); Uri relUri = baseUri.MakeRelativeUri(new Uri(path)); - return Uri.UnescapeDataString(relUri.ToString()).Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar); + string relativePath = Uri.UnescapeDataString(relUri.ToString()).Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar); + if (relativePath.StartsWith(".." + Path.DirectorySeparatorChar)) + { + return path; + } + + return relativePath; } const string defaultsIniName = "defaults.ini"; @@ -576,9 +584,9 @@ public void SaveSettings() if (DaggerfallUnityApplication.IsPortableInstall) { // Save relative paths - SetString(sectionDaggerfall, "MyDaggerfallPath", GetRelativePath(AppDomain.CurrentDomain.BaseDirectory, MyDaggerfallPath)); - SetString(sectionDaggerfall, "MyDaggerfallUnitySavePath", GetRelativePath(AppDomain.CurrentDomain.BaseDirectory, MyDaggerfallUnitySavePath)); - SetString(sectionDaggerfall, "MyDaggerfallUnityScreenshotsPath", GetRelativePath(AppDomain.CurrentDomain.BaseDirectory,MyDaggerfallUnityScreenshotsPath)); + SetString(sectionDaggerfall, "MyDaggerfallPath", GetPortablePath(AppDomain.CurrentDomain.BaseDirectory, MyDaggerfallPath)); + SetString(sectionDaggerfall, "MyDaggerfallUnitySavePath", GetPortablePath(AppDomain.CurrentDomain.BaseDirectory, MyDaggerfallUnitySavePath)); + SetString(sectionDaggerfall, "MyDaggerfallUnityScreenshotsPath", GetPortablePath(AppDomain.CurrentDomain.BaseDirectory,MyDaggerfallUnityScreenshotsPath)); } else { From 2386889b82f01a809b2c707cb007e3e73ee3c8d6 Mon Sep 17 00:00:00 2001 From: kaboissonneault Date: Sun, 14 Apr 2024 15:46:01 -0400 Subject: [PATCH 7/8] Fixed inconsistent whitespace in FolderBrowser.cs --- Assets/Scripts/Game/UserInterface/FolderBrowser.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Assets/Scripts/Game/UserInterface/FolderBrowser.cs b/Assets/Scripts/Game/UserInterface/FolderBrowser.cs index d3c760e8fb..db133df9b6 100644 --- a/Assets/Scripts/Game/UserInterface/FolderBrowser.cs +++ b/Assets/Scripts/Game/UserInterface/FolderBrowser.cs @@ -176,7 +176,7 @@ void Setup() // Setup initial folder conditions RefreshDrives(); - RefreshFolders(); + RefreshFolders(); // Setup events confirmButton.OnMouseClick += ConfirmButton_OnMouseClick; From 98990df25ac1f4f0c471f5328960a79808ebb0a9 Mon Sep 17 00:00:00 2001 From: kaboissonneault Date: Sun, 14 Apr 2024 15:47:50 -0400 Subject: [PATCH 8/8] Reverted "SelectIndexSilent" in ListBox.cs --- Assets/Scripts/Game/UserInterface/ListBox.cs | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/Assets/Scripts/Game/UserInterface/ListBox.cs b/Assets/Scripts/Game/UserInterface/ListBox.cs index 3aa207f4b4..ccbba4b42c 100644 --- a/Assets/Scripts/Game/UserInterface/ListBox.cs +++ b/Assets/Scripts/Game/UserInterface/ListBox.cs @@ -767,17 +767,6 @@ public void SelectIndex(int index) } } - public void SelectIndexSilent(int index) - { - if (index < 0 || index >= listItems.Count) - return; - - if (listItems[index].Enabled) - { - selectedIndex = index; - } - } - public void SelectNone() { selectedIndex = -1;