Skip to content

Editor Layouts Management #431

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 13 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions Sources/Overload/OvEditor/include/OvEditor/Core/EditorActions.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,23 @@ namespace OvEditor::Core
*/
void ResetLayout();

/**
* Save the editor layout to the given configuration file
* @param p_filePath
*/
void SaveLayout(const std::filesystem::path& p_filePath);

/**
* Save the current editor layout to the last used configuration file
*/
void SaveCurrentLayout();

/**
* Set and load the editor layout from the given configuration file
* @param p_filePath
*/
void SetLayout(const std::filesystem::path& p_filePath);

/**
* Defines the scene view camera speed
* @param p_speed
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,5 +92,6 @@ namespace OvEditor::Settings
inline static Property<float> TranslationSnapUnit = { 1.0f };
inline static Property<float> RotationSnapUnit = { 15.0f };
inline static Property<float> ScalingSnapUnit = { 1.0f };
inline static Property<std::string> LatestLayout = { "" };
};
}
2 changes: 1 addition & 1 deletion Sources/Overload/OvEditor/src/OvEditor/Core/Context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ OvEditor::Core::Context::Context(const std::string& p_projectPath, const std::st
uiManager->EnableDocking(true);

if (!std::filesystem::exists(OvTools::Utils::SystemCalls::GetPathToAppdata() + "\\OverloadTech\\OvEditor\\layout.ini"))
uiManager->ResetLayout("Config\\layout.ini");
uiManager->ResetToDefaultLayout();

/* Audio */
audioEngine = std::make_unique<OvAudio::Core::AudioEngine>(projectAssetsPath);
Expand Down
5 changes: 5 additions & 0 deletions Sources/Overload/OvEditor/src/OvEditor/Core/Editor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,11 @@ void OvEditor::Core::Editor::SetupUI()

m_canvas.MakeDockspace(true);
m_context.uiManager->SetCanvas(m_canvas);

if (!Settings::EditorSettings::LatestLayout.Get().empty() && std::filesystem::exists(Settings::EditorSettings::LatestLayout.Get()))
{
m_context.uiManager->SetLayout(Settings::EditorSettings::LatestLayout.Get());
}
}

void OvEditor::Core::Editor::PreUpdate()
Expand Down
17 changes: 16 additions & 1 deletion Sources/Overload/OvEditor/src/OvEditor/Core/EditorActions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -374,7 +374,22 @@ void OvEditor::Core::EditorActions::SetActorSpawnMode(EActorSpawnMode p_value)

void OvEditor::Core::EditorActions::ResetLayout()
{
DelayAction([this]() {m_context.uiManager->ResetLayout("Config\\layout.ini"); });
DelayAction([this]() {m_context.uiManager->ResetToDefaultLayout(); });
}

void OvEditor::Core::EditorActions::SaveLayout(const std::filesystem::path& p_filePath)
{
DelayAction([&]() {m_context.uiManager->SaveLayout(p_filePath); });
}

void OvEditor::Core::EditorActions::SaveCurrentLayout()
{
DelayAction([&]() {m_context.uiManager->SaveCurrentLayout(); });
}

void OvEditor::Core::EditorActions::SetLayout(const std::filesystem::path& p_filePath)
{
DelayAction([&]() {m_context.uiManager->SetLayout(p_filePath); });
}

void OvEditor::Core::EditorActions::SetSceneViewCameraSpeed(int p_speed)
Expand Down
79 changes: 77 additions & 2 deletions Sources/Overload/OvEditor/src/OvEditor/Panels/MenuBar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
* @licence: MIT
*/

#include <filesystem>

#include <OvTools/Utils/SystemCalls.h>

#include <OvCore/ECS/Components/CCamera.h>
Expand All @@ -30,6 +32,7 @@
#include "OvEditor/Core/EditorActions.h"
#include "OvEditor/Settings/EditorSettings.h"
#include "OvEditor/Utils/ActorCreationMenu.h"
#include "OvUI/Plugins/ContextualMenu.h"

using namespace OvUI::Panels;
using namespace OvUI::Widgets;
Expand Down Expand Up @@ -197,8 +200,80 @@ void OvEditor::Panels::MenuBar::CreateSettingsMenu()

void OvEditor::Panels::MenuBar::CreateLayoutMenu()
{
auto& layoutMenu = CreateWidget<MenuList>("Layout");
layoutMenu.CreateWidget<MenuItem>("Reset").ClickedEvent += EDITOR_BIND(ResetLayout);
auto& layoutMenuList = CreateWidget<MenuList>("Layout");

auto& uiManager = *EDITOR_CONTEXT(uiManager);
const std::filesystem::path& layoutsPath = uiManager.GetLayoutsPath();

auto& saveMenuItem = layoutMenuList.CreateWidget<MenuItem>("Save");
saveMenuItem.ClickedEvent += EDITOR_BIND(SaveCurrentLayout);

auto& saveNewMenuList = layoutMenuList.CreateWidget<MenuList>("Save New");
auto& layoutInputText = saveNewMenuList.CreateWidget<InputFields::InputText>("Layout Name");
layoutInputText.selectAllOnClick = true;
layoutInputText.EnterPressedEvent += [&layoutsPath](std::string p_input)
{
if (p_input.empty())
return;

auto& uiManager = *EDITOR_CONTEXT(uiManager);
EDITOR_EXEC(DelayAction(std::bind(&OvUI::Core::UIManager::SaveLayout, &uiManager, layoutsPath / (p_input + ".ini")), 1));
Copy link
Member

@adriengivry adriengivry Apr 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After this call, we should also update Settings::EditorSettings::LatestLayout, otherwise creating a new layout and exiting, result in the LatestLayout still being the previous one.

Suggested change
EDITOR_EXEC(DelayAction(std::bind(&OvUI::Core::UIManager::SaveLayout, &uiManager, layoutsPath / (p_input + ".ini")), 1));
EDITOR_EXEC(DelayAction(std::bind(&OvUI::Core::UIManager::SaveLayout, &uiManager, layoutsPath / (p_input + ".ini")), 1));
Settings::EditorSettings::LatestLayout = p_input;

};

auto& loadMenuList = layoutMenuList.CreateWidget<MenuList>("Load");

loadMenuList.ClickedEvent += [&]
{
loadMenuList.RemoveAllWidgets();

for (const auto& entry : std::filesystem::directory_iterator(layoutsPath))
{
if (entry.is_regular_file() && entry.path().extension() == ".ini")
{
auto& layoutMenuItem = loadMenuList.CreateWidget<MenuItem>(entry.path().stem().string());
layoutMenuItem.name = entry.path().stem().string();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could display which layout is currently selected with a checkmark

Suggested change
layoutMenuItem.name = entry.path().stem().string();
layoutMenuItem.name = entry.path().stem().string();
layoutMenuItem.checkable = true;
layoutMenuItem.checked = Settings::EditorSettings::LatestLayout.Get() == entry.path().stem().string();

image

Copy link
Member

@adriengivry adriengivry Apr 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, since with this change we can show the currently selected layout, maybe we should always have a "Default" option in the "Load" list (instead of "Reset" outside of the list), and the "Default" option would have no contextual menu (so it cannot be deleted/renamed)


layoutMenuItem.ClickedEvent += [entry]
{
auto& uiManager = *EDITOR_CONTEXT(uiManager);
EDITOR_EXEC(DelayAction(std::bind(&OvUI::Core::UIManager::SetLayout, &uiManager, entry.path()), 1));

Settings::EditorSettings::LatestLayout = entry.path().string();
};

auto& contextualMenu = layoutMenuItem.AddPlugin<OvUI::Plugins::ContextualMenu>();
auto& deleteMenuItem = contextualMenu.CreateWidget<MenuItem>("Delete");

deleteMenuItem.ClickedEvent += [entry, &layoutMenuItem]
{
auto& uiManager = *EDITOR_CONTEXT(uiManager);
EDITOR_EXEC(DelayAction(std::bind(&OvUI::Core::UIManager::DeleteLayout, &uiManager, entry.path()), 1));
layoutMenuItem.enabled = false;

};
auto& renameToMenuList = contextualMenu.CreateWidget<MenuList>("Rename to...");

auto& renameInputText = renameToMenuList.CreateWidget<InputFields::InputText>("");
renameInputText.content = entry.path().stem().string();
renameInputText.selectAllOnClick = true;

renameInputText.EnterPressedEvent += [entry, &layoutMenuItem, &layoutsPath, &contextualMenu](std::string p_newName)
{
if (p_newName.empty())
return;

layoutMenuItem.name = p_newName;

auto& uiManager = *EDITOR_CONTEXT(uiManager);
EDITOR_EXEC(DelayAction(std::bind(&OvUI::Core::UIManager::RenameLayout, &uiManager, entry.path(), layoutsPath / (p_newName + ".ini")), 1));

contextualMenu.Close();
};
}
}
};

layoutMenuList.CreateWidget<MenuItem>("Reset").ClickedEvent += EDITOR_BIND(ResetLayout);
}

void OvEditor::Panels::MenuBar::CreateHelpMenu()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ void OvEditor::Settings::EditorSettings::Save()
iniFile.Add("translation_snap_unit", TranslationSnapUnit.Get());
iniFile.Add("rotation_snap_unit", RotationSnapUnit.Get());
iniFile.Add("scaling_snap_unit", ScalingSnapUnit.Get());
iniFile.Add("latest_layout", LatestLayout.Get());
iniFile.Rewrite();
}

Expand All @@ -57,4 +58,5 @@ void OvEditor::Settings::EditorSettings::Load()
LoadIniEntry<float>(iniFile, "translation_snap_unit", TranslationSnapUnit);
LoadIniEntry<float>(iniFile, "rotation_snap_unit", RotationSnapUnit);
LoadIniEntry<float>(iniFile, "scaling_snap_unit", ScalingSnapUnit);
LoadIniEntry<std::string>(iniFile, "latest_layout", LatestLayout);
}
61 changes: 54 additions & 7 deletions Sources/Overload/OvUI/include/OvUI/Core/UIManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#pragma once

#include <filesystem>
#include <string>
#include <unordered_map>

Expand Down Expand Up @@ -77,7 +78,7 @@ namespace OvUI::Core
/**
* Defines a filename for the editor layout save file
*/
void SetEditorLayoutSaveFilename(const std::string& p_filename);
void SetEditorLayoutSaveFilename(const std::filesystem::path& p_filePath);

/**
* Defines a frequency (in seconds) for the auto saving system of the editor layout
Expand All @@ -96,11 +97,53 @@ namespace OvUI::Core
*/
void EnableDocking(bool p_value);

/**
* Reset the UI layout to the given configuration file
* @param p_config
*/
void ResetLayout(const std::string & p_config) const;
/**
* Reset the UI layout to the default configuration file
* @param p_config
*/
void ResetToDefaultLayout() const;

/**
* Reset the UI layout to the given configuration file
* @param p_config
*/
void ResetLayout(const std::string& p_config) const;

/**
* Load the UI layout from the given configuration file
* @param p_fileName
*/
void LoadLayout(const std::string& p_fileName);

/**
* Save the UI layout to the given configuration file
* @param p_filePath
*/
void SaveLayout(const std::filesystem::path& p_filePath);

/**
* Save the current UI layout to the last used configuration file
*/
void SaveCurrentLayout();

/**
* Set and load the UI layout from the given configuration file
* @param p_filePath
*/
void SetLayout(const std::filesystem::path& p_filePath);

/**
* Delete the UI layout configuration file
* @param p_filePath
*/
void DeleteLayout(const std::filesystem::path& p_filePath);

/**
* Rename a UI layout configuration file
* @param p_filePath
* @param p_newFilePath
*/
void RenameLayout(const std::filesystem::path& p_filePath, const std::filesystem::path& p_newFilePath);

/**
* Return true if the docking system is enabled
Expand All @@ -124,6 +167,8 @@ namespace OvUI::Core
*/
void Render();

const std::filesystem::path& GetLayoutsPath() const;

private:
void PushCurrentFont();
void PopCurrentFont();
Expand All @@ -132,6 +177,8 @@ namespace OvUI::Core
bool m_dockingState;
Modules::Canvas* m_currentCanvas = nullptr;
std::unordered_map<std::string, ImFont*> m_fonts;
std::string m_layoutSaveFilename = "imgui.ini";
std::filesystem::path m_layoutSaveFilename = "imgui.ini";
const std::filesystem::path m_defaultLayout;
const std::filesystem::path m_layoutsPath;
};
}
Loading