diff --git a/Sources/OvEditor/src/OvEditor/Panels/AssetBrowser.cpp b/Sources/OvEditor/src/OvEditor/Panels/AssetBrowser.cpp index e7178925c..1434881a8 100644 --- a/Sources/OvEditor/src/OvEditor/Panels/AssetBrowser.cpp +++ b/Sources/OvEditor/src/OvEditor/Panels/AssetBrowser.cpp @@ -39,6 +39,7 @@ #include #include #include +#include #include #include @@ -135,6 +136,15 @@ namespace return !relativePath.empty() && *relativePath.begin() != ".."; } + bool ValidateFolderPath(const std::filesystem::path& p_path, const std::string& p_actionName) + { + if (std::filesystem::exists(p_path) && std::filesystem::is_directory(p_path)) + return true; + + OVLOG_ERROR(std::format("Cannot perform '{}' because the target folder was deleted externally", p_actionName)); + return false; + } + class TexturePreview : public OvUI::Plugins::IPlugin { private: @@ -185,6 +195,13 @@ namespace nameEditor.selectAllOnClick = true; renameMenu.ClickedEvent +=[this, &nameEditor] { + // Check if the item still exists before allowing rename + if (!std::filesystem::exists(filePath)) + { + OVLOG_ERROR("Cannot rename this item because it was deleted externally"); + return; + } + nameEditor.content = filePath.stem().string(); if (!std::filesystem::is_directory(filePath)) @@ -198,6 +215,12 @@ namespace nameEditor.EnterPressedEvent += [this](std::string p_newName) { + if (!std::filesystem::exists(filePath)) + { + OVLOG_ERROR("Cannot complete rename because the item was deleted externally"); + return; + } + if (!std::filesystem::is_directory(filePath)) { p_newName += filePath.extension().string(); @@ -257,6 +280,9 @@ namespace void CreateNewShader(const std::string& p_shaderName, std::optional p_type) { + if (!ValidateFolderPath(filePath, "Create shader")) + return; + const auto finalPath = FindAvailableFilePath(filePath / (p_shaderName + ".ovfx")); if (p_type.has_value()) @@ -296,6 +322,9 @@ namespace std::optional> p_setupCallback ) { + if (!ValidateFolderPath(filePath, "Create material")) + return; + OvCore::Resources::Material material; if (p_type.has_value()) @@ -342,6 +371,8 @@ namespace auto& showInExplorer = CreateWidget("Show in explorer"); showInExplorer.ClickedEvent += [this] { + if (!ValidateFolderPath(filePath, "Show in explorer")) + return; OvTools::Utils::SystemCalls::ShowInExplorer(filePath.string()); }; @@ -350,6 +381,9 @@ namespace auto& importAssetHere = CreateWidget("Import Here..."); importAssetHere.ClickedEvent += [this] { + if (!ValidateFolderPath(filePath, "Import")) + return; + if (EDITOR_EXEC(ImportAssetAtLocation(filePath.string()))) { OvUI::Widgets::Layout::TreeNode* pluginOwner = reinterpret_cast(userData); @@ -412,6 +446,8 @@ namespace createAtmosphereMaterialMenu.ClickedEvent += [&createAtmosphereMaterial] { createAtmosphereMaterial.content = ""; }; createFolder.EnterPressedEvent += [this](std::string newFolderName) { + if (!ValidateFolderPath(filePath, "Create folder")) + return; const auto finalPath = FindAvailableFilePath(filePath / newFolderName); std::filesystem::create_directory(finalPath); ItemAddedEvent.Invoke(finalPath); @@ -419,6 +455,8 @@ namespace }; createScene.EnterPressedEvent += [this](std::string newSceneName) { + if (!ValidateFolderPath(filePath, "Create scene")) + return; const auto finalPath = FindAvailableFilePath(filePath / (newSceneName + ".ovscene")); auto emptyScene = OvCore::SceneSystem::Scene{}; @@ -432,6 +470,8 @@ namespace }; createPartialShader.EnterPressedEvent += [this](std::string newShaderName) { + if (!ValidateFolderPath(filePath, "Create shader")) + return; const auto finalPath = FindAvailableFilePath(filePath / (newShaderName + ".ovfxh")); { @@ -443,6 +483,8 @@ namespace }; createScript.EnterPressedEvent += [this](std::string p_newName) { + if (!ValidateFolderPath(filePath, "Create script")) + return; std::erase_if(p_newName, [](char c) { return std::find(kAllowedFilenameChars.begin(), kAllowedFilenameChars.end(), c) == kAllowedFilenameChars.end(); }); @@ -507,8 +549,9 @@ namespace { EDITOR_EXEC(PropagateFolderDestruction(filePath.string())); std::filesystem::remove_all(filePath); - DestroyedEvent.Invoke(filePath); } + + DestroyedEvent.Invoke(filePath); } } @@ -1045,6 +1088,13 @@ void OvEditor::Panels::AssetBrowser::ConsiderItem(OvUI::Widgets::Layout::TreeNod treeNode.OpenedEvent += [this, &treeNode, path, p_isEngineItem] { treeNode.RemoveAllWidgets(); std::filesystem::path updatedPath = std::filesystem::path{path}.parent_path() / treeNode.name; + + if (!std::filesystem::exists(updatedPath) || !std::filesystem::is_directory(updatedPath)) + { + OVLOG_ERROR("Folder was deleted externally: " + updatedPath.string()); + return; + } + ParseFolder(treeNode, std::filesystem::directory_entry(updatedPath), p_isEngineItem); };