diff --git a/DarkScript3/EditorGUI.cs b/DarkScript3/EditorGUI.cs index 5043a01..dfa5901 100644 --- a/DarkScript3/EditorGUI.cs +++ b/DarkScript3/EditorGUI.cs @@ -10,6 +10,7 @@ using System.Windows.Forms; using FastColoredTextBoxNS; using SoulsFormats; +using SoulsFormats.Utilities; using static DarkScript3.DocAutocomplete; using Range = FastColoredTextBoxNS.Range; @@ -293,7 +294,7 @@ private bool SaveJSAndEMEVDFileOperation(out Range errorSelect) } if (File.Exists(Scripter.EmevdPath)) { - SFUtil.Backup(Scripter.EmevdPath); + PathHelper.Backup(Scripter.EmevdPath); } result.Write(Scripter.EmevdPath); SaveJSFile(); diff --git a/DarkScript3/GUI.cs b/DarkScript3/GUI.cs index 7dd36ee..36677b0 100644 --- a/DarkScript3/GUI.cs +++ b/DarkScript3/GUI.cs @@ -102,12 +102,16 @@ private void GUI_Load(object sender, EventArgs e) // Load projects string projectJson = Settings.Default.ProjectJson; if (!string.IsNullOrEmpty(projectJson) - && File.Exists(projectJson) - && Path.GetFileName(projectJson) == "project.json") + && File.Exists(projectJson) ) { + bool smithboxProject = false; + if ( Path.GetFileName(projectJson) != "project.json") + { + smithboxProject = true; + } try { - LoadProject(projectJson); + LoadProject(projectJson, smithboxProject); } catch (Exception ex) { @@ -163,26 +167,31 @@ private void openProjectToolStripMenuItem_Click(object sender, EventArgs e) } SharedControls.HideTip(); OpenFileDialog ofd = new OpenFileDialog(); - ofd.Filter = "DSMapStudio Project File|project.json|All files|*.*"; + ofd.Filter = "DSMapStudio Project File|project.json|Smithbox Project File|*.json|All files|*.*"; if (ofd.ShowDialog() != DialogResult.OK) { return; } string projectJson = ofd.FileName; - if (Path.GetFileName(projectJson) != "project.json") - { - return; - } - try - { - LoadProject(projectJson); - ManuallySelectedProject = true; - Settings.Default.ProjectJson = projectJson; - Settings.Default.Save(); - } - catch (Exception ex) + + if (Path.GetExtension(projectJson) == ".json") { - ScrollDialog.Show(this, ex.ToString()); + bool smithboxProject = false; + if (Path.GetFileName(projectJson) != "project.json") + { + smithboxProject = true; + } + try + { + LoadProject(projectJson, smithboxProject); + ManuallySelectedProject = true; + Settings.Default.ProjectJson = projectJson; + Settings.Default.Save(); + } + catch (Exception ex) + { + ScrollDialog.Show(this, ex.ToString()); + } } } @@ -197,10 +206,10 @@ private void clearProjectToolStripMenuItem_Click(object sender, EventArgs e) clearProjectToolStripMenuItem.Enabled = false; } - private void LoadProject(string projectJson) + private void LoadProject(string projectJson, bool smithboxProject) { // projectJson should be a valid project file. Callers should handle exceptions. - CurrentDefaultProject = ProjectSettingsFile.LoadProjectFile(projectJson); + CurrentDefaultProject = ProjectSettingsFile.LoadProjectFile(projectJson, smithboxProject); if (CurrentDefaultProject.ProjectEventDirectory != null) { DirectoryProjects[CurrentDefaultProject.ProjectEventDirectory] = CurrentDefaultProject; diff --git a/DarkScript3/ProjectSettingsFile.cs b/DarkScript3/ProjectSettingsFile.cs index 3ab04a0..2f1fe6f 100644 --- a/DarkScript3/ProjectSettingsFile.cs +++ b/DarkScript3/ProjectSettingsFile.cs @@ -16,6 +16,9 @@ public class ProjectSettingsFile public ProjectSettings Settings { get; set; } // Project file path, which exists public string FilePath { get; set; } + // Project directory path, which is null if it it does not exist or is not supported. + // Used for Smithbox 2.0.0, which stores project files outside of the project directory. + public string ProjectDirectory { get; set; } // Project event directory path, which is null if it is not supported. // If present, it but may not exist, but the outer directory should. public string ProjectEventDirectory { get; set; } @@ -63,6 +66,16 @@ public class ProjectSettings public GameType GameType { get; set; } = GameType.Undefined; } + // Smithbox 2.0 project files have a different structure + // https://github.com/vawser/Smithbox/blob/main/src/Smithbox.Program/Core/ProjectSettings.cs + public class SmithboxProjectSettings + { + public string ProjectName { get; set; } = ""; + public string ProjectPath { get; set; } = ""; + public string DataPath { get; set; } = ""; + public GameType ProjectType { get; set; } = GameType.Undefined; + } + private static readonly GameType[] eventDirGames = new[] { GameType.DarkSoulsPTDE, GameType.DarkSoulsRemastered, @@ -85,12 +98,19 @@ public class ProjectSettings // Expects a fully specified valid project JSON path. // This may throw an exception. - public static ProjectSettingsFile LoadProjectFile(string projectJsonPath) + public static ProjectSettingsFile LoadProjectFile(string projectJsonPath, bool smithboxProject) { // Wrapper to rewrite exceptions try { - return LoadProject(projectJsonPath); + if (smithboxProject) + { + return LoadSmithboxProject(projectJsonPath); + } + else + { + return LoadDSMapStudioProject(projectJsonPath); + } } catch (JsonException je) { @@ -116,9 +136,25 @@ public static bool TryGetEmevdFileProject(string emevdPath, out ProjectSettingsF string projectJson = Path.Combine(eventParent.FullName, "project.json"); if (File.Exists(projectJson)) { - project = LoadProject(projectJson); + project = LoadDSMapStudioProject(projectJson); return true; } + else + { + // Iterate through Smithbox's list of projects until one with the same project directory is found. + string localAppDataPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Smithbox\\Projects"); + + IEnumerable projectFiles = Directory.EnumerateFiles(localAppDataPath, "*.json"); + + foreach(string currentFile in projectFiles) + { + project = LoadSmithboxProject(Path.Combine(localAppDataPath, currentFile)); + if (project.ProjectDirectory == eventParent.FullName) + { + return true; + } + } + } } } catch (Exception) @@ -129,33 +165,65 @@ public static bool TryGetEmevdFileProject(string emevdPath, out ProjectSettingsF return false; } - private static ProjectSettingsFile LoadProject(string jsonPath) + private static ProjectSettingsFile LoadProject(ProjectSettingsFile file) { - jsonPath = Path.GetFullPath(jsonPath); - string input = File.ReadAllText(jsonPath); - ProjectSettings settings = JsonConvert.DeserializeObject(input); - ProjectSettingsFile file = new ProjectSettingsFile - { - Settings = settings, - FilePath = jsonPath, - }; - if (eventDirGames.Contains(settings.GameType)) + + if (eventDirGames.Contains(file.Settings.GameType)) { - file.ProjectEventDirectory = Path.Combine(Path.GetDirectoryName(jsonPath), "event"); - if (settings.GameRoot != null && Directory.Exists(settings.GameRoot)) + file.ProjectEventDirectory = file.ProjectDirectory == null ? + Path.Combine(Path.GetDirectoryName(file.FilePath), "event") : + Path.Combine(file.ProjectDirectory, "event"); + + if (file.Settings.GameRoot != null && Directory.Exists(file.Settings.GameRoot)) { - string gameDir = Path.Combine(Path.GetFullPath(settings.GameRoot), "event"); + string gameDir = Path.Combine(Path.GetFullPath(file.Settings.GameRoot), "event"); if (Directory.Exists(gameDir)) { file.GameEventDirectory = gameDir; } } } - if (resourcePrefixHint.TryGetValue(settings.GameType, out string prefix)) + if (resourcePrefixHint.TryGetValue(file.Settings.GameType, out string prefix)) { file.ResourcePrefix = prefix; } return file; } + + private static ProjectSettingsFile LoadDSMapStudioProject(string jsonPath) + { + + jsonPath = Path.GetFullPath(jsonPath); + string input = File.ReadAllText(jsonPath); + ProjectSettings settings = JsonConvert.DeserializeObject(input); + ProjectSettingsFile file = new ProjectSettingsFile + { + Settings = settings, + FilePath = jsonPath, + }; + + return LoadProject(file); + } + + private static ProjectSettingsFile LoadSmithboxProject(string jsonPath) + { + jsonPath = Path.GetFullPath(jsonPath); + string input = File.ReadAllText(jsonPath); + SmithboxProjectSettings smithboxSettings = JsonConvert.DeserializeObject(input); + ProjectSettingsFile file = new ProjectSettingsFile + { + // Convert Smithbox 2.0.0 Project settings into DSMapStudio settings for easy compat. + Settings = new ProjectSettings + { + ProjectName = smithboxSettings.ProjectName, + GameRoot = smithboxSettings.DataPath, + GameType = smithboxSettings.ProjectType + }, + FilePath = jsonPath, + ProjectDirectory = smithboxSettings.ProjectPath + }; + + return LoadProject(file); + } } }