diff --git a/SHADE_Engine/src/Editor/EditorWindow/AssetBrowser/SHAssetBrowser.cpp b/SHADE_Engine/src/Editor/EditorWindow/AssetBrowser/SHAssetBrowser.cpp index 66b3c962..bd39b38e 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/AssetBrowser/SHAssetBrowser.cpp +++ b/SHADE_Engine/src/Editor/EditorWindow/AssetBrowser/SHAssetBrowser.cpp @@ -14,6 +14,8 @@ #include "Editor/DragDrop/SHDragDrop.hpp" #include "Editor/EditorWindow/MaterialInspector/SHMaterialInspector.h" #include "Editor/EditorWindow/SHEditorWindowManager.h" +#include "Scripting/SHVSUtilities.h" +#include "Scripting/SHScriptEngine.h" namespace SHADE { @@ -249,6 +251,12 @@ namespace SHADE matInspector->OpenMaterial(asset->id); } break; + case AssetType::SCRIPT: + if(auto scriptEngine = SHSystemManager::GetSystem()) + { + scriptEngine->OpenFile(asset->path); + } + break; case AssetType::MAX_COUNT: break; default:; } diff --git a/SHADE_Engine/src/Scripting/SHScriptEngine.cpp b/SHADE_Engine/src/Scripting/SHScriptEngine.cpp index a8417117..96f1539d 100644 --- a/SHADE_Engine/src/Scripting/SHScriptEngine.cpp +++ b/SHADE_Engine/src/Scripting/SHScriptEngine.cpp @@ -306,22 +306,12 @@ namespace SHADE void SHScriptEngine::OpenSolution() { - // Generate csproj file if it doesn't exist - if (!std::filesystem::exists(CSPROJ_PATH)) - { - GenerateScriptsCsProjFile(CSPROJ_PATH); - } + SHVSUtilties::OpenProject(CSPROJ_PATH); + } - // Open it - try - { - SHVSUtilties::OpenFile(CSPROJ_PATH); - } - catch (std::exception& e) - { - SHLOG_ERROR("{}", e.what()); - SHLOG_ERROR("[SHScriptEngine] Failed to open project csproj file."); - } + void SHScriptEngine::OpenFile(const std::filesystem::path& path) + { + SHVSUtilties::OpenFile(CSPROJ_PATH, path); } /*-----------------------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Scripting/SHScriptEngine.h b/SHADE_Engine/src/Scripting/SHScriptEngine.h index d26b360e..9710f5c5 100644 --- a/SHADE_Engine/src/Scripting/SHScriptEngine.h +++ b/SHADE_Engine/src/Scripting/SHScriptEngine.h @@ -218,9 +218,14 @@ namespace SHADE /// File path to the generated file. void GenerateScriptsCsProjFile(const std::filesystem::path& path = CSPROJ_PATH) const; /// - /// Opens the script solution in Visual Studio 2019. + /// Opens the script solution in Visual Studio. /// void OpenSolution(); + /// + /// Opens the file in Visual Studio. + /// + /// + void OpenFile(const std::filesystem::path& path); private: /*-----------------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Scripting/SHVSUtilities.cpp b/SHADE_Engine/src/Scripting/SHVSUtilities.cpp index 3a53fc79..17435d6f 100644 --- a/SHADE_Engine/src/Scripting/SHVSUtilities.cpp +++ b/SHADE_Engine/src/Scripting/SHVSUtilities.cpp @@ -22,18 +22,82 @@ namespace SHADE /* Static Data Members */ /*-----------------------------------------------------------------------------------*/ std::filesystem::path SHVSUtilties::devEnvPath; + HANDLE SHVSUtilties::devEnvInst = nullptr; /*-----------------------------------------------------------------------------------*/ /* Usage Functions */ /*-----------------------------------------------------------------------------------*/ - void SHVSUtilties::OpenFile(const std::filesystem::path& path) + void SHVSUtilties::OpenProject(const std::filesystem::path& projPath) try { - if (devEnvPath.empty()) + // Check if there is an instance + bool devEnvActive = false; + if (devEnvInst) { - devEnvPath = SHVSUtilties::getDevEnvPath(); + + DWORD status; + const auto GET_CODE_STATUS = GetExitCodeProcess(devEnvInst, &status); + devEnvActive = GET_CODE_STATUS && status == STILL_ACTIVE; + } + + // Reuse the existing instance if there is one + if (devEnvActive) + { + // No need to reopen one + return; + } + else + { + if (devEnvPath.empty()) + { + devEnvPath = SHVSUtilties::getDevEnvPath(); + } + + auto absProjPath = std::filesystem::canonical(projPath); + auto pi = SHExecUtilties::ExecProcess(devEnvPath.generic_wstring(), L" " + absProjPath.generic_wstring()); + // Cache the process handle + devEnvInst = pi.hProcess; + } + } + catch (std::exception& e) + { + SHLOG_ERROR("{}", e.what()); + SHLOG_ERROR("[SHVSUtilities] Failed to launch Visual Studio."); + } + + void SHVSUtilties::OpenFile(const std::filesystem::path& projPath, const std::filesystem::path& path) + try + { + // Check if there is an instance + bool devEnvActive = false; + if (devEnvInst) + { + + DWORD status; + const auto GET_CODE_STATUS = GetExitCodeProcess(devEnvInst, &status); + devEnvActive = GET_CODE_STATUS && status == STILL_ACTIVE; + } + + auto absPath = std::filesystem::canonical(path); + + // Reuse the existing instance if there is one + if (devEnvActive) + { + // Edit the file only + SHExecUtilties::ExecProcess(devEnvPath.generic_wstring(), L" /Edit " + absPath.generic_wstring()); + } + else + { + if (devEnvPath.empty()) + { + devEnvPath = SHVSUtilties::getDevEnvPath(); + } + + auto absProjPath = std::filesystem::canonical(projPath); + auto pi = SHExecUtilties::ExecProcess(devEnvPath.generic_wstring(), absProjPath.generic_wstring() + L" " + absPath.generic_wstring()); + // Cache the process handle + devEnvInst = pi.hProcess; } - SHExecUtilties::ExecProcess(devEnvPath.generic_wstring(), L"/Edit " + path.generic_wstring()); } catch (std::exception& e) { @@ -51,7 +115,7 @@ namespace SHADE #else static constexpr int EXCESS_CHARS_COUNT = 2; - const auto RESULT = SHExecUtilties::ExecBlockingPowerShellCommand(L"./vswhere -version \"[15.0,19.0]\" -requires Microsoft.NetCore.Component.DevelopmentTools -find Common7\\\\IDE\\\\devenv.exe | Select-Object -last 1", true, true); + const auto RESULT = SHExecUtilties::ExecBlockingPowerShellCommand(L"./vswhere -version \"[15.0,19.0]\" -requires Microsoft.NetCore.Component.DevelopmentTools -find Common7\\\\IDE\\\\devenv.exe | Select-Object -first 1", true, true); if (RESULT.StdOutput.size() < EXCESS_CHARS_COUNT) { SHLOG_ERROR("[SHVSUtilities] Unable to get path to Visual Studio installation. SHVSUtilities will not work."); diff --git a/SHADE_Engine/src/Scripting/SHVSUtilities.h b/SHADE_Engine/src/Scripting/SHVSUtilities.h index 5613779b..8e702dfd 100644 --- a/SHADE_Engine/src/Scripting/SHVSUtilities.h +++ b/SHADE_Engine/src/Scripting/SHVSUtilities.h @@ -28,10 +28,18 @@ namespace SHADE /* Usage Functions */ /*---------------------------------------------------------------------------------*/ /// - /// Opens the file at the specified path with a new instance of Visual Studio. + /// Opens the project at the specified path with a new or existing instance of Visual + /// Studio if it exists. /// + /// Path to the project file to open. + static void OpenProject(const std::filesystem::path& projPath); + /// + /// Opens the file at the specified path with a new or existing instance of Visual + /// Studio if it exists. + /// + /// Path to the project file to open. /// Path to the file to open. - static void OpenFile(const std::filesystem::path& path); + static void OpenFile(const std::filesystem::path& projPath, const std::filesystem::path& path); private: /*---------------------------------------------------------------------------------*/ @@ -43,6 +51,7 @@ namespace SHADE /* Static Data Members */ /*---------------------------------------------------------------------------------*/ static std::filesystem::path devEnvPath; + static HANDLE devEnvInst; /*---------------------------------------------------------------------------------*/ /* Helper Functions */ diff --git a/SHADE_Engine/src/Tools/Utilities/SHExecUtilities.h b/SHADE_Engine/src/Tools/Utilities/SHExecUtilities.h index 94c853cd..718fc45b 100644 --- a/SHADE_Engine/src/Tools/Utilities/SHExecUtilities.h +++ b/SHADE_Engine/src/Tools/Utilities/SHExecUtilities.h @@ -22,8 +22,17 @@ namespace SHADE /// struct SH_API ExecResult final { + /// + /// Exit code of the process. + /// DWORD Code; + /// + /// Stored text output from the process. + /// std::wstring StdOutput; + /// + /// Stored error text output from the process. + /// std::wstring StdErrOutput; };