From 791b3f354b378769bffe623b05f1305c91b77101 Mon Sep 17 00:00:00 2001 From: rtk0c Date: Fri, 3 Jun 2022 23:30:01 -0700 Subject: Changeset: 64 [WIP] Rename directories --- source/Game/EditorCommandPalette.cpp | 406 ----------------------------------- 1 file changed, 406 deletions(-) delete mode 100644 source/Game/EditorCommandPalette.cpp (limited to 'source/Game/EditorCommandPalette.cpp') diff --git a/source/Game/EditorCommandPalette.cpp b/source/Game/EditorCommandPalette.cpp deleted file mode 100644 index 0e7b894..0000000 --- a/source/Game/EditorCommandPalette.cpp +++ /dev/null @@ -1,406 +0,0 @@ -#include "EditorCommandPalette.hpp" - -#include "AppConfig.hpp" -#include "EditorUtils.hpp" -#include "FuzzyMatch.hpp" -#include "Utils.hpp" - -#include -#include -#include -#include -#include -#include - -#define IMGUI_DEFINE_MATH_OPERATORS -#include - -using namespace std::literals; - -bool EditorCommandExecuteContext::IsInitiated() const { - return mCommand != nullptr; -} - -const EditorCommand* EditorCommandExecuteContext::GetCurrentCommand() const { - return mCommand; -} - -void EditorCommandExecuteContext::Initiate(const EditorCommand& command) { - if (mCommand == nullptr) { - mCommand = &command; - } -} - -void EditorCommandExecuteContext::Prompt(std::vector options) { - assert(mCommand != nullptr); - mCurrentOptions = std::move(options); - ++mDepth; -} - -void EditorCommandExecuteContext::Finish() { - assert(mCommand != nullptr); - mCommand = nullptr; - mCurrentOptions.clear(); - mDepth = 0; -} - -int EditorCommandExecuteContext::GetExecutionDepth() const { - return mDepth; -} - -struct EditorCommandPalette::SearchResult { - int itemIndex; - int score; - int matchCount; - uint8_t matches[32]; -}; - -struct EditorCommandPalette::Item { - bool hovered = false; - bool held = false; -}; - -EditorCommandPalette::EditorCommandPalette() = default; -EditorCommandPalette::~EditorCommandPalette() = default; - -namespace P6503_UNITY_ID { -std::string MakeCommandName(std::string_view category, std::string_view name) { - std::string result; - constexpr auto infix = ": "sv; - result.reserve(category.size() + infix.size() + name.size()); - result.append(category); - result.append(infix); - result.append(name); - return result; -} -} // namespace P6503_UNITY_ID - -void EditorCommandPalette::AddCommand(std::string_view category, std::string_view name, EditorCommand command) { - command.name = P6503_UNITY_ID::MakeCommandName(category, name); - - auto location = std::lower_bound( - mCommands.begin(), - mCommands.end(), - command, - [](const EditorCommand& a, const EditorCommand& b) -> bool { - return a.name < b.name; - }); - auto iter = mCommands.insert(location, std::move(command)); - - InvalidateSearchResults(); -} - -void EditorCommandPalette::RemoveCommand(std::string_view category, std::string_view name) { - auto commandName = P6503_UNITY_ID::MakeCommandName(category, name); - RemoveCommand(commandName); -} - -void EditorCommandPalette::RemoveCommand(const std::string& commandName) { - struct Comparator { - bool operator()(const EditorCommand& command, const std::string& str) const { - return command.name < str; - } - - bool operator()(const std::string& str, const EditorCommand& command) const { - return str < command.name; - } - }; - - auto range = std::equal_range(mCommands.begin(), mCommands.end(), commandName, Comparator{}); - mCommands.erase(range.first, range.second); - - InvalidateSearchResults(); -} - -void EditorCommandPalette::Show(bool* open) { - // Center window horizontally, align top vertically - ImGui::SetNextWindowPos(ImVec2(ImGui::GetMainViewport()->Size.x / 2, 0), ImGuiCond_Always, ImVec2(0.5f, 0.0f)); - ImGui::SetNextWindowSizeRelScreen(0.3f, 0.0f); - - ImGui::Begin("Command Palette", open, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoTitleBar); - float width = ImGui::GetWindowContentRegionMax().x - ImGui::GetWindowContentRegionMin().x; - - if (!ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows) || mShouldCloseNextFrame) { - // Close popup when user unfocused the command palette window (clicking elsewhere) - // or some action requested closing this window - mShouldCloseNextFrame = false; - if (open) { - *open = false; - } - } - - if (ImGui::IsWindowAppearing() || mFocusSearchBox) { - mFocusSearchBox = false; - - // Focus the search box when user first brings command palette window up - // Note: this only affects the next frame - ImGui::SetKeyboardFocusHere(0); - } - ImGui::SetNextItemWidth(width); - if (ImGui::InputText("##", &mSearchText)) { - // Search string updated, update search results - - mFocusedItemId = 0; - mSearchResults.clear(); - - size_t itemCount; - if (mExeCtx.GetExecutionDepth() == 0) { - itemCount = mCommands.size(); - } else { - itemCount = mExeCtx.mCurrentOptions.size(); - } - - for (size_t i = 0; i < itemCount; ++i) { - const char* text; - if (mExeCtx.GetExecutionDepth() == 0) { - text = mCommands[i].name.c_str(); - } else { - text = mExeCtx.mCurrentOptions[i].c_str(); - } - - SearchResult result{ - .itemIndex = (int)i, - }; - if (FuzzyMatch::Search(mSearchText.c_str(), text, result.score, result.matches, std::size(result.matches), result.matchCount)) { - mSearchResults.push_back(result); - } - } - - std::sort( - mSearchResults.begin(), - mSearchResults.end(), - [](const SearchResult& a, const SearchResult& b) -> bool { - // We want the biggest element first - return a.score > b.score; - }); - } - - ImGui::BeginChild("SearchResults", ImVec2(width, 300), false, ImGuiWindowFlags_AlwaysAutoResize); - auto window = ImGui::GetCurrentWindow(); - - auto& io = ImGui::GetIO(); - auto dlSharedData = ImGui::GetDrawListSharedData(); - - auto textColor = ImGui::GetColorU32(ImGuiCol_Text); - auto itemHoveredColor = ImGui::GetColorU32(ImGuiCol_HeaderHovered); - auto itemActiveColor = ImGui::GetColorU32(ImGuiCol_HeaderActive); - auto itemSelectedColor = ImGui::GetColorU32(ImGuiCol_Header); - - int itemCount = GetItemCount(); - if (mItems.size() < itemCount) { - mItems.resize(itemCount); - } - - // Flag used to delay item selection until after the loop ends - bool selectFocusedItem = false; - for (size_t i = 0; i < itemCount; ++i) { - auto id = window->GetID(static_cast(i)); - - ImVec2 size{ - ImGui::GetContentRegionAvail().x, - dlSharedData->Font->FontSize, - }; - ImRect rect{ - window->DC.CursorPos, - window->DC.CursorPos + ImGui::CalcItemSize(size, 0.0f, 0.0f), - }; - - bool& hovered = mItems[i].hovered; - bool& held = mItems[i].held; - if (held && hovered) { - window->DrawList->AddRectFilled(rect.Min, rect.Max, itemActiveColor); - } else if (hovered) { - window->DrawList->AddRectFilled(rect.Min, rect.Max, itemHoveredColor); - } else if (mFocusedItemId == i) { - window->DrawList->AddRectFilled(rect.Min, rect.Max, itemSelectedColor); - } - - auto item = GetItem(i); - if (item.indexType == SearchResultIndex) { - // Iterating search results: draw text with highlights at matched chars - - auto& searchResult = mSearchResults[i]; - auto textPos = window->DC.CursorPos; - int rangeBegin; - int rangeEnd; - int lastRangeEnd = 0; - - auto DrawCurrentRange = [&]() -> void { - if (rangeBegin != lastRangeEnd) { - // Draw normal text between last highlighted range end and current highlighted range start - auto begin = item.text + lastRangeEnd; - auto end = item.text + rangeBegin; - window->DrawList->AddText(textPos, textColor, begin, end); - - auto segmentSize = dlSharedData->Font->CalcTextSizeA(dlSharedData->Font->FontSize, std::numeric_limits::max(), 0.0f, begin, end); - textPos.x += segmentSize.x; - } - - auto begin = item.text + rangeBegin; - auto end = item.text + rangeEnd; - window->DrawList->AddText(AppConfig::fontBold, AppConfig::fontBold->FontSize, textPos, textColor, begin, end); - - auto segmentSize = AppConfig::fontBold->CalcTextSizeA(AppConfig::fontBold->FontSize, std::numeric_limits::max(), 0.0f, begin, end); - textPos.x += segmentSize.x; - }; - - assert(searchResult.matchCount >= 1); - rangeBegin = searchResult.matches[0]; - rangeEnd = rangeBegin; - - int lastCharIdx = -1; - for (int j = 0; j < searchResult.matchCount; ++j) { - int charIdx = searchResult.matches[j]; - - if (charIdx == lastCharIdx + 1) { - // These 2 indices are equal, extend our current range by 1 - ++rangeEnd; - } else { - DrawCurrentRange(); - lastRangeEnd = rangeEnd; - rangeBegin = charIdx; - rangeEnd = charIdx + 1; - } - - lastCharIdx = charIdx; - } - - // Draw the remaining range (if any) - if (rangeBegin != rangeEnd) { - DrawCurrentRange(); - } - - // Draw the text after the last range (if any) - window->DrawList->AddText(textPos, textColor, item.text + rangeEnd); // Draw until \0 - } else { - // Iterating everything else: draw text as-is, there is no highlights - - window->DrawList->AddText(window->DC.CursorPos, textColor, item.text); - } - - ImGui::ItemSize(rect); - if (!ImGui::ItemAdd(rect, id)) { - continue; - } - if (ImGui::ButtonBehavior(rect, id, &hovered, &held)) { - mFocusedItemId = i; - selectFocusedItem = true; - } - } - - if (ImGui::IsKeyPressed(GLFW_KEY_UP)) { - mFocusedItemId = std::max(mFocusedItemId - 1, 0); - } else if (ImGui::IsKeyPressed(GLFW_KEY_DOWN)) { - mFocusedItemId = std::min(mFocusedItemId + 1, itemCount - 1); - } - if (ImGui::IsKeyPressed(GLFW_KEY_ENTER) || selectFocusedItem) { - SelectFocusedItem(); - } - - ImGui::EndChild(); - - ImGui::End(); -} - -size_t EditorCommandPalette::GetItemCount() const { - int depth = mExeCtx.GetExecutionDepth(); - if (depth == 0) { - if (mSearchText.empty()) { - return mCommands.size(); - } else { - return mSearchResults.size(); - } - } else { - if (mSearchText.empty()) { - return mExeCtx.mCurrentOptions.size(); - } else { - return mSearchResults.size(); - } - } -} - -EditorCommandPalette::ItemInfo EditorCommandPalette::GetItem(size_t idx) const { - ItemInfo option; - - int depth = mExeCtx.GetExecutionDepth(); - if (depth == 0) { - if (mSearchText.empty()) { - option.text = mCommands[idx].name.c_str(); - option.command = &mCommands[idx]; - option.itemId = idx; - option.indexType = DirectIndex; - } else { - auto id = mSearchResults[idx].itemIndex; - option.text = mCommands[id].name.c_str(); - option.command = &mCommands[id]; - option.itemId = id; - option.indexType = SearchResultIndex; - } - option.itemType = CommandItem; - } else { - assert(mExeCtx.GetCurrentCommand() != nullptr); - if (mSearchText.empty()) { - option.text = mExeCtx.mCurrentOptions[idx].c_str(); - option.command = mExeCtx.GetCurrentCommand(); - option.itemId = idx; - option.indexType = DirectIndex; - } else { - auto id = mSearchResults[idx].itemIndex; - option.text = mExeCtx.mCurrentOptions[id].c_str(); - option.command = mExeCtx.GetCurrentCommand(); - option.itemId = id; - option.indexType = SearchResultIndex; - } - option.itemType = CommandOptionItem; - } - - return option; -} - -void EditorCommandPalette::SelectFocusedItem() { - if (mFocusedItemId < 0 || mFocusedItemId >= GetItemCount()) { - return; - } - - auto selectedItem = GetItem(mFocusedItemId); - auto& command = *selectedItem.command; - - int depth = mExeCtx.GetExecutionDepth(); - if (depth == 0) { - assert(!mExeCtx.IsInitiated()); - - mExeCtx.Initiate(*selectedItem.command); - if (command.callback) { - command.callback(mExeCtx); - - mFocusSearchBox = true; - // Don't invalidate search results if no further actions have been requested (returning to global list of commands) - if (mExeCtx.IsInitiated()) { - InvalidateSearchResults(); - } - } else { - mExeCtx.Finish(); - } - } else { - assert(mExeCtx.IsInitiated()); - assert(command.subsequentCallback); - command.subsequentCallback(mExeCtx, selectedItem.itemId); - - mFocusSearchBox = true; - InvalidateSearchResults(); - } - - // This action terminated execution, close command palette window - if (!mExeCtx.IsInitiated()) { - if (command.terminate) { - command.terminate(); - } - mShouldCloseNextFrame = true; - } -} - -void EditorCommandPalette::InvalidateSearchResults() { - mSearchText.clear(); - mSearchResults.clear(); - mFocusedItemId = 0; -} -- cgit v1.2.3-70-g09d2