diff --git a/CMakeLists.txt b/CMakeLists.txt index 13b6abcf3..cc41470de 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -849,6 +849,10 @@ file(GLOB_RECURSE HYPERSOMNIA_HEADERS_WITH_INTROSPECTED_CLASSES # Conditional inclusion of source files happens here. if(BUILD_WINDOW_FRAMEWORK) + list(APPEND HYPERSOMNIA_CODEBASE_CPPS + "src/augs/window_framework/window_explorer_utils.cpp" + ) + if(USE_GLFW) message("Using GLFW as the window framework.") diff --git a/docs/pages/todo/brainstorm_now.md b/docs/pages/todo/brainstorm_now.md index 5842ca3a5..40eed6852 100644 --- a/docs/pages/todo/brainstorm_now.md +++ b/docs/pages/todo/brainstorm_now.md @@ -6,8 +6,6 @@ permalink: brainstorm_now summary: That which we are brainstorming at the moment. --- -- dont kick spectators during ranked -- disable enemy highlight when dead - we'll have to update to the latest version of yojimbo at some point - optimize de_rambo diff --git a/docs/pages/todo/todo_done.md b/docs/pages/todo/todo_done.md index 085e29d2a..fc62b8058 100644 --- a/docs/pages/todo/todo_done.md +++ b/docs/pages/todo/todo_done.md @@ -6880,3 +6880,5 @@ This will discard your redo history." - test over 192.168.0.1 - show enemy silhouettes in spectator +- dont kick spectators during ranked +- disable enemy highlight when dead diff --git a/src/application/gui/leaderboards_gui.cpp b/src/application/gui/leaderboards_gui.cpp index 7527b7f2d..376ccab96 100644 --- a/src/application/gui/leaderboards_gui.cpp +++ b/src/application/gui/leaderboards_gui.cpp @@ -12,13 +12,9 @@ #include "augs/log.h" #include "application/setups/debugger/detail/maybe_different_colors.h" #include "augs/misc/date_time.h" -#include "augs/network/netcode_sockets.h" -#include "application/nat/nat_detection_settings.h" -#include "application/network/resolve_address.h" #include "application/masterserver/masterserver_requests.h" #include "application/masterserver/gameserver_command_readwrite.h" #include "augs/misc/httplib_utils.h" -#include "application/network/resolve_address.h" #include "augs/readwrite/json_readwrite.h" #include "application/setups/editor/detail/simple_two_tabs.h" #include "augs/window_framework/shell.h" diff --git a/src/augs/window_framework/explorer_utils_winapi.hpp b/src/augs/window_framework/explorer_utils_winapi.hpp index 524dea545..3c20e7cbf 100644 --- a/src/augs/window_framework/explorer_utils_winapi.hpp +++ b/src/augs/window_framework/explorer_utils_winapi.hpp @@ -1,209 +1,221 @@ - -static auto get_filter(const std::vector& filters) { - std::wstring filter; - - auto to_reserve = std::size_t{ 0 }; - - for (const auto& f : filters) { - to_reserve += f.description.length(); - to_reserve += f.extension.length() + 1; - to_reserve += 2; - } - - filter.reserve(to_reserve); - - for (const auto& f : filters) { - const auto description = widen(f.description); - const auto extension = widen(f.extension); - - filter += widen(f.description); - filter.push_back(L'\0'); - filter += L'*'; - filter += widen(f.extension); - filter.push_back(L'\0'); - } - - return filter; -} - -std::optional window::open_file_dialog( - const std::vector& filters, - const std::string& custom_title -) { - const auto filter = get_filter(filters); - const auto title = widen(custom_title); - - OPENFILENAME ofn; // common dialog box structure - std::array szFile; - fill_range(szFile, 0); - - ZeroMemory(&ofn, sizeof(ofn)); - ofn.lStructSize = sizeof(ofn); - ofn.lpstrFile = szFile.data(); - ofn.hwndOwner = platform->get_hwnd(); - ofn.lpstrFile[0] = '\0'; - ofn.nMaxFile = static_cast(szFile.size()); - ofn.lpstrFilter = filter.data(); - ofn.lpstrTitle = title.data(); - ofn.nFilterIndex = 1; - ofn.lpstrFileTitle = NULL; - ofn.nMaxFileTitle = 0; - ofn.lpstrInitialDir = NULL; - ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_EXPLORER | OFN_NOCHANGEDIR; - - // Display the Open dialog box. - - auto show_after = scope_guard([this]() { - ShowWindow(platform->get_hwnd(), SW_SHOW); - }); - - if (GetOpenFileName(&ofn) == TRUE) { - return augs::path_type(ofn.lpstrFile); - } - else { - return std::nullopt; - } -} - -static augs::path_type PickContainer(const std::wstring& custom_title) { - augs::path_type result; - IFileDialog *pfd; - - if (SUCCEEDED(CoCreateInstance(CLSID_FileOpenDialog, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pfd)))) - { - DWORD dwOptions; - if (SUCCEEDED(pfd->GetOptions(&dwOptions))) - { - pfd->SetOptions(dwOptions | FOS_PICKFOLDERS); - } - - pfd->SetTitle(custom_title.c_str()); - - if (SUCCEEDED(pfd->Show(NULL))) - { - IShellItem *psi; - if (SUCCEEDED(pfd->GetResult(&psi))) - { - LPWSTR g_path = nullptr; - if(!SUCCEEDED(psi->GetDisplayName(SIGDN_DESKTOPABSOLUTEPARSING, &g_path))) - { - MessageBox(NULL, L"GetIDListName() failed", NULL, NULL); - } - - result = augs::path_type(g_path); - - psi->Release(); - } - } - pfd->Release(); - } - - return result; -} - -std::optional window::choose_directory_dialog( - const std::string& custom_title -) { - const auto title = widen(custom_title); - const auto choice = PickContainer(title); - - if (!choice.empty()) { - return choice; - } - - return std::nullopt; -} - -std::optional window::save_file_dialog( - const std::vector& filters, - const std::string& custom_title -) { - const auto filter = get_filter(filters); - const auto title = widen(custom_title); - - OPENFILENAME ofn; // common dialog box structure - std::array szFile; - fill_range(szFile, 0); - - ZeroMemory(&ofn, sizeof(ofn)); - ofn.lStructSize = sizeof(ofn); - ofn.lpstrFile = szFile.data(); - ofn.hwndOwner = platform->get_hwnd(); - ofn.lpstrFile[0] = '\0'; - ofn.nMaxFile = static_cast(szFile.size()); - ofn.lpstrFilter = filter.data(); - ofn.lpstrTitle = title.data(); - ofn.nFilterIndex = 1; - ofn.lpstrFileTitle = NULL; - ofn.nMaxFileTitle = 0; - ofn.lpstrInitialDir = NULL; - ofn.Flags = OFN_PATHMUSTEXIST | OFN_EXPLORER | OFN_NOCHANGEDIR | OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT; - - // Display the Open dialog box. - - auto show_after = scope_guard([this]() { - ShowWindow(platform->get_hwnd(), SW_SHOW); - }); - - if (GetSaveFileName(&ofn) == TRUE) { - auto result = augs::path_type(ofn.lpstrFile); - const auto supposed_extension = filters[ofn.nFilterIndex - 1].extension; - - if (supposed_extension != ".*") { - if (result.extension() != supposed_extension) { - result += filters[ofn.nFilterIndex - 1].extension; - } - } - - return result; - } - else { - return std::nullopt; - } -} - -static void BrowseToFile(LPCTSTR filename) -{ - CoInitializeEx(nullptr, COINIT_MULTITHREADED); - - const auto pidl = ILCreateFromPath(filename); - - if (pidl) { - LOG("pidl non-null"); - SHOpenFolderAndSelectItems(pidl,0,0,0); - ILFree(pidl); - } - else { - LOG("pidl is null"); - } - - CoUninitialize(); -} - -void window::reveal_in_explorer(const augs::path_type& p) { - auto absolute_path = std::filesystem::absolute(p); - const auto wide_path = absolute_path.wstring(); - LOG_NVPS(absolute_path.string()); - BrowseToFile(wide_path.c_str()); -} - -static auto to_message_box_button(const int button_code) { - switch (button_code) { - case IDCANCEL: - return message_box_button::CANCEL; - case IDRETRY: - return message_box_button::RETRY; - default: - return message_box_button::CANCEL; - } -} - -message_box_button window::retry_cancel( - const std::string& caption, - const std::string& text -) { - const auto wide_caption = widen(caption); - const auto wide_text = widen(text); - - return to_message_box_button(MessageBox(platform->get_hwnd(), wide_text.c_str(), wide_caption.c_str(), MB_RETRYCANCEL | MB_ICONEXCLAMATION)); +#include +#include +#undef min +#undef max + +namespace augs { + GLFWwindow* get_glfw_window(const window::platform_data& d); + + HWND get_hwnd(const window::platform_data& d) { + return glfwGetWin32Window(get_glfw_window(d)); + } + + static auto get_filter(const std::vector& filters) { + std::wstring filter; + + auto to_reserve = std::size_t{ 0 }; + + for (const auto& f : filters) { + to_reserve += f.description.length(); + to_reserve += f.extension.length() + 1; + to_reserve += 2; + } + + filter.reserve(to_reserve); + + for (const auto& f : filters) { + const auto description = widen(f.description); + const auto extension = widen(f.extension); + + filter += widen(f.description); + filter.push_back(L'\0'); + filter += L'*'; + filter += widen(f.extension); + filter.push_back(L'\0'); + } + + return filter; + } + + std::optional window::open_file_dialog( + const std::vector& filters, + const std::string& custom_title + ) { + const auto filter = get_filter(filters); + const auto title = widen(custom_title); + + OPENFILENAME ofn; // common dialog box structure + std::array szFile; + fill_range(szFile, 0); + + ZeroMemory(&ofn, sizeof(ofn)); + ofn.lStructSize = sizeof(ofn); + ofn.lpstrFile = szFile.data(); + ofn.hwndOwner = get_hwnd(platform); + ofn.lpstrFile[0] = '\0'; + ofn.nMaxFile = static_cast(szFile.size()); + ofn.lpstrFilter = filter.data(); + ofn.lpstrTitle = title.data(); + ofn.nFilterIndex = 1; + ofn.lpstrFileTitle = NULL; + ofn.nMaxFileTitle = 0; + ofn.lpstrInitialDir = NULL; + ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_EXPLORER | OFN_NOCHANGEDIR; + + // Display the Open dialog box. + + auto show_after = scope_guard([this]() { + ShowWindow(get_hwnd(platform), SW_SHOW); + }); + + if (GetOpenFileName(&ofn) == TRUE) { + return augs::path_type(ofn.lpstrFile); + } + else { + return std::nullopt; + } + } + + static augs::path_type PickContainer(const std::wstring& custom_title) { + augs::path_type result; + IFileDialog *pfd; + + if (SUCCEEDED(CoCreateInstance(CLSID_FileOpenDialog, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pfd)))) + { + DWORD dwOptions; + if (SUCCEEDED(pfd->GetOptions(&dwOptions))) + { + pfd->SetOptions(dwOptions | FOS_PICKFOLDERS); + } + + pfd->SetTitle(custom_title.c_str()); + + if (SUCCEEDED(pfd->Show(NULL))) + { + IShellItem *psi; + if (SUCCEEDED(pfd->GetResult(&psi))) + { + LPWSTR g_path = nullptr; + if(!SUCCEEDED(psi->GetDisplayName(SIGDN_DESKTOPABSOLUTEPARSING, &g_path))) + { + MessageBox(NULL, L"GetIDListName() failed", NULL, NULL); + } + + result = augs::path_type(g_path); + + psi->Release(); + } + } + pfd->Release(); + } + + return result; + } + + std::optional window::choose_directory_dialog( + const std::string& custom_title + ) { + const auto title = widen(custom_title); + const auto choice = PickContainer(title); + + if (!choice.empty()) { + return choice; + } + + return std::nullopt; + } + + std::optional window::save_file_dialog( + const std::vector& filters, + const std::string& custom_title + ) { + const auto filter = get_filter(filters); + const auto title = widen(custom_title); + + OPENFILENAME ofn; // common dialog box structure + std::array szFile; + fill_range(szFile, 0); + + ZeroMemory(&ofn, sizeof(ofn)); + ofn.lStructSize = sizeof(ofn); + ofn.lpstrFile = szFile.data(); + ofn.hwndOwner = get_hwnd(platform); + ofn.lpstrFile[0] = '\0'; + ofn.nMaxFile = static_cast(szFile.size()); + ofn.lpstrFilter = filter.data(); + ofn.lpstrTitle = title.data(); + ofn.nFilterIndex = 1; + ofn.lpstrFileTitle = NULL; + ofn.nMaxFileTitle = 0; + ofn.lpstrInitialDir = NULL; + ofn.Flags = OFN_PATHMUSTEXIST | OFN_EXPLORER | OFN_NOCHANGEDIR | OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT; + + // Display the Open dialog box. + + auto show_after = scope_guard([this]() { + ShowWindow(get_hwnd(platform), SW_SHOW); + }); + + if (GetSaveFileName(&ofn) == TRUE) { + auto result = augs::path_type(ofn.lpstrFile); + const auto supposed_extension = filters[ofn.nFilterIndex - 1].extension; + + if (supposed_extension != ".*") { + if (result.extension() != supposed_extension) { + result += filters[ofn.nFilterIndex - 1].extension; + } + } + + return result; + } + else { + return std::nullopt; + } + } + + static void BrowseToFile(LPCTSTR filename) + { + CoInitializeEx(nullptr, COINIT_MULTITHREADED); + + const auto pidl = ILCreateFromPath(filename); + + if (pidl) { + LOG("pidl non-null"); + SHOpenFolderAndSelectItems(pidl,0,0,0); + ILFree(pidl); + } + else { + LOG("pidl is null"); + } + + CoUninitialize(); + } + + void window::reveal_in_explorer(const augs::path_type& p) { + auto absolute_path = std::filesystem::absolute(p); + const auto wide_path = absolute_path.wstring(); + LOG_NVPS(absolute_path.string()); + BrowseToFile(wide_path.c_str()); + } + + static auto to_message_box_button(const int button_code) { + switch (button_code) { + case IDCANCEL: + return message_box_button::CANCEL; + case IDRETRY: + return message_box_button::RETRY; + default: + return message_box_button::CANCEL; + } + } + + message_box_button window::retry_cancel( + const std::string& caption, + const std::string& text + ) { + const auto wide_caption = widen(caption); + const auto wide_text = widen(text); + + return to_message_box_button(MessageBox(get_hwnd(platform), wide_text.c_str(), wide_caption.c_str(), MB_RETRYCANCEL | MB_ICONEXCLAMATION)); + } } diff --git a/src/augs/window_framework/window.h b/src/augs/window_framework/window.h index 8888b463d..9471e0239 100644 --- a/src/augs/window_framework/window.h +++ b/src/augs/window_framework/window.h @@ -60,19 +60,15 @@ namespace augs { #endif #if PLATFORM_WINDOWS || USE_GLFW + public: struct platform_data; + private: std::unique_ptr platform; local_entropy wndproc_queue; void show(); -#if DECLARE_FRIEND_WNDPROC - public: - void handle_wndproc(HWND hwnd, UINT umsg, WPARAM wParam, LPARAM lParam); - private: -#endif - template std::optional handle_event( const H, diff --git a/src/augs/window_framework/window_explorer_utils.cpp b/src/augs/window_framework/window_explorer_utils.cpp new file mode 100644 index 000000000..295765c03 --- /dev/null +++ b/src/augs/window_framework/window_explorer_utils.cpp @@ -0,0 +1,119 @@ +#include "augs/window_framework/window.h" +#include "all_paths.h" +#include "augs/filesystem/file.h" +#include "augs/log.h" +#include "augs/window_framework/shell.h" + +#if PLATFORM_WINDOWS +#include "augs/window_framework/explorer_utils_winapi.hpp" + +#elif PLATFORM_LINUX +#include + +namespace augs { + static std::optional read_chosen_path(const augs::path_type& script_path) { + const auto& temp_result = CACHE_DIR / "last_file_path.txt"; + + try { + const auto result = file_to_string(temp_result); + remove_file(temp_result); + return result; + } + catch (const augs::file_open_error&) { + LOG("Error: %x did not produce %x", script_path, temp_result); + return std::nullopt; + } + } + + static std::optional choose_path(const augs::path_type& script_path) { + if (!augs::exists(script_path)) { + LOG("WARNING! Could not find the script file: %x.", script_path); + return std::nullopt; + } + + augs::shell(script_path); + return read_chosen_path(script_path); + } + + std::optional window::open_file_dialog( + const std::vector& /* filters */, + const std::string& /* custom_title */ + ) { + return choose_path(DETAIL_DIR / "unix/open_file.local"); + } + + std::optional window::save_file_dialog( + const std::vector& /* filters */, + const std::string& /* custom_title */ + ) { + return choose_path(DETAIL_DIR / "unix/save_file.local"); + } + + std::optional window::choose_directory_dialog( + const std::string& /* custom_title */ + ) { + return choose_path(DETAIL_DIR / "unix/choose_directory.local"); + } + + void window::reveal_in_explorer(const augs::path_type& p) { + const auto script_path = DETAIL_DIR / "unix/reveal_file.local"; + + if (!augs::exists(script_path)) { + LOG("WARNING! Could not find the script file: %x.", script_path); + return; + } + + const auto shell_command = typesafe_sprintf("%x \"%x\"", script_path, p.string()); + + std::thread([shell_command](){ augs::shell(shell_command); }).detach(); + } + + message_box_button window::retry_cancel( + const std::string& caption, + const std::string& text + ) { + LOG("RETRY CANCEL!!"); + LOG_NVPS(caption, text); + return message_box_button::CANCEL; + } +} + +#elif PLATFORM_MACOS + +namespace augs { + std::optional window::open_file_dialog( + const std::vector& /* filters */, + const std::string& /* custom_title */ + ) { + return std::nullopt; + } + + std::optional window::save_file_dialog( + const std::vector& /* filters */, + const std::string& /* custom_title */ + ) { + return std::nullopt; + } + + std::optional window::choose_directory_dialog( + const std::string& /* custom_title */ + ) { + return std::nullopt; + } + + message_box_button window::retry_cancel( + const std::string& caption, + const std::string& text + ) { + LOG("RETRY CANCEL!!"); + LOG_NVPS(caption, text); + return message_box_button::CANCEL; + } + + void window::reveal_in_explorer(const augs::path_type& full_path) { + const auto command = typesafe_sprintf("open -R -a Finder \"%x\"", full_path); + shell(command); + } +} + +#endif diff --git a/src/augs/window_framework/window_glfw.cpp b/src/augs/window_framework/window_glfw.cpp index 2bb2e3e0a..455268efb 100644 --- a/src/augs/window_framework/window_glfw.cpp +++ b/src/augs/window_framework/window_glfw.cpp @@ -1,14 +1,5 @@ #include #include - -#if PLATFORM_WINDOWS -#define GLFW_EXPOSE_NATIVE_WIN32 -#include -#include -#undef min -#undef max -#endif - #include "augs/misc/scope_guard.h" #include "augs/window_framework/window.h" #include "augs/window_framework/translate_glfw_enums.h" @@ -50,6 +41,7 @@ struct unhandled_focus { int focused; }; + namespace augs { struct window::platform_data { GLFWwindow* window = nullptr; @@ -64,13 +56,11 @@ namespace augs { std::vector unhandled_window_positions; std::vector unhandled_window_sizes; std::vector unhandled_focuses; - -#if PLATFORM_WINDOWS - auto get_hwnd() const { - return glfwGetWin32Window(window); - } -#endif }; + + GLFWwindow* get_glfw_window(const window::platform_data& d) { + return d.window; + } } struct glfw_callbacks { @@ -434,82 +424,6 @@ namespace augs { } -#if PLATFORM_LINUX - static std::optional read_chosen_path(const augs::path_type& script_path) { - const auto& temp_result = CACHE_DIR / "last_file_path.txt"; - - try { - const auto result = file_to_string(temp_result); - remove_file(temp_result); - return result; - } - catch (const augs::file_open_error&) { - LOG("Error: %x did not produce %x", script_path, temp_result); - return std::nullopt; - } - } - - static std::optional choose_path(const augs::path_type& script_path) { - if (!augs::exists(script_path)) { - LOG("WARNING! Could not find the script file: %x.", script_path); - return std::nullopt; - } - - augs::shell(script_path); - return read_chosen_path(script_path); - } -#endif - -#if PLATFORM_WINDOWS - #include "explorer_utils_winapi.hpp" -#else - std::optional window::open_file_dialog( - const std::vector& /* filters */, - const std::string& /* custom_title */ - ) { -#if PLATFORM_LINUX - return choose_path(DETAIL_DIR / "unix/open_file.local"); -#else - return std::nullopt; -#endif - } - - std::optional window::save_file_dialog( - const std::vector& /* filters */, - const std::string& /* custom_title */ - ) { -#if PLATFORM_LINUX - return choose_path(DETAIL_DIR / "unix/save_file.local"); -#else - return std::nullopt; -#endif - } - - std::optional window::choose_directory_dialog( - const std::string& /* custom_title */ - ) { -#if PLATFORM_LINUX - return choose_path(DETAIL_DIR / "unix/choose_directory.local"); -#else - return std::nullopt; -#endif - } - - message_box_button window::retry_cancel( - const std::string& caption, - const std::string& text - ) { - LOG("RETRY CANCEL!!"); - LOG_NVPS(caption, text); - return message_box_button::CANCEL; - } - - void window::reveal_in_explorer(const augs::path_type& full_path) { - const auto command = typesafe_sprintf("open -R -a Finder \"%x\"", full_path); - shell(command); - } -#endif - void window::set_cursor_visible_impl(bool) { /* Implemented with GLFW_CURSOR_DISABLED */ } diff --git a/src/augs/window_framework/window_x.cpp b/src/augs/window_framework/window_x.cpp index e35958d76..0c69303ec 100644 --- a/src/augs/window_framework/window_x.cpp +++ b/src/augs/window_framework/window_x.cpp @@ -975,63 +975,6 @@ namespace augs { } } - static std::optional read_chosen_path(const augs::path_type& script_path) { - const auto& temp_result = CACHE_DIR / "last_file_path.txt"; - - try { - const auto result = file_to_string(temp_result); - remove_file(temp_result); - return result; - } - catch (const augs::file_open_error&) { - LOG("Error: %x did not produce %x", script_path, temp_result); - return std::nullopt; - } - } - - static std::optional choose_path(const augs::path_type& script_path) { - if (!augs::exists(script_path)) { - LOG("WARNING! Could not find the script file: %x.", script_path); - return std::nullopt; - } - - augs::shell(script_path); - return read_chosen_path(script_path); - } - - std::optional window::open_file_dialog( - const std::vector& /* filters */, - const std::string& /* custom_title */ - ) { - return choose_path(DETAIL_DIR / "unix/open_file.local"); - } - - std::optional window::save_file_dialog( - const std::vector& /* filters */, - const std::string& /* custom_title */ - ) { - return choose_path(DETAIL_DIR / "unix/save_file.local"); - } - - std::optional window::choose_directory_dialog( - const std::string& /* custom_title */ - ) { - return choose_path(DETAIL_DIR / "unix/choose_directory.local"); - } - - void window::reveal_in_explorer(const augs::path_type& p) { - const auto script_path = DETAIL_DIR / "unix/reveal_file.local"; - - if (!augs::exists(script_path)) { - LOG("WARNING! Could not find the script file: %x.", script_path); - return; - } - - const auto shell_command = typesafe_sprintf("%x \"%x\"", script_path, p.string()); - - std::thread([shell_command](){ augs::shell(shell_command); }).detach(); - } - xywhi window::get_display() const { if (Screen* s = DefaultScreenOfDisplay(display)) { return { 0, 0, s->width, s->height }; @@ -1040,15 +983,6 @@ namespace augs { return {}; } - message_box_button window::retry_cancel( - const std::string& caption, - const std::string& text - ) { - LOG("RETRY CANCEL!!"); - LOG_NVPS(caption, text); - return message_box_button::CANCEL; - } - int window::get_refresh_rate() { return -1; }