From ac24b5b04df3fa2be06bb0edaf96b34359efe082 Mon Sep 17 00:00:00 2001 From: Christian Heinemann Date: Mon, 22 Apr 2024 20:54:47 +0200 Subject: [PATCH 01/16] README.md updated --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 963b0b041..1854171bd 100644 --- a/README.md +++ b/README.md @@ -67,7 +67,7 @@ Further information and artwork: An Nvidia graphics card with compute capability 6.0 or higher is needed. Please check [https://en.wikipedia.org/wiki/CUDA#GPUs_supported](https://en.wikipedia.org/wiki/CUDA#GPUs_supported). # 💽 Installer -Installer for Windows: [alien-installer.msi](https://alien-project.org/media/files/alien-installer.msi) (Updated: 2024-03-16) +Installer for Windows: [alien-installer.msi](https://alien-project.org/media/files/alien-installer.msi) (Updated: 2024-04-22) In the case that the program crashes for an unknown reason, please refer to the troubleshooting section in [alien-project.org/downloads.html](https://alien-project.org/downloads.html). From 115b0162b673426b42cdfb1f21b6c0ddf433b44b Mon Sep 17 00:00:00 2001 From: Christian Heinemann Date: Mon, 22 Apr 2024 21:39:33 +0200 Subject: [PATCH 02/16] track real-time info in CLI --- source/Cli/Main.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source/Cli/Main.cpp b/source/Cli/Main.cpp index 2e7308ca3..abf6b9804 100644 --- a/source/Cli/Main.cpp +++ b/source/Cli/Main.cpp @@ -51,6 +51,7 @@ int main(int argc, char** argv) simController->newSimulation(simData.auxiliaryData.timestep, simData.auxiliaryData.generalSettings, simData.auxiliaryData.simulationParameters); simController->setClusteredSimulationData(simData.mainData); simController->setStatisticsHistory(simData.statistics); + simController->setRealTime(simData.auxiliaryData.realTime); std::cout << "Device: " << simController->getGpuName() << std::endl; std::cout << "Start simulation" << std::endl; @@ -68,6 +69,7 @@ int main(int argc, char** argv) simData.mainData = simController->getClusteredSimulationData(); simData.auxiliaryData.simulationParameters = simController->getSimulationParameters(); simData.statistics = simController->getStatisticsHistory().getCopiedData(); + simData.auxiliaryData.realTime = simController->getRealTime(); if (outputFilename.empty()) { std::cout << "No output file given." << std::endl; return 1; From 4ba214a375d0771c8ad9882736f5731d9f51664b Mon Sep 17 00:00:00 2001 From: Will Allen Date: Mon, 22 Apr 2024 16:32:51 -0500 Subject: [PATCH 03/16] update vcpkg for building on windows --- external/vcpkg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/external/vcpkg b/external/vcpkg index d8783052c..9224b3bbd 160000 --- a/external/vcpkg +++ b/external/vcpkg @@ -1 +1 @@ -Subproject commit d8783052cbf85bb5b1777b58b998c88d99357943 +Subproject commit 9224b3bbd8df24999d85720b1d005dd6f969ade0 From 5704c2ab57c46f74eb7a6cc27fdf5f8be7a09287 Mon Sep 17 00:00:00 2001 From: Christian Heinemann Date: Tue, 23 Apr 2024 15:37:47 +0200 Subject: [PATCH 04/16] Update README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 1854171bd..2335c7b9d 100644 --- a/README.md +++ b/README.md @@ -137,9 +137,10 @@ A short architectural overview of the source code can be found in the [documenta ALIEN has been initiated, mainly developed and maintained by [Christian Heinemann](mailto:heinemann.christian@gmail.com). Thanks to all the others who contributed to this repository: - [tlemo](https://github.com/tlemo) -- [TheBarret](https://github.com/TheBarret) - [mpersano](https://github.com/mpersano) - [dguerizec](https://github.com/dguerizec) +- [Will Allen](https://github.com/willjallen) +- [TheBarret](https://github.com/TheBarret) The following external libraries are used: - [CUDA Toolkit](https://developer.nvidia.com/cuda-toolkit) From 2506565d17eebb31cf8f6a0b9aaaa152dcc3d4ba Mon Sep 17 00:00:00 2001 From: Christian Heinemann Date: Tue, 23 Apr 2024 21:06:17 +0200 Subject: [PATCH 05/16] vcpkg.json updated --- vcpkg.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/vcpkg.json b/vcpkg.json index 63efa832a..b60899381 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -4,7 +4,7 @@ "dependencies": [ { "name": "glew", - "version>=": "2.2.0" + "version>=": "2.2.0#3" }, { "name": "imgui", @@ -29,7 +29,7 @@ }, { "name": "stb", - "version>=": "2020-09-14#1" + "version>=": "2023-04-11#1" }, { "name": "boost-core", @@ -53,7 +53,7 @@ }, { "name": "cereal", - "version>=": "1.3.0" + "version>=": "1.3.2" }, { "name": "gtest", @@ -67,12 +67,12 @@ }, { "name": "openssl", - "version>=": "1.1.1l" + "version>=": "3.3.0" }, { "name": "cli11" } ], - "builtin-baseline": "d48ac9aa527620d43fb3b3327d0b9e054de203c2" + "builtin-baseline": "9224b3bbd8df24999d85720b1d005dd6f969ade0" } \ No newline at end of file From 5441138b8dc90cd4006ca74bc140e0deddde3a96 Mon Sep 17 00:00:00 2001 From: Christian Heinemann Date: Tue, 23 Apr 2024 21:12:46 +0200 Subject: [PATCH 06/16] Update ubuntu-ci.yml --- .github/workflows/ubuntu-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ubuntu-ci.yml b/.github/workflows/ubuntu-ci.yml index f7f8f7e99..14da8b45f 100644 --- a/.github/workflows/ubuntu-ci.yml +++ b/.github/workflows/ubuntu-ci.yml @@ -40,7 +40,7 @@ jobs: setupOnly: true # Location of the vcpkg as submodule of the repository. vcpkgDirectory: '${{ github.workspace }}/vcpkg' - vcpkgGitCommitId: '50fd3d9957195575849a49fa591e645f1d8e7156' + vcpkgGitCommitId: '9224b3bbd8df24999d85720b1d005dd6f969ade0' # Since the cache must be invalidated when content of the vcpkg.json file changes, let's # compute its hash and append this to the computed cache's key. appendedCacheKey: ${{ hashFiles( '**/vcpkg.json' ) }} From 40ef92ec03a2b78d1b147520613dab508298e7fe Mon Sep 17 00:00:00 2001 From: Christian Heinemann Date: Tue, 23 Apr 2024 21:43:29 +0200 Subject: [PATCH 07/16] compile errors fixed --- external/ImFileDialog/CMakeLists.txt | 2 -- source/Gui/BrowserWindow.cpp | 6 +++--- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/external/ImFileDialog/CMakeLists.txt b/external/ImFileDialog/CMakeLists.txt index 40d4b8c2d..6f91a2e92 100644 --- a/external/ImFileDialog/CMakeLists.txt +++ b/external/ImFileDialog/CMakeLists.txt @@ -7,5 +7,3 @@ target_include_directories(im_file_dialog PUBLIC .) find_package(imgui CONFIG REQUIRED) target_link_libraries(im_file_dialog imgui::imgui) -find_path(STB_INCLUDE_DIRS "stb.h") -target_include_directories(im_file_dialog PRIVATE ${STB_INCLUDE_DIRS}) diff --git a/source/Gui/BrowserWindow.cpp b/source/Gui/BrowserWindow.cpp index 8ecfbbabd..5ba75083d 100644 --- a/source/Gui/BrowserWindow.cpp +++ b/source/Gui/BrowserWindow.cpp @@ -1043,7 +1043,7 @@ void _BrowserWindow::processEmojiWindow() } ImGui::SetCursorPosY(ImGui::GetCursorPosY() + scale(8.0f)); - if (AlienImGui::Button("More", ImGui::GetContentRegionAvailWidth())) { + if (AlienImGui::Button("More", ImGui::GetContentRegionAvail().x)) { _showAllEmojis = true; } } @@ -1110,8 +1110,8 @@ void _BrowserWindow::processShortenedText(std::string const& text, bool bold) { } auto& styleRepository = StyleRepository::getInstance(); auto textSize = ImGui::CalcTextSize(substrings.at(0).c_str()); - auto needDetailButton = textSize.x > ImGui::GetContentRegionAvailWidth() || substrings.size() > 1; - auto cursorPos = ImGui::GetCursorPosX() + ImGui::GetContentRegionAvailWidth() - styleRepository.scale(15.0f); + auto needDetailButton = textSize.x > ImGui::GetContentRegionAvail().x || substrings.size() > 1; + auto cursorPos = ImGui::GetCursorPosX() + ImGui::GetContentRegionAvail().x - styleRepository.scale(15.0f); if (bold) { ImGui::PushFont(styleRepository.getSmallBoldFont()); } From 2f3b3b6412976061b2f63d7daf50880e71e58b38 Mon Sep 17 00:00:00 2001 From: Christian Heinemann Date: Tue, 23 Apr 2024 22:00:19 +0200 Subject: [PATCH 08/16] Revert "compile errors fixed" This reverts commit 40ef92ec03a2b78d1b147520613dab508298e7fe. Revert "Update ubuntu-ci.yml" This reverts commit 5441138b8dc90cd4006ca74bc140e0deddde3a96. Revert "vcpkg.json updated" This reverts commit 2506565d17eebb31cf8f6a0b9aaaa152dcc3d4ba. --- .github/workflows/ubuntu-ci.yml | 2 +- external/ImFileDialog/CMakeLists.txt | 2 ++ source/Gui/BrowserWindow.cpp | 6 +++--- vcpkg.json | 10 +++++----- 4 files changed, 11 insertions(+), 9 deletions(-) diff --git a/.github/workflows/ubuntu-ci.yml b/.github/workflows/ubuntu-ci.yml index 14da8b45f..f7f8f7e99 100644 --- a/.github/workflows/ubuntu-ci.yml +++ b/.github/workflows/ubuntu-ci.yml @@ -40,7 +40,7 @@ jobs: setupOnly: true # Location of the vcpkg as submodule of the repository. vcpkgDirectory: '${{ github.workspace }}/vcpkg' - vcpkgGitCommitId: '9224b3bbd8df24999d85720b1d005dd6f969ade0' + vcpkgGitCommitId: '50fd3d9957195575849a49fa591e645f1d8e7156' # Since the cache must be invalidated when content of the vcpkg.json file changes, let's # compute its hash and append this to the computed cache's key. appendedCacheKey: ${{ hashFiles( '**/vcpkg.json' ) }} diff --git a/external/ImFileDialog/CMakeLists.txt b/external/ImFileDialog/CMakeLists.txt index 6f91a2e92..40d4b8c2d 100644 --- a/external/ImFileDialog/CMakeLists.txt +++ b/external/ImFileDialog/CMakeLists.txt @@ -7,3 +7,5 @@ target_include_directories(im_file_dialog PUBLIC .) find_package(imgui CONFIG REQUIRED) target_link_libraries(im_file_dialog imgui::imgui) +find_path(STB_INCLUDE_DIRS "stb.h") +target_include_directories(im_file_dialog PRIVATE ${STB_INCLUDE_DIRS}) diff --git a/source/Gui/BrowserWindow.cpp b/source/Gui/BrowserWindow.cpp index 5ba75083d..8ecfbbabd 100644 --- a/source/Gui/BrowserWindow.cpp +++ b/source/Gui/BrowserWindow.cpp @@ -1043,7 +1043,7 @@ void _BrowserWindow::processEmojiWindow() } ImGui::SetCursorPosY(ImGui::GetCursorPosY() + scale(8.0f)); - if (AlienImGui::Button("More", ImGui::GetContentRegionAvail().x)) { + if (AlienImGui::Button("More", ImGui::GetContentRegionAvailWidth())) { _showAllEmojis = true; } } @@ -1110,8 +1110,8 @@ void _BrowserWindow::processShortenedText(std::string const& text, bool bold) { } auto& styleRepository = StyleRepository::getInstance(); auto textSize = ImGui::CalcTextSize(substrings.at(0).c_str()); - auto needDetailButton = textSize.x > ImGui::GetContentRegionAvail().x || substrings.size() > 1; - auto cursorPos = ImGui::GetCursorPosX() + ImGui::GetContentRegionAvail().x - styleRepository.scale(15.0f); + auto needDetailButton = textSize.x > ImGui::GetContentRegionAvailWidth() || substrings.size() > 1; + auto cursorPos = ImGui::GetCursorPosX() + ImGui::GetContentRegionAvailWidth() - styleRepository.scale(15.0f); if (bold) { ImGui::PushFont(styleRepository.getSmallBoldFont()); } diff --git a/vcpkg.json b/vcpkg.json index b60899381..63efa832a 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -4,7 +4,7 @@ "dependencies": [ { "name": "glew", - "version>=": "2.2.0#3" + "version>=": "2.2.0" }, { "name": "imgui", @@ -29,7 +29,7 @@ }, { "name": "stb", - "version>=": "2023-04-11#1" + "version>=": "2020-09-14#1" }, { "name": "boost-core", @@ -53,7 +53,7 @@ }, { "name": "cereal", - "version>=": "1.3.2" + "version>=": "1.3.0" }, { "name": "gtest", @@ -67,12 +67,12 @@ }, { "name": "openssl", - "version>=": "3.3.0" + "version>=": "1.1.1l" }, { "name": "cli11" } ], - "builtin-baseline": "9224b3bbd8df24999d85720b1d005dd6f969ade0" + "builtin-baseline": "d48ac9aa527620d43fb3b3327d0b9e054de203c2" } \ No newline at end of file From c25626db5dd79c8a5f97f846ac863f9e3ea13005 Mon Sep 17 00:00:00 2001 From: Christian Heinemann Date: Thu, 25 Apr 2024 21:16:02 +0200 Subject: [PATCH 09/16] accentuate new simulations --- source/Base/GlobalSettings.cpp | 29 ++++++--- source/Base/GlobalSettings.h | 20 +++--- source/Gui/AlienImGui.cpp | 9 ++- source/Gui/AlienImGui.h | 1 + source/Gui/AlienWindow.cpp | 4 +- source/Gui/AutosaveController.cpp | 4 +- source/Gui/BrowserWindow.cpp | 74 ++++++++++++++++------- source/Gui/BrowserWindow.h | 4 ++ source/Gui/GenomeEditorWindow.cpp | 8 +-- source/Gui/GpuSettingsDialog.cpp | 8 +-- source/Gui/ImageToPatternDialog.cpp | 4 +- source/Gui/LogWindow.cpp | 4 +- source/Gui/LoginDialog.cpp | 16 ++--- source/Gui/NewSimulationDialog.cpp | 4 +- source/Gui/PatternAnalysisDialog.cpp | 4 +- source/Gui/PatternEditorWindow.cpp | 4 +- source/Gui/ShaderWindow.cpp | 12 ++-- source/Gui/SimulationParametersWindow.cpp | 12 ++-- source/Gui/SimulationView.cpp | 4 +- source/Gui/StatisticsWindow.cpp | 24 ++++---- source/Gui/StyleRepository.h | 9 +-- source/Gui/UploadSimulationDialog.cpp | 5 +- source/Gui/WindowController.cpp | 20 +++--- source/Network/NetworkService.cpp | 4 +- 24 files changed, 174 insertions(+), 113 deletions(-) diff --git a/source/Base/GlobalSettings.cpp b/source/Base/GlobalSettings.cpp index 104f46f17..199fb4ada 100644 --- a/source/Base/GlobalSettings.cpp +++ b/source/Base/GlobalSettings.cpp @@ -153,7 +153,7 @@ void GlobalSettings::setDebugMode(bool value) const _impl->_debugMode = value; } -bool GlobalSettings::getBoolState(std::string const& key, bool defaultValue) +bool GlobalSettings::getBool(std::string const& key, bool defaultValue) { bool result; #ifdef _WIN32 @@ -164,7 +164,7 @@ bool GlobalSettings::getBoolState(std::string const& key, bool defaultValue) return result; } -void GlobalSettings::setBoolState(std::string const& key, bool value) +void GlobalSettings::setBool(std::string const& key, bool value) { #ifdef _WIN32 setBoolToWinReg(key, value); @@ -173,7 +173,7 @@ void GlobalSettings::setBoolState(std::string const& key, bool value) #endif } -int GlobalSettings::getIntState(std::string const& key, int defaultValue) +int GlobalSettings::getInt(std::string const& key, int defaultValue) { int result; #ifdef _WIN32 @@ -184,7 +184,7 @@ int GlobalSettings::getIntState(std::string const& key, int defaultValue) return result; } -void GlobalSettings::setIntState(std::string const& key, int value) +void GlobalSettings::setInt(std::string const& key, int value) { #ifdef _WIN32 setIntToWinReg(key, value); @@ -193,7 +193,7 @@ void GlobalSettings::setIntState(std::string const& key, int value) #endif } -float GlobalSettings::getFloatState(std::string const& key, float defaultValue) +float GlobalSettings::getFloat(std::string const& key, float defaultValue) { float result; #ifdef _WIN32 @@ -204,7 +204,7 @@ float GlobalSettings::getFloatState(std::string const& key, float defaultValue) return result; } -void GlobalSettings::setFloatState(std::string const& key, float value) +void GlobalSettings::setFloat(std::string const& key, float value) { #ifdef _WIN32 setFloatToWinReg(key, value); @@ -213,7 +213,7 @@ void GlobalSettings::setFloatState(std::string const& key, float value) #endif } -std::string GlobalSettings::getStringState(std::string const& key, std::string const& defaultValue) +std::string GlobalSettings::getString(std::string const& key, std::string const& defaultValue) { std::string result; #ifdef _WIN32 @@ -224,7 +224,7 @@ std::string GlobalSettings::getStringState(std::string const& key, std::string c return result; } -void GlobalSettings::setStringState(std::string const& key, std::string value) +void GlobalSettings::setString(std::string const& key, std::string value) { #ifdef _WIN32 setStringToWinReg(key, value); @@ -233,6 +233,19 @@ void GlobalSettings::setStringState(std::string const& key, std::string value) #endif } +std::vector GlobalSettings::getStringVector(std::string const& key, std::vector const& defaultValue) +{ + auto joinedString = getString(key, boost::join(defaultValue, "\\")); + std::vector result; + boost::split(result, joinedString, boost::is_any_of("\\")); + return result; +} + +void GlobalSettings::setStringVector(std::string const& key, std::vector value) +{ + setString(key, boost::join(value, "\\")); +} + GlobalSettings::GlobalSettings() { _impl = std::make_shared(); diff --git a/source/Base/GlobalSettings.h b/source/Base/GlobalSettings.h index 8363bcf31..cc5b97f78 100644 --- a/source/Base/GlobalSettings.h +++ b/source/Base/GlobalSettings.h @@ -2,6 +2,7 @@ #include #include +#include struct GlobalSettingsImpl; @@ -16,17 +17,20 @@ class GlobalSettings GlobalSettings(GlobalSettings const&) = delete; void operator=(GlobalSettings const&) = delete; - bool getBoolState(std::string const& key, bool defaultValue); - void setBoolState(std::string const& key, bool value); + bool getBool(std::string const& key, bool defaultValue); + void setBool(std::string const& key, bool value); - int getIntState(std::string const& key, int defaultValue); - void setIntState(std::string const& key, int value); + int getInt(std::string const& key, int defaultValue); + void setInt(std::string const& key, int value); - float getFloatState(std::string const& key, float defaultValue); - void setFloatState(std::string const& key, float value); + float getFloat(std::string const& key, float defaultValue); + void setFloat(std::string const& key, float value); - std::string getStringState(std::string const& key, std::string const& defaultValue); - void setStringState(std::string const& key, std::string value); + std::string getString(std::string const& key, std::string const& defaultValue); + void setString(std::string const& key, std::string value); + + std::vector getStringVector(std::string const& key, std::vector const& defaultValue); + void setStringVector(std::string const& key, std::vector value); private: GlobalSettings(); diff --git a/source/Gui/AlienImGui.cpp b/source/Gui/AlienImGui.cpp index f2e8f5a15..506142224 100644 --- a/source/Gui/AlienImGui.cpp +++ b/source/Gui/AlienImGui.cpp @@ -1491,12 +1491,17 @@ void AlienImGui::NeuronSelection( ImGui::EndChild(); } -void AlienImGui::OnlineSymbol() +ImVec4 AlienImGui::GetBlinkingColor() { auto counter = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); counter = (((counter % 2000) + 2000) % 2000); auto color = ImColor::HSV(0.0f, counter < 1000 ? toFloat(counter) / 1000.0f : 2.0f - toFloat(counter) / 1000.0f, 1.0f); - ImGui::PushStyleColor(ImGuiCol_Text, color.Value); + return color.Value; +} + +void AlienImGui::OnlineSymbol() +{ + ImGui::PushStyleColor(ImGuiCol_Text, GetBlinkingColor()); ImGui::Text(ICON_FA_GENDERLESS); ImGui::PopStyleColor(); } diff --git a/source/Gui/AlienImGui.h b/source/Gui/AlienImGui.h index 2b7f48a98..28082ec53 100644 --- a/source/Gui/AlienImGui.h +++ b/source/Gui/AlienImGui.h @@ -314,6 +314,7 @@ class AlienImGui std::vector& biases, std::vector& activationFunctions); + static ImVec4 GetBlinkingColor(); static void OnlineSymbol(); static void LastDayOnlineSymbol(); diff --git a/source/Gui/AlienWindow.cpp b/source/Gui/AlienWindow.cpp index bdca2d3bb..c7966506e 100644 --- a/source/Gui/AlienWindow.cpp +++ b/source/Gui/AlienWindow.cpp @@ -11,12 +11,12 @@ _AlienWindow::_AlienWindow(std::string const& title, std::string const& settings : _title(title) , _settingsNode(settingsNode) { - _on = GlobalSettings::getInstance().getBoolState(settingsNode + ".active", defaultOn); + _on = GlobalSettings::getInstance().getBool(settingsNode + ".active", defaultOn); } _AlienWindow::~_AlienWindow() { - GlobalSettings::getInstance().setBoolState(_settingsNode + ".active", _on); + GlobalSettings::getInstance().setBool(_settingsNode + ".active", _on); } void _AlienWindow::process() diff --git a/source/Gui/AutosaveController.cpp b/source/Gui/AutosaveController.cpp index 5253e1db5..5486a4c2b 100644 --- a/source/Gui/AutosaveController.cpp +++ b/source/Gui/AutosaveController.cpp @@ -15,12 +15,12 @@ _AutosaveController::_AutosaveController(SimulationController const& simControll : _simController(simController) { _startTimePoint = std::chrono::steady_clock::now(); - _on = GlobalSettings::getInstance().getBoolState("controllers.auto save.active", true); + _on = GlobalSettings::getInstance().getBool("controllers.auto save.active", true); } _AutosaveController::~_AutosaveController() { - GlobalSettings::getInstance().setBoolState("controllers.auto save.active", _on); + GlobalSettings::getInstance().setBool("controllers.auto save.active", _on); } void _AutosaveController::shutdown() diff --git a/source/Gui/BrowserWindow.cpp b/source/Gui/BrowserWindow.cpp index 8ecfbbabd..92be17c3a 100644 --- a/source/Gui/BrowserWindow.cpp +++ b/source/Gui/BrowserWindow.cpp @@ -67,9 +67,10 @@ _BrowserWindow::_BrowserWindow( , _temporalControlWindow(temporalControlWindow) , _editorController(editorController) { - _currentWorkspace.resourceType = GlobalSettings::getInstance().getIntState("windows.browser.resource type", _currentWorkspace.resourceType); - _currentWorkspace.workspaceType = GlobalSettings::getInstance().getIntState("windows.browser.workspace type", _currentWorkspace.workspaceType); - _userTableWidth = GlobalSettings::getInstance().getFloatState("windows.browser.user table width", scale(UserTableWidth)); + auto& settings = GlobalSettings::getInstance(); + _currentWorkspace.resourceType = settings.getInt("windows.browser.resource type", _currentWorkspace.resourceType); + _currentWorkspace.workspaceType = settings.getInt("windows.browser.workspace type", _currentWorkspace.workspaceType); + _userTableWidth = settings.getFloat("windows.browser.user table width", scale(UserTableWidth)); int numEmojis = 0; for (int i = 0; i < NumEmojiBlocks; ++i) { @@ -98,16 +99,18 @@ namespace _BrowserWindow::~_BrowserWindow() { - GlobalSettings::getInstance().setIntState("windows.browser.resource type", _currentWorkspace.resourceType); - GlobalSettings::getInstance().setIntState("windows.browser.workspace type", _currentWorkspace.workspaceType); - GlobalSettings::getInstance().setBoolState("windows.browser.first start", false); - GlobalSettings::getInstance().setFloatState("windows.browser.user table width", _userTableWidth); + auto& settings = GlobalSettings::getInstance(); + settings.setInt("windows.browser.resource type", _currentWorkspace.resourceType); + settings.setInt("windows.browser.workspace type", _currentWorkspace.workspaceType); + settings.setBool("windows.browser.first start", false); + settings.setFloat("windows.browser.user table width", _userTableWidth); for (auto const& [workspaceId, workspace] : _workspaces) { - GlobalSettings::getInstance().setStringState( + settings.setString( "windows.browser.collapsed folders." + networkResourceTypeToString.at(workspaceId.resourceType) + "." + workspaceTypeToString.at(workspaceId.workspaceType), NetworkResourceService::convertFolderNamesToSettings(workspace.collapsedFolderNames)); } + settings.setStringVector("windows.browser.simulation ids", getAllSimulationIds()); } void _BrowserWindow::registerCyclicReferences( @@ -119,19 +122,22 @@ void _BrowserWindow::registerCyclicReferences( _uploadSimulationDialog = uploadSimulationDialog; _editSimulationDialog = editSimulationDialog; - auto firstStart = GlobalSettings::getInstance().getBoolState("windows.browser.first start", true); + auto firstStart = GlobalSettings::getInstance().getBool("windows.browser.first start", true); refreshIntern(firstStart); for (auto& [workspaceId, workspace] : _workspaces) { auto initialCollapsedSimulationFolders = NetworkResourceService::convertFolderNamesToSettings(NetworkResourceService::getFolderNames(workspace.rawTOs)); - auto collapsedSimulationFolders = GlobalSettings::getInstance().getStringState( + auto collapsedSimulationFolders = GlobalSettings::getInstance().getString( "windows.browser.collapsed folders." + networkResourceTypeToString.at(workspaceId.resourceType) + "." + workspaceTypeToString.at(workspaceId.workspaceType), initialCollapsedSimulationFolders); workspace.collapsedFolderNames = NetworkResourceService::convertSettingsToFolderNames(collapsedSimulationFolders); createTreeTOs(workspace); } + + auto simIds = GlobalSettings::getInstance().getStringVector("windows.browser.simulation ids", getAllSimulationIds()); + _simIdsFromLastSession = std::unordered_set(simIds.begin(), simIds.end()); } void _BrowserWindow::onRefresh() @@ -149,6 +155,11 @@ BrowserCache& _BrowserWindow::getSimulationCache() return _simulationCache; } +void _BrowserWindow::registerUploadedSimulation(std::string const& id) +{ + _simIdsFromLastSession.insert(id); +} + void _BrowserWindow::refreshIntern(bool withRetry) { try { @@ -757,6 +768,16 @@ bool _BrowserWindow::processResourceNameField(NetworkResourceTreeTO const& treeT AlienImGui::Tooltip("Visible in the public workspace"); } ImGui::SameLine(); + + if (!_simIdsFromLastSession.contains(leaf.rawTO->id)) { + ImGui::PushFont(StyleRepository::getInstance().getSmallBoldFont()); + ImGui::PushStyleColor(ImGuiCol_Text, AlienImGui::GetBlinkingColor()); + AlienImGui::Text("NEW"); + ImGui::PopStyleColor(); + ImGui::SameLine(); + ImGui::PopFont(); + } + processShortenedText(leaf.leafName, true); } else { auto& folder = treeTO->getFolder(); @@ -764,7 +785,7 @@ bool _BrowserWindow::processResourceNameField(NetworkResourceTreeTO const& treeT result |= processFolderTreeSymbols(treeTO, collapsedFolderNames); processShortenedText(treeTO->folderNames.back()); ImGui::SameLine(); - ImGui::PushStyleColor(ImGuiCol_Text, (ImU32)Const::BrowserFolderPropertiesTextColor); + ImGui::PushStyleColor(ImGuiCol_Text, (ImU32)Const::BrowserResourcePropertiesTextColor); std::string resourceTypeString = [&] { if (treeTO->type == NetworkResourceType_Simulation) { return folder.numLeafs == 1 ? "sim" : "sims"; @@ -863,7 +884,7 @@ void _BrowserWindow::processReactionList(NetworkResourceTreeTO const& treeTO) auto pos = ImGui::GetCursorScreenPos(); ImGui::SetCursorScreenPos({pos.x + scale(3.0f), pos.y}); - ImGui::PushStyleColor(ImGuiCol_Text, (ImU32)Const::BrowserFolderPropertiesTextColor); + ImGui::PushStyleColor(ImGuiCol_Text, (ImU32)Const::BrowserResourcePropertiesTextColor); AlienImGui::Text("(" + std::to_string(folder.numReactions) + ")"); ImGui::PopStyleColor(); } @@ -940,7 +961,7 @@ void _BrowserWindow::processVersionField(NetworkResourceTreeTO const& treeTO) bool _BrowserWindow::processFolderTreeSymbols(NetworkResourceTreeTO const& treeTO, std::set>& collapsedFolderNames) { auto result = false; - ImGui::PushStyleColor(ImGuiCol_Text, (ImU32)Const::BrowserFolderSymbolColor); + ImGui::PushStyleColor(ImGuiCol_Text, (ImU32)Const::BrowserResourceSymbolColor); ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor::HSV(0, 0, 0, 0)); auto const& treeSymbols = treeTO->treeSymbols; for (auto const& folderLine : treeSymbols) { @@ -963,37 +984,37 @@ bool _BrowserWindow::processFolderTreeSymbols(NetworkResourceTreeTO const& treeT ImGui::GetWindowDrawList()->AddRectFilled( ImVec2(pos.x + style.FramePadding.x + scale(6.0f), pos.y), ImVec2(pos.x + style.FramePadding.x + scale(7.5f), pos.y + scale(RowHeight) + style.FramePadding.y), - Const::BrowserFolderLineColor); + Const::BrowserResourceLineColor); ImGui::Dummy({scale(20.0f), 0}); } break; case FolderTreeSymbols::Branch: { ImGui::GetWindowDrawList()->AddRectFilled( ImVec2(pos.x + style.FramePadding.x + scale(6.0f), pos.y), ImVec2(pos.x + style.FramePadding.x + scale(7.5f), pos.y + scale(RowHeight) + style.FramePadding.y), - Const::BrowserFolderLineColor); + Const::BrowserResourceLineColor); ImGui::GetWindowDrawList()->AddRectFilled( ImVec2(pos.x + style.FramePadding.x + scale(7.5f), pos.y + scale(RowHeight) / 2 - style.FramePadding.y), ImVec2(pos.x + style.FramePadding.x + scale(20.0f), pos.y + scale(RowHeight) / 2 - style.FramePadding.y + scale(1.5f)), - Const::BrowserFolderLineColor); + Const::BrowserResourceLineColor); ImGui::GetWindowDrawList()->AddRectFilled( ImVec2(pos.x + style.FramePadding.x + scale(20.0f - 0.5f), pos.y + scale(RowHeight) / 2 - style.FramePadding.y - scale(0.5f)), ImVec2(pos.x + style.FramePadding.x + scale(20.0f + 2.0f), pos.y + scale(RowHeight) / 2 - style.FramePadding.y + scale(2.0f)), - Const::BrowserFolderLineColor); + Const::BrowserResourceLineColor); ImGui::Dummy({scale(20.0f), 0}); } break; case FolderTreeSymbols::End: { ImGui::GetWindowDrawList()->AddRectFilled( ImVec2(pos.x + style.FramePadding.x + scale(6.0f), pos.y), ImVec2(pos.x + style.FramePadding.x + scale(7.5f), pos.y + scale(RowHeight) / 2 - style.FramePadding.y + scale(1.5f)), - Const::BrowserFolderLineColor); + Const::BrowserResourceLineColor); ImGui::GetWindowDrawList()->AddRectFilled( ImVec2(pos.x + style.FramePadding.x + scale(7.5f), pos.y + scale(RowHeight) / 2 - style.FramePadding.y), ImVec2(pos.x + style.FramePadding.x + scale(20.0f), pos.y + scale(RowHeight) / 2 - style.FramePadding.y + scale(1.5f)), - Const::BrowserFolderLineColor); + Const::BrowserResourceLineColor); ImGui::GetWindowDrawList()->AddRectFilled( ImVec2(pos.x + style.FramePadding.x + scale(20.0f - 0.5f), pos.y + scale(RowHeight) / 2 - style.FramePadding.y - scale(0.5f)), ImVec2(pos.x + style.FramePadding.x + scale(20.0f + 2.0f), pos.y + scale(RowHeight) / 2 - style.FramePadding.y + scale(2.0f)), - Const::BrowserFolderLineColor); + Const::BrowserResourceLineColor); ImGui::Dummy({scale(20.0f), 0}); } break; case FolderTreeSymbols::None: { @@ -1429,6 +1450,17 @@ std::string _BrowserWindow::getUserNamesToEmojiType(std::string const& resourceI return boost::algorithm::join(userNames, ", "); } +std::vector _BrowserWindow::getAllSimulationIds() const +{ + std::unordered_set result; + for (auto const& workspace : _workspaces | std::views::values) { + for(auto const& rawTO : workspace.rawTOs) { + result.insert(rawTO->id); + } + } + return std::vector(result.begin(), result.end()); +} + void _BrowserWindow::pushTextColor(NetworkResourceTreeTO const& to) { if (to->isLeaf()) { @@ -1441,7 +1473,7 @@ void _BrowserWindow::pushTextColor(NetworkResourceTreeTO const& to) ImGui::PushStyleColor(ImGuiCol_Text, (ImVec4)Const::BrowserVersionOkTextColor); } } else { - ImGui::PushStyleColor(ImGuiCol_Text, (ImVec4)Const::BrowserFolderTextColor); + ImGui::PushStyleColor(ImGuiCol_Text, (ImVec4)Const::BrowserResourceTextColor); } } diff --git a/source/Gui/BrowserWindow.h b/source/Gui/BrowserWindow.h index ecec2c33e..77facd09e 100644 --- a/source/Gui/BrowserWindow.h +++ b/source/Gui/BrowserWindow.h @@ -36,6 +36,7 @@ class _BrowserWindow : public _AlienWindow WorkspaceType getCurrentWorkspaceType() const; BrowserCache& getSimulationCache(); + void registerUploadedSimulation(std::string const& id); private: struct WorkspaceId @@ -106,6 +107,8 @@ class _BrowserWindow : public _AlienWindow bool isOwner(NetworkResourceTreeTO const& treeTO) const; std::string getUserNamesToEmojiType(std::string const& resourceId, int emojiType); + std::vector getAllSimulationIds() const; + void pushTextColor(NetworkResourceTreeTO const& to); void popTextColor(); @@ -117,6 +120,7 @@ class _BrowserWindow : public _AlienWindow std::vector _userTOs; WorkspaceId _currentWorkspace = {NetworkResourceType_Simulation, WorkspaceType_AlienProject}; std::map _workspaces; + std::unordered_set _simIdsFromLastSession; NetworkResourceTreeTO _selectedTreeTO; diff --git a/source/Gui/GenomeEditorWindow.cpp b/source/Gui/GenomeEditorWindow.cpp index 2c89a4464..7e05f256a 100644 --- a/source/Gui/GenomeEditorWindow.cpp +++ b/source/Gui/GenomeEditorWindow.cpp @@ -51,16 +51,16 @@ _GenomeEditorWindow ::_GenomeEditorWindow(EditorModel const& editorModel, Simula if (path.has_parent_path()) { path = path.parent_path(); } - _startingPath = GlobalSettings::getInstance().getStringState("windows.genome editor.starting path", path.string()); - _previewHeight = GlobalSettings::getInstance().getFloatState("windows.genome editor.preview height", scale(PreviewHeight)); + _startingPath = GlobalSettings::getInstance().getString("windows.genome editor.starting path", path.string()); + _previewHeight = GlobalSettings::getInstance().getFloat("windows.genome editor.preview height", scale(PreviewHeight)); _changeColorDialog = std::make_shared<_ChangeColorDialog>([&] { return getCurrentGenome(); }, [&](GenomeDescription const& genome) { setCurrentGenome(genome); }); } _GenomeEditorWindow::~_GenomeEditorWindow() { - GlobalSettings::getInstance().setStringState("windows.genome editor.starting path", _startingPath); - GlobalSettings::getInstance().setFloatState("windows.genome editor.preview height", _previewHeight); + GlobalSettings::getInstance().setString("windows.genome editor.starting path", _startingPath); + GlobalSettings::getInstance().setFloat("windows.genome editor.preview height", _previewHeight); } void _GenomeEditorWindow::registerCyclicReferences(UploadSimulationDialogWeakPtr const& uploadSimulationDialog) diff --git a/source/Gui/GpuSettingsDialog.cpp b/source/Gui/GpuSettingsDialog.cpp index 30fad8852..6d158d770 100644 --- a/source/Gui/GpuSettingsDialog.cpp +++ b/source/Gui/GpuSettingsDialog.cpp @@ -19,8 +19,8 @@ _GpuSettingsDialog::_GpuSettingsDialog(SimulationController const& simController , _simController(simController) { GpuSettings gpuSettings; - gpuSettings.numBlocks = GlobalSettings::getInstance().getIntState("settings.gpu.num blocks", gpuSettings.numBlocks); - gpuSettings.numThreadsPerBlock = GlobalSettings::getInstance().getIntState("settings.gpu.num threads per block", gpuSettings.numThreadsPerBlock); + gpuSettings.numBlocks = GlobalSettings::getInstance().getInt("settings.gpu.num blocks", gpuSettings.numBlocks); + gpuSettings.numThreadsPerBlock = GlobalSettings::getInstance().getInt("settings.gpu.num threads per block", gpuSettings.numThreadsPerBlock); _simController->setGpuSettings_async(gpuSettings); } @@ -28,8 +28,8 @@ _GpuSettingsDialog::_GpuSettingsDialog(SimulationController const& simController _GpuSettingsDialog::~_GpuSettingsDialog() { auto gpuSettings = _simController->getGpuSettings(); - GlobalSettings::getInstance().setIntState("settings.gpu.num blocks", gpuSettings.numBlocks); - GlobalSettings::getInstance().setIntState("settings.gpu.num threads per block", gpuSettings.numThreadsPerBlock); + GlobalSettings::getInstance().setInt("settings.gpu.num blocks", gpuSettings.numBlocks); + GlobalSettings::getInstance().setInt("settings.gpu.num threads per block", gpuSettings.numThreadsPerBlock); } void _GpuSettingsDialog::processIntern() diff --git a/source/Gui/ImageToPatternDialog.cpp b/source/Gui/ImageToPatternDialog.cpp index b3d4d6f15..57a339e1d 100644 --- a/source/Gui/ImageToPatternDialog.cpp +++ b/source/Gui/ImageToPatternDialog.cpp @@ -25,12 +25,12 @@ _ImageToPatternDialog::_ImageToPatternDialog(SimulationController const& simCont if (path.has_parent_path()) { path = path.parent_path(); } - _startingPath = GlobalSettings::getInstance().getStringState("dialogs.open image.starting path", path.string()); + _startingPath = GlobalSettings::getInstance().getString("dialogs.open image.starting path", path.string()); } _ImageToPatternDialog::~_ImageToPatternDialog() { - GlobalSettings::getInstance().setStringState("dialogs.open image.starting path", _startingPath); + GlobalSettings::getInstance().setString("dialogs.open image.starting path", _startingPath); } namespace diff --git a/source/Gui/LogWindow.cpp b/source/Gui/LogWindow.cpp index cef034a53..c26139ebc 100644 --- a/source/Gui/LogWindow.cpp +++ b/source/Gui/LogWindow.cpp @@ -14,12 +14,12 @@ _LogWindow::_LogWindow(GuiLogger const& logger) : _AlienWindow("Log", "windows.log", false) , _logger(logger) { - _verbose = GlobalSettings::getInstance().getBoolState("windows.log.verbose", false); + _verbose = GlobalSettings::getInstance().getBool("windows.log.verbose", false); } _LogWindow::~_LogWindow() { - GlobalSettings::getInstance().setBoolState("windows.log.verbose", _verbose); + GlobalSettings::getInstance().setBool("windows.log.verbose", _verbose); } void _LogWindow::processIntern() diff --git a/source/Gui/LoginDialog.cpp b/source/Gui/LoginDialog.cpp index 49570a71a..3c4a09624 100644 --- a/source/Gui/LoginDialog.cpp +++ b/source/Gui/LoginDialog.cpp @@ -30,12 +30,12 @@ _LoginDialog::_LoginDialog( { auto& settings = GlobalSettings::getInstance(); - _remember = settings.getBoolState("dialogs.login.remember", _remember); - _shareGpuInfo = settings.getBoolState("dialogs.login.share gpu info", _shareGpuInfo); + _remember = settings.getBool("dialogs.login.remember", _remember); + _shareGpuInfo = settings.getBool("dialogs.login.share gpu info", _shareGpuInfo); if (_remember) { - _userName = settings.getStringState("dialogs.login.user name", ""); - _password = settings.getStringState("dialogs.login.password", ""); + _userName = settings.getString("dialogs.login.user name", ""); + _password = settings.getString("dialogs.login.password", ""); if (!_userName.empty()) { LoginErrorCode errorCode; if (!NetworkService::login(errorCode, _userName, _password, getUserInfo())) { @@ -148,11 +148,11 @@ void _LoginDialog::onLogin() void _LoginDialog::saveSettings() { auto& settings = GlobalSettings::getInstance(); - settings.setBoolState("dialogs.login.remember", _remember); - settings.setBoolState("dialogs.login.share gpu info", _shareGpuInfo); + settings.setBool("dialogs.login.remember", _remember); + settings.setBool("dialogs.login.share gpu info", _shareGpuInfo); if (_remember) { - settings.setStringState("dialogs.login.user name", _userName); - settings.setStringState("dialogs.login.password", _password); + settings.setString("dialogs.login.user name", _userName); + settings.setString("dialogs.login.password", _password); } } diff --git a/source/Gui/NewSimulationDialog.cpp b/source/Gui/NewSimulationDialog.cpp index 5e0070afd..659f8eb9b 100644 --- a/source/Gui/NewSimulationDialog.cpp +++ b/source/Gui/NewSimulationDialog.cpp @@ -25,12 +25,12 @@ _NewSimulationDialog::_NewSimulationDialog( , _temporalControlWindow(temporalControlWindow) , _statisticsWindow(statisticsWindow) { - _adoptSimulationParameters = GlobalSettings::getInstance().getBoolState("dialogs.new simulation.adopt simulation parameters", true); + _adoptSimulationParameters = GlobalSettings::getInstance().getBool("dialogs.new simulation.adopt simulation parameters", true); } _NewSimulationDialog::~_NewSimulationDialog() { - GlobalSettings::getInstance().setBoolState("dialogs.new simulation.adopt simulation parameters", _adoptSimulationParameters); + GlobalSettings::getInstance().setBool("dialogs.new simulation.adopt simulation parameters", _adoptSimulationParameters); } void _NewSimulationDialog::processIntern() diff --git a/source/Gui/PatternAnalysisDialog.cpp b/source/Gui/PatternAnalysisDialog.cpp index c18e0a95c..fca9ce145 100644 --- a/source/Gui/PatternAnalysisDialog.cpp +++ b/source/Gui/PatternAnalysisDialog.cpp @@ -22,12 +22,12 @@ _PatternAnalysisDialog::_PatternAnalysisDialog(SimulationController const& simCo if (path.has_parent_path()) { path = path.parent_path(); } - _startingPath = GlobalSettings::getInstance().getStringState("dialogs.pattern analysis.starting path", path.string()); + _startingPath = GlobalSettings::getInstance().getString("dialogs.pattern analysis.starting path", path.string()); } _PatternAnalysisDialog::~_PatternAnalysisDialog() { - GlobalSettings::getInstance().setStringState("dialogs.pattern analysis.starting path", _startingPath); + GlobalSettings::getInstance().setString("dialogs.pattern analysis.starting path", _startingPath); } void _PatternAnalysisDialog::process() diff --git a/source/Gui/PatternEditorWindow.cpp b/source/Gui/PatternEditorWindow.cpp index ff5d3a09d..8c6c8a452 100644 --- a/source/Gui/PatternEditorWindow.cpp +++ b/source/Gui/PatternEditorWindow.cpp @@ -38,12 +38,12 @@ _PatternEditorWindow::_PatternEditorWindow( if (path.has_parent_path()) { path = path.parent_path(); } - _startingPath = GlobalSettings::getInstance().getStringState("editors.pattern editor.starting path", path.string()); + _startingPath = GlobalSettings::getInstance().getString("editors.pattern editor.starting path", path.string()); } _PatternEditorWindow::~_PatternEditorWindow() { - GlobalSettings::getInstance().setStringState("editors.pattern editor.starting path", _startingPath); + GlobalSettings::getInstance().setString("editors.pattern editor.starting path", _startingPath); } void _PatternEditorWindow::processIntern() diff --git a/source/Gui/ShaderWindow.cpp b/source/Gui/ShaderWindow.cpp index 73d05a36c..ebffd3756 100644 --- a/source/Gui/ShaderWindow.cpp +++ b/source/Gui/ShaderWindow.cpp @@ -14,9 +14,9 @@ _ShaderWindow::_ShaderWindow(SimulationView const& simulationView) : _AlienWindow("Shader parameters", "windows.shader", false) , _simulationView(simulationView) { - _brightness = GlobalSettings::getInstance().getFloatState("windows.shader.brightness", _brightness); - _contrast = GlobalSettings::getInstance().getFloatState("windows.shader.contrast", _contrast); - _motionBlur = GlobalSettings::getInstance().getFloatState("windows.shader.motion blur", _motionBlur); + _brightness = GlobalSettings::getInstance().getFloat("windows.shader.brightness", _brightness); + _contrast = GlobalSettings::getInstance().getFloat("windows.shader.contrast", _contrast); + _motionBlur = GlobalSettings::getInstance().getFloat("windows.shader.motion blur", _motionBlur); _simulationView->setBrightness(_brightness); _simulationView->setContrast(_contrast); _simulationView->setMotionBlur(_motionBlur); @@ -24,9 +24,9 @@ _ShaderWindow::_ShaderWindow(SimulationView const& simulationView) _ShaderWindow::~_ShaderWindow() { - GlobalSettings::getInstance().setFloatState("windows.shader.brightness", _brightness); - GlobalSettings::getInstance().setFloatState("windows.shader.contrast", _contrast); - GlobalSettings::getInstance().setFloatState("windows.shader.motion blur", _motionBlur); + GlobalSettings::getInstance().setFloat("windows.shader.brightness", _brightness); + GlobalSettings::getInstance().setFloat("windows.shader.contrast", _contrast); + GlobalSettings::getInstance().setFloat("windows.shader.motion blur", _motionBlur); } void _ShaderWindow::processIntern() diff --git a/source/Gui/SimulationParametersWindow.cpp b/source/Gui/SimulationParametersWindow.cpp index bc845d96b..e2e5ce169 100644 --- a/source/Gui/SimulationParametersWindow.cpp +++ b/source/Gui/SimulationParametersWindow.cpp @@ -65,9 +65,9 @@ _SimulationParametersWindow::_SimulationParametersWindow( if (path.has_parent_path()) { path = path.parent_path(); } - _startingPath = GlobalSettings::getInstance().getStringState("windows.simulation parameters.starting path", path.string()); - _featureListOpen = GlobalSettings::getInstance().getBoolState("windows.simulation parameters.feature list.open", _featureListOpen); - _featureListHeight = GlobalSettings::getInstance().getFloatState("windows.simulation parameters.feature list.height", _featureListHeight); + _startingPath = GlobalSettings::getInstance().getString("windows.simulation parameters.starting path", path.string()); + _featureListOpen = GlobalSettings::getInstance().getBool("windows.simulation parameters.feature list.open", _featureListOpen); + _featureListHeight = GlobalSettings::getInstance().getFloat("windows.simulation parameters.feature list.height", _featureListHeight); for (int i = 0; i < CellFunction_Count; ++i) { _cellFunctionStrings.emplace_back(Const::CellFunctionToStringMap.at(i)); @@ -76,9 +76,9 @@ _SimulationParametersWindow::_SimulationParametersWindow( _SimulationParametersWindow::~_SimulationParametersWindow() { - GlobalSettings::getInstance().setStringState("windows.simulation parameters.starting path", _startingPath); - GlobalSettings::getInstance().setBoolState("windows.simulation parameters.feature list.open", _featureListOpen); - GlobalSettings::getInstance().setFloatState("windows.simulation parameters.feature list.height", _featureListHeight); + GlobalSettings::getInstance().setString("windows.simulation parameters.starting path", _startingPath); + GlobalSettings::getInstance().setBool("windows.simulation parameters.feature list.open", _featureListOpen); + GlobalSettings::getInstance().setFloat("windows.simulation parameters.feature list.height", _featureListHeight); } void _SimulationParametersWindow::processIntern() diff --git a/source/Gui/SimulationView.cpp b/source/Gui/SimulationView.cpp index 2e4bb6e42..3e58c5294 100644 --- a/source/Gui/SimulationView.cpp +++ b/source/Gui/SimulationView.cpp @@ -34,7 +34,7 @@ _SimulationView::_SimulationView( EditorModel const& editorModel) : _editorModel(editorModel) { - _isCellDetailOverlayActive = GlobalSettings::getInstance().getBoolState("settings.simulation view.overlay", _isCellDetailOverlayActive); + _isCellDetailOverlayActive = GlobalSettings::getInstance().getBool("settings.simulation view.overlay", _isCellDetailOverlayActive); _modeWindow = modeWindow; _simController = simController; @@ -97,7 +97,7 @@ _SimulationView::_SimulationView( _SimulationView::~_SimulationView() { - GlobalSettings::getInstance().setBoolState("settings.simulation view.overlay", _isCellDetailOverlayActive); + GlobalSettings::getInstance().setBool("settings.simulation view.overlay", _isCellDetailOverlayActive); } void _SimulationView::resize(IntVector2D const& size) diff --git a/source/Gui/StatisticsWindow.cpp b/source/Gui/StatisticsWindow.cpp index 2032b658b..8a433de31 100644 --- a/source/Gui/StatisticsWindow.cpp +++ b/source/Gui/StatisticsWindow.cpp @@ -36,12 +36,12 @@ _StatisticsWindow::_StatisticsWindow(SimulationController const& simController) if (path.has_parent_path()) { path = path.parent_path(); } - _startingPath = GlobalSettings::getInstance().getStringState("windows.statistics.starting path", path.string()); - _plotHeight = GlobalSettings::getInstance().getFloatState("windows.statistics.plot height", _plotHeight); - _mode = GlobalSettings::getInstance().getIntState("windows.statistics.mode", _mode); - _liveStatistics.history = GlobalSettings::getInstance().getFloatState("windows.statistics.live statistics horizon", _liveStatistics.history); - _plotType = GlobalSettings::getInstance().getIntState("windows.statistics.plot type", _plotType); - auto collapsedPlotIndexJoinedString = GlobalSettings::getInstance().getStringState("windows.statistics.collapsed plot indices", ""); + _startingPath = GlobalSettings::getInstance().getString("windows.statistics.starting path", path.string()); + _plotHeight = GlobalSettings::getInstance().getFloat("windows.statistics.plot height", _plotHeight); + _mode = GlobalSettings::getInstance().getInt("windows.statistics.mode", _mode); + _liveStatistics.history = GlobalSettings::getInstance().getFloat("windows.statistics.live statistics horizon", _liveStatistics.history); + _plotType = GlobalSettings::getInstance().getInt("windows.statistics.plot type", _plotType); + auto collapsedPlotIndexJoinedString = GlobalSettings::getInstance().getString("windows.statistics.collapsed plot indices", ""); if (!collapsedPlotIndexJoinedString.empty()) { std::vector collapsedPlotIndexStrings; @@ -54,17 +54,17 @@ _StatisticsWindow::_StatisticsWindow(SimulationController const& simController) _StatisticsWindow::~_StatisticsWindow() { - GlobalSettings::getInstance().setStringState("windows.statistics.starting path", _startingPath); - GlobalSettings::getInstance().setFloatState("windows.statistics.plot height", _plotHeight); - GlobalSettings::getInstance().setIntState("windows.statistics.mode", _mode); - GlobalSettings::getInstance().setFloatState("windows.statistics.live statistics horizon", _liveStatistics.history); - GlobalSettings::getInstance().setIntState("windows.statistics.plot type", _plotType); + GlobalSettings::getInstance().setString("windows.statistics.starting path", _startingPath); + GlobalSettings::getInstance().setFloat("windows.statistics.plot height", _plotHeight); + GlobalSettings::getInstance().setInt("windows.statistics.mode", _mode); + GlobalSettings::getInstance().setFloat("windows.statistics.live statistics horizon", _liveStatistics.history); + GlobalSettings::getInstance().setInt("windows.statistics.plot type", _plotType); std::vector collapsedPlotIndexStrings; for (auto const& index : _collapsedPlotIndices) { collapsedPlotIndexStrings.emplace_back(std::to_string(index)); } - GlobalSettings::getInstance().setStringState("windows.statistics.collapsed plot indices", boost::join(collapsedPlotIndexStrings, " ")); + GlobalSettings::getInstance().setString("windows.statistics.collapsed plot indices", boost::join(collapsedPlotIndexStrings, " ")); } void _StatisticsWindow::processIntern() diff --git a/source/Gui/StyleRepository.h b/source/Gui/StyleRepository.h index 967b8ab7a..4d5c0b03f 100644 --- a/source/Gui/StyleRepository.h +++ b/source/Gui/StyleRepository.h @@ -91,10 +91,11 @@ namespace Const ImColor const BrowserAddReactionButtonTextColor = ImColor::HSV(0.375f, 0.6f, 0.7f, 1.0f); ImColor const BrowserDownloadButtonTextColor = ImColor::HSV(0.55f, 0.6f, 1.0f, 1.0f); ImColor const BrowserDeleteButtonTextColor = ImColor::HSV(0.0f, 0.6f, 0.8f, 1.0f); - ImColor const BrowserFolderTextColor = ImColor::HSV(0.0f, 0.0f, 1.0f); - ImColor const BrowserFolderLineColor = ImColor::HSV(0.0f, 0.0f, 0.5f); - ImColor const BrowserFolderPropertiesTextColor = ImColor::HSV(0.0f, 0.0f, 0.5f, 1.0f); - ImColor const BrowserFolderSymbolColor = ImColor::HSV(0.0f, 0.0f, 1.0f, 1.0f); + ImColor const BrowserResourceTextColor = ImColor::HSV(0.0f, 0.0f, 1.0f); + ImColor const BrowserResourceLineColor = ImColor::HSV(0.0f, 0.0f, 0.5f); + ImColor const BrowserResourcePropertiesTextColor = ImColor::HSV(0.0f, 0.0f, 0.5f, 1.0f); + ImColor const BrowserResourceNewTextColor = ImColor::HSV(0.0f, 0.0f, 1.0f, 1.0f); + ImColor const BrowserResourceSymbolColor = ImColor::HSV(0.0f, 0.0f, 1.0f, 1.0f); ImColor const BrowserVersionOkTextColor = ImColor::HSV(0.58f, 0.2f, 1.0f); ImColor const BrowserVersionOutdatedTextColor = ImColor::HSV(0.0f, 0.0f, 0.6f); diff --git a/source/Gui/UploadSimulationDialog.cpp b/source/Gui/UploadSimulationDialog.cpp index 61abc26c5..1c5a476dd 100644 --- a/source/Gui/UploadSimulationDialog.cpp +++ b/source/Gui/UploadSimulationDialog.cpp @@ -45,13 +45,13 @@ _UploadSimulationDialog::_UploadSimulationDialog( , _genomeEditorWindow(genomeEditorWindow) { auto& settings = GlobalSettings::getInstance(); - _share = settings.getBoolState("dialogs.upload.share", _share); + _share = settings.getBool("dialogs.upload.share", _share); } _UploadSimulationDialog::~_UploadSimulationDialog() { auto& settings = GlobalSettings::getInstance(); - settings.setBoolState("dialogs.upload.share", _share); + settings.setBool("dialogs.upload.share", _share); } void _UploadSimulationDialog::open(NetworkResourceType resourceType, std::string const& folder) @@ -200,5 +200,6 @@ void _UploadSimulationDialog::onUpload() _browserWindow->getSimulationCache().insert(resourceId, deserializedSim); } _browserWindow->onRefresh(); + _browserWindow->registerUploadedSimulation(resourceId); }); } diff --git a/source/Gui/WindowController.cpp b/source/Gui/WindowController.cpp index de2c79e66..3e616f3e0 100644 --- a/source/Gui/WindowController.cpp +++ b/source/Gui/WindowController.cpp @@ -56,11 +56,11 @@ std::string WindowController::_mode; void WindowController::init() { auto& settings = GlobalSettings::getInstance(); - _mode = settings.getStringState("settings.display.mode", DesktopMode); - _sizeInWindowedMode.x = settings.getIntState("settings.display.window width", _sizeInWindowedMode.x); - _sizeInWindowedMode.y = settings.getIntState("settings.display.window height", _sizeInWindowedMode.y); - _fps = settings.getIntState("settings.display.fps", _fps); - _lastContentScaleFactor = settings.getFloatState("settings.display.content scale factor", _lastContentScaleFactor); + _mode = settings.getString("settings.display.mode", DesktopMode); + _sizeInWindowedMode.x = settings.getInt("settings.display.window width", _sizeInWindowedMode.x); + _sizeInWindowedMode.y = settings.getInt("settings.display.window height", _sizeInWindowedMode.y); + _fps = settings.getInt("settings.display.fps", _fps); + _lastContentScaleFactor = settings.getFloat("settings.display.content scale factor", _lastContentScaleFactor); GLFWmonitor* primaryMonitor = glfwGetPrimaryMonitor(); _windowData.mode = glfwGetVideoMode(primaryMonitor); @@ -102,11 +102,11 @@ void WindowController::shutdown() updateWindowSize(); } auto& settings = GlobalSettings::getInstance(); - settings.setStringState("settings.display.mode", _mode); - settings.setIntState("settings.display.window width", _sizeInWindowedMode.x); - settings.setIntState("settings.display.window height", _sizeInWindowedMode.y); - settings.setIntState("settings.display.fps", _fps); - settings.setFloatState("settings.display.content scale factor", _contentScaleFactor); + settings.setString("settings.display.mode", _mode); + settings.setInt("settings.display.window width", _sizeInWindowedMode.x); + settings.setInt("settings.display.window height", _sizeInWindowedMode.y); + settings.setInt("settings.display.fps", _fps); + settings.setFloat("settings.display.content scale factor", _contentScaleFactor); } diff --git a/source/Network/NetworkService.cpp b/source/Network/NetworkService.cpp index 250194728..6fbfe2567 100644 --- a/source/Network/NetworkService.cpp +++ b/source/Network/NetworkService.cpp @@ -75,12 +75,12 @@ Cache NetworkService::_downloadCa void NetworkService::init() { - _serverAddress = GlobalSettings::getInstance().getStringState("settings.server", "alien-project.org"); + _serverAddress = GlobalSettings::getInstance().getString("settings.server", "alien-project.org"); } void NetworkService::shutdown() { - GlobalSettings::getInstance().setStringState("settings.server", _serverAddress); + GlobalSettings::getInstance().setString("settings.server", _serverAddress); logout(); } From c886302876f9dc200ac012f1fc0bb6d51c2a673b Mon Sep 17 00:00:00 2001 From: Christian Heinemann Date: Thu, 25 Apr 2024 21:31:06 +0200 Subject: [PATCH 10/16] new symbol for indicating new simulations --- source/Gui/AlienImGui.cpp | 10 ++-------- source/Gui/AlienImGui.h | 1 - source/Gui/BrowserWindow.cpp | 11 ++++++++--- source/Gui/StyleRepository.h | 2 +- 4 files changed, 11 insertions(+), 13 deletions(-) diff --git a/source/Gui/AlienImGui.cpp b/source/Gui/AlienImGui.cpp index 506142224..b934496f2 100644 --- a/source/Gui/AlienImGui.cpp +++ b/source/Gui/AlienImGui.cpp @@ -1491,17 +1491,12 @@ void AlienImGui::NeuronSelection( ImGui::EndChild(); } -ImVec4 AlienImGui::GetBlinkingColor() +void AlienImGui::OnlineSymbol() { auto counter = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); counter = (((counter % 2000) + 2000) % 2000); auto color = ImColor::HSV(0.0f, counter < 1000 ? toFloat(counter) / 1000.0f : 2.0f - toFloat(counter) / 1000.0f, 1.0f); - return color.Value; -} - -void AlienImGui::OnlineSymbol() -{ - ImGui::PushStyleColor(ImGuiCol_Text, GetBlinkingColor()); + ImGui::PushStyleColor(ImGuiCol_Text, color.Value); ImGui::Text(ICON_FA_GENDERLESS); ImGui::PopStyleColor(); } @@ -1591,7 +1586,6 @@ bool AlienImGui::BasicSlider(Parameter const& parameters, T* value, bool* enable } //slider - T sliderValue; T minValue = value[0], maxValue = value[0]; int sliderValueColor = 0; diff --git a/source/Gui/AlienImGui.h b/source/Gui/AlienImGui.h index 28082ec53..2b7f48a98 100644 --- a/source/Gui/AlienImGui.h +++ b/source/Gui/AlienImGui.h @@ -314,7 +314,6 @@ class AlienImGui std::vector& biases, std::vector& activationFunctions); - static ImVec4 GetBlinkingColor(); static void OnlineSymbol(); static void LastDayOnlineSymbol(); diff --git a/source/Gui/BrowserWindow.cpp b/source/Gui/BrowserWindow.cpp index 92be17c3a..25cd70d38 100644 --- a/source/Gui/BrowserWindow.cpp +++ b/source/Gui/BrowserWindow.cpp @@ -770,12 +770,17 @@ bool _BrowserWindow::processResourceNameField(NetworkResourceTreeTO const& treeT ImGui::SameLine(); if (!_simIdsFromLastSession.contains(leaf.rawTO->id)) { - ImGui::PushFont(StyleRepository::getInstance().getSmallBoldFont()); - ImGui::PushStyleColor(ImGuiCol_Text, AlienImGui::GetBlinkingColor()); + auto font = StyleRepository::getInstance().getSmallBoldFont(); + auto origSize = font->Scale; + font->Scale *= 0.65f; + ImGui::PushFont(font); + ImGui::PushStyleColor(ImGuiCol_Text, Const::BrowserResourceNewTextColor.Value); AlienImGui::Text("NEW"); ImGui::PopStyleColor(); - ImGui::SameLine(); + font->Scale = origSize; ImGui::PopFont(); + + ImGui::SameLine(); } processShortenedText(leaf.leafName, true); diff --git a/source/Gui/StyleRepository.h b/source/Gui/StyleRepository.h index 4d5c0b03f..831efa7e0 100644 --- a/source/Gui/StyleRepository.h +++ b/source/Gui/StyleRepository.h @@ -94,7 +94,7 @@ namespace Const ImColor const BrowserResourceTextColor = ImColor::HSV(0.0f, 0.0f, 1.0f); ImColor const BrowserResourceLineColor = ImColor::HSV(0.0f, 0.0f, 0.5f); ImColor const BrowserResourcePropertiesTextColor = ImColor::HSV(0.0f, 0.0f, 0.5f, 1.0f); - ImColor const BrowserResourceNewTextColor = ImColor::HSV(0.0f, 0.0f, 1.0f, 1.0f); + ImColor const BrowserResourceNewTextColor = ImColor::HSV(0.15f, 0.8f, 1.0f); ImColor const BrowserResourceSymbolColor = ImColor::HSV(0.0f, 0.0f, 1.0f, 1.0f); ImColor const BrowserVersionOkTextColor = ImColor::HSV(0.58f, 0.2f, 1.0f); From 59d64b4a0135d9e2f044434600630813ba53e8f6 Mon Sep 17 00:00:00 2001 From: Christian Heinemann Date: Thu, 25 Apr 2024 21:38:50 +0200 Subject: [PATCH 11/16] loading and saving folder states refactored --- source/Gui/BrowserWindow.cpp | 4 ++-- source/Network/NetworkResourceService.cpp | 15 ++++++--------- source/Network/NetworkResourceService.h | 4 ++-- 3 files changed, 10 insertions(+), 13 deletions(-) diff --git a/source/Gui/BrowserWindow.cpp b/source/Gui/BrowserWindow.cpp index 25cd70d38..7b0b952d6 100644 --- a/source/Gui/BrowserWindow.cpp +++ b/source/Gui/BrowserWindow.cpp @@ -105,7 +105,7 @@ _BrowserWindow::~_BrowserWindow() settings.setBool("windows.browser.first start", false); settings.setFloat("windows.browser.user table width", _userTableWidth); for (auto const& [workspaceId, workspace] : _workspaces) { - settings.setString( + settings.setStringVector( "windows.browser.collapsed folders." + networkResourceTypeToString.at(workspaceId.resourceType) + "." + workspaceTypeToString.at(workspaceId.workspaceType), NetworkResourceService::convertFolderNamesToSettings(workspace.collapsedFolderNames)); @@ -128,7 +128,7 @@ void _BrowserWindow::registerCyclicReferences( for (auto& [workspaceId, workspace] : _workspaces) { auto initialCollapsedSimulationFolders = NetworkResourceService::convertFolderNamesToSettings(NetworkResourceService::getFolderNames(workspace.rawTOs)); - auto collapsedSimulationFolders = GlobalSettings::getInstance().getString( + auto collapsedSimulationFolders = GlobalSettings::getInstance().getStringVector( "windows.browser.collapsed folders." + networkResourceTypeToString.at(workspaceId.resourceType) + "." + workspaceTypeToString.at(workspaceId.workspaceType), initialCollapsedSimulationFolders); diff --git a/source/Network/NetworkResourceService.cpp b/source/Network/NetworkResourceService.cpp index f6a7d9764..9431f3a82 100644 --- a/source/Network/NetworkResourceService.cpp +++ b/source/Network/NetworkResourceService.cpp @@ -319,22 +319,19 @@ std::string NetworkResourceService::concatenateFolderName(std::vector> const& data) +std::vector NetworkResourceService::convertFolderNamesToSettings(std::set> const& folderNames) { std::vector parts; - for (auto const& folderNames : data) { - parts.emplace_back(concatenateFolderName(folderNames, false)); + for (auto const& folderName : folderNames) { + parts.emplace_back(concatenateFolderName(folderName, false)); } - return boost::join(parts, "\\"); + return parts; } -std::set> NetworkResourceService::convertSettingsToFolderNames(std::string const& data) +std::set> NetworkResourceService::convertSettingsToFolderNames(std::vector const& settings) { - std::vector parts; - boost::split(parts, data, boost::is_any_of("\\")); - std::set> result; - for (auto const& part : parts) { + for (auto const& part : settings) { std::vector splittedParts = getNameParts(part); result.insert(splittedParts); } diff --git a/source/Network/NetworkResourceService.h b/source/Network/NetworkResourceService.h index 4877509da..edc684a48 100644 --- a/source/Network/NetworkResourceService.h +++ b/source/Network/NetworkResourceService.h @@ -19,8 +19,8 @@ class NetworkResourceService static std::string removeFoldersFromName(std::string const& resourceName); static std::set> getFolderNames(std::vector const& browserData, int minNesting = 2); static std::string concatenateFolderName(std::vector const& folderNames, bool withSlashAtTheEnd); - static std::string convertFolderNamesToSettings(std::set> const& data); - static std::set> convertSettingsToFolderNames(std::string const& data); + static std::vector convertFolderNamesToSettings(std::set> const& folderNames); + static std::set> convertSettingsToFolderNames(std::vector const& settings); private: static std::unordered_map> _treeTOtoRawTOcache; From 01bf355f30aa8cc519c5e16bff5eb83623f44a03 Mon Sep 17 00:00:00 2001 From: Christian Heinemann Date: Fri, 26 Apr 2024 16:08:48 +0200 Subject: [PATCH 12/16] + allow replacing simulations and genomes + new labels also show up for replaced items --- scripts/Server/replacesimulation.php | 68 +++++++++++++++++ source/Base/Cache.h | 4 +- source/Gui/BrowserWindow.cpp | 93 ++++++++++++++++++----- source/Gui/BrowserWindow.h | 11 ++- source/Gui/CMakeLists.txt | 4 + source/Gui/Definitions.h | 1 + source/Gui/LastSessionBrowserData.cpp | 38 +++++++++ source/Gui/LastSessionBrowserData.h | 20 +++++ source/Gui/MainWindow.cpp | 2 +- source/Gui/SerializationHelperService.cpp | 19 +++++ source/Gui/SerializationHelperService.h | 11 +++ source/Gui/UploadSimulationDialog.cpp | 13 +--- source/Network/NetworkService.cpp | 72 ++++++++++++++++-- source/Network/NetworkService.h | 15 +++- 14 files changed, 325 insertions(+), 46 deletions(-) create mode 100644 scripts/Server/replacesimulation.php create mode 100644 source/Gui/LastSessionBrowserData.cpp create mode 100644 source/Gui/LastSessionBrowserData.h create mode 100644 source/Gui/SerializationHelperService.cpp create mode 100644 source/Gui/SerializationHelperService.h diff --git a/scripts/Server/replacesimulation.php b/scripts/Server/replacesimulation.php new file mode 100644 index 000000000..e9b76486a --- /dev/null +++ b/scripts/Server/replacesimulation.php @@ -0,0 +1,68 @@ +false]); + $db->close(); + exit; + } + + + $db = connectToDB(); + $db->begin_transaction(); + + $userName = $_POST["userName"]; + $pw = $_POST["password"]; + + if (!checkPw($db, $userName, $pw)) { + echo json_encode(["result"=>false]); + $db->close(); + exit; + } + + $obj = $db->query("SELECT u.ID as id FROM user u WHERE u.NAME='".addslashes($userName)."'")->fetch_object(); + if (!$obj) { + echo json_encode(["result"=>false]); + $db->close(); + exit; + } + + $success = false; + $particles = (int)$_POST['particles']; + $version = $_POST['version']; + $content = $_POST['content']; + $settings = $_POST['settings']; + $simId = $_POST['simId']; + $size = strlen($content); + $type = array_key_exists('type', $_POST) ? $_POST['type'] : 0; + $workspace = array_key_exists('workspace', $_POST) ? $_POST['workspace'] : 0; + $statistics = array_key_exists('statistics', $_POST) ? $_POST['statistics'] : ""; + + if ($userName != 'alien-project' && $workspace == 1) { + closeAndExit($db); + } + + $stmt = $db->prepare("UPDATE simulation SET PARTICLES=?, VERSION=?, CONTENT=?, WIDTH=?, HEIGHT=?, SETTINGS=?, SIZE=?, STATISTICS=?, CONTENT2=?, CONTENT3=?, CONTENT4=?, CONTENT5=?, CONTENT6=? WHERE ID=?"); + if (!$stmt) { + closeAndExit($db); + } + + $emptyString = ''; + $stmt->bind_param("issiisissssssi", $particles, $version, $content, $width, $height, $settings, $size, $statistics, $emptyString, $emptyString, $emptyString, $emptyString, $emptyString, $simId); + + if (!$stmt->execute()) { + closeAndExit($db); + } + + // create Discord message + //if ($workspace != PRIVATE_WORKSPACE_TYPE) { + // $discordPayload = createAddResourceMessage($type, $simName, $userName, $simDesc, $width, $height, $particles); + // sendDiscordMessage($discordPayload); + //} + + echo json_encode(["result"=>true]); + + $db->commit(); + $db->close(); +?> \ No newline at end of file diff --git a/source/Base/Cache.h b/source/Base/Cache.h index db75d0bc6..d3797474b 100644 --- a/source/Base/Cache.h +++ b/source/Base/Cache.h @@ -8,7 +8,7 @@ template class Cache { public: - void insert(Key const& key, Value const& value); + void insertOrAssign(Key const& key, Value const& value); std::optional find(Key const& key); @@ -21,7 +21,7 @@ class Cache /* Implementation */ /************************************************************************/ template -void Cache::insert(Key const& key, Value const& value) +void Cache::insertOrAssign(Key const& key, Value const& value) { if (_cacheMap.size() >= MaxEntries) { _cacheMap.erase(_usedKeys.front()); diff --git a/source/Gui/BrowserWindow.cpp b/source/Gui/BrowserWindow.cpp index 7b0b952d6..060248ac3 100644 --- a/source/Gui/BrowserWindow.cpp +++ b/source/Gui/BrowserWindow.cpp @@ -41,6 +41,7 @@ #include "OverlayMessageController.h" #include "GenomeEditorWindow.h" #include "HelpStrings.h" +#include "SerializationHelperService.h" namespace { @@ -110,17 +111,19 @@ _BrowserWindow::~_BrowserWindow() + workspaceTypeToString.at(workspaceId.workspaceType), NetworkResourceService::convertFolderNamesToSettings(workspace.collapsedFolderNames)); } - settings.setStringVector("windows.browser.simulation ids", getAllSimulationIds()); + _lastSessionData.save(getAllRawTOs()); } void _BrowserWindow::registerCyclicReferences( LoginDialogWeakPtr const& loginDialog, UploadSimulationDialogWeakPtr const& uploadSimulationDialog, - EditSimulationDialogWeakPtr const& editSimulationDialog) + EditSimulationDialogWeakPtr const& editSimulationDialog, + GenomeEditorWindowWeakPtr const& genomeEditorWindow) { _loginDialog = loginDialog; _uploadSimulationDialog = uploadSimulationDialog; _editSimulationDialog = editSimulationDialog; + _genomeEditorWindow = genomeEditorWindow; auto firstStart = GlobalSettings::getInstance().getBool("windows.browser.first start", true); refreshIntern(firstStart); @@ -136,8 +139,7 @@ void _BrowserWindow::registerCyclicReferences( createTreeTOs(workspace); } - auto simIds = GlobalSettings::getInstance().getStringVector("windows.browser.simulation ids", getAllSimulationIds()); - _simIdsFromLastSession = std::unordered_set(simIds.begin(), simIds.end()); + _lastSessionData.load(getAllRawTOs()); } void _BrowserWindow::onRefresh() @@ -155,11 +157,6 @@ BrowserCache& _BrowserWindow::getSimulationCache() return _simulationCache; } -void _BrowserWindow::registerUploadedSimulation(std::string const& id) -{ - _simIdsFromLastSession.insert(id); -} - void _BrowserWindow::refreshIntern(bool withRetry) { try { @@ -291,6 +288,14 @@ void _BrowserWindow::processToolbar() + " to the server and made visible in the browser. You can choose whether you want to share it with other users or whether it should only be visible " "in your private workspace.\nIf you have already selected a folder, your " + resourceTypeString + " will be uploaded there."); + //replace button + ImGui::SameLine(); + ImGui::BeginDisabled(!isOwnerForSelectedItem || !_selectedTreeTO->isLeaf()); + if (AlienImGui::ToolbarButton(ICON_FA_EXCHANGE_ALT)) { + onReplaceResource(_selectedTreeTO->getLeaf()); + } + ImGui::EndDisabled(); + //edit button ImGui::SameLine(); ImGui::BeginDisabled(!isOwnerForSelectedItem); @@ -769,7 +774,7 @@ bool _BrowserWindow::processResourceNameField(NetworkResourceTreeTO const& treeT } ImGui::SameLine(); - if (!_simIdsFromLastSession.contains(leaf.rawTO->id)) { + if (!isOwner(treeTO) && _lastSessionData.isNew(leaf.rawTO)) { auto font = StyleRepository::getInstance().getSmallBoldFont(); auto origSize = font->Scale; font->Scale *= 0.65f; @@ -1234,7 +1239,7 @@ void _BrowserWindow::onDownloadResource(BrowserLeaf const& leaf) MessageDialog::getInstance().information("Error", "Failed to load simulation. Your program version may not match."); return; } - _simulationCache.insert(leaf.rawTO->id, deserializedSim); + _simulationCache.insertOrAssign(leaf.rawTO->id, deserializedSim); } else { log(Priority::Important, "browser: get resource with id=" + leaf.rawTO->id + " from simulation cache"); std::swap(deserializedSim, *cachedSimulation); @@ -1286,6 +1291,62 @@ void _BrowserWindow::onDownloadResource(BrowserLeaf const& leaf) }); } +void _BrowserWindow::onReplaceResource(BrowserLeaf const& leaf) +{ + printOverlayMessage("Replacing ..."); + + delayedExecution([=, this] { + std::string mainData; + std::string settings; + std::string statistics; + IntVector2D worldSize; + int numObjects = 0; + + DeserializedSimulation deserializedSim; + if (leaf.rawTO->resourceType == NetworkResourceType_Simulation) { + deserializedSim = SerializationHelperService::getDeserializedSerialization(_simController); + + SerializedSimulation serializedSim; + if (!SerializerService::serializeSimulationToStrings(serializedSim, deserializedSim)) { + MessageDialog::getInstance().information("Replace simulation", "The simulation could not be serialized for replacing."); + return; + } + mainData = serializedSim.mainData; + settings = serializedSim.auxiliaryData; + statistics = serializedSim.statistics; + worldSize = {deserializedSim.auxiliaryData.generalSettings.worldSizeX, deserializedSim.auxiliaryData.generalSettings.worldSizeY}; + numObjects = deserializedSim.mainData.getNumberOfCellAndParticles(); + } else { + auto genome = _genomeEditorWindow.lock()->getCurrentGenome(); + if (genome.cells.empty()) { + showMessage("Replace genome", "The is no valid genome in the genome editor selected."); + return; + } + auto genomeData = GenomeDescriptionService::convertDescriptionToBytes(genome); + numObjects = GenomeDescriptionService::getNumNodesRecursively(genomeData, true); + + if (!SerializerService::serializeGenomeToString(mainData, genomeData)) { + showMessage("Replace genome", "The genome could not be serialized for replacing."); + return; + } + } + + if (!NetworkService::replaceResource(leaf.rawTO->id, worldSize, numObjects, mainData, settings, statistics)) { + std::string type = leaf.rawTO->resourceType == NetworkResourceType_Simulation ? "simulation" : "genome"; + showMessage( + "Error", + "Failed to replace " + type + ".\n\n" + "Possible reasons:\n\n" ICON_FA_CHEVRON_RIGHT " The server is not reachable.\n\n" ICON_FA_CHEVRON_RIGHT + " The total size of your uploads exceeds the allowed storage limit."); + return; + } + if (leaf.rawTO->resourceType == NetworkResourceType_Simulation) { + getSimulationCache().insertOrAssign(leaf.rawTO->id, deserializedSim); + } + onRefresh(); + }); +} + void _BrowserWindow::onEditResource(NetworkResourceTreeTO const& treeTO) { if (treeTO->isLeaf()) { @@ -1455,15 +1516,13 @@ std::string _BrowserWindow::getUserNamesToEmojiType(std::string const& resourceI return boost::algorithm::join(userNames, ", "); } -std::vector _BrowserWindow::getAllSimulationIds() const +std::unordered_set _BrowserWindow::getAllRawTOs() const { - std::unordered_set result; + std::unordered_set result; for (auto const& workspace : _workspaces | std::views::values) { - for(auto const& rawTO : workspace.rawTOs) { - result.insert(rawTO->id); - } + result.insert(workspace.rawTOs.begin(), workspace.rawTOs.end()); } - return std::vector(result.begin(), result.end()); + return result; } void _BrowserWindow::pushTextColor(NetworkResourceTreeTO const& to) diff --git a/source/Gui/BrowserWindow.h b/source/Gui/BrowserWindow.h index 77facd09e..074d0394d 100644 --- a/source/Gui/BrowserWindow.h +++ b/source/Gui/BrowserWindow.h @@ -12,6 +12,7 @@ #include "AlienWindow.h" #include "Definitions.h" +#include "LastSessionBrowserData.h" struct ImGuiTableColumnSortSpecs; @@ -30,13 +31,13 @@ class _BrowserWindow : public _AlienWindow void registerCyclicReferences( LoginDialogWeakPtr const& loginDialog, UploadSimulationDialogWeakPtr const& uploadSimulationDialog, - EditSimulationDialogWeakPtr const& editSimulationDialog); + EditSimulationDialogWeakPtr const& editSimulationDialog, + GenomeEditorWindowWeakPtr const& genomeEditorWindow); void onRefresh(); WorkspaceType getCurrentWorkspaceType() const; BrowserCache& getSimulationCache(); - void registerUploadedSimulation(std::string const& id); private: struct WorkspaceId @@ -96,6 +97,7 @@ class _BrowserWindow : public _AlienWindow void sortUserList(); void onDownloadResource(BrowserLeaf const& leaf); + void onReplaceResource(BrowserLeaf const& leaf); void onEditResource(NetworkResourceTreeTO const& treeTO); void onMoveResource(NetworkResourceTreeTO const& treeTO); void onDeleteResource(NetworkResourceTreeTO const& treeTO); @@ -107,7 +109,7 @@ class _BrowserWindow : public _AlienWindow bool isOwner(NetworkResourceTreeTO const& treeTO) const; std::string getUserNamesToEmojiType(std::string const& resourceId, int emojiType); - std::vector getAllSimulationIds() const; + std::unordered_set getAllRawTOs() const; void pushTextColor(NetworkResourceTreeTO const& to); void popTextColor(); @@ -120,7 +122,7 @@ class _BrowserWindow : public _AlienWindow std::vector _userTOs; WorkspaceId _currentWorkspace = {NetworkResourceType_Simulation, WorkspaceType_AlienProject}; std::map _workspaces; - std::unordered_set _simIdsFromLastSession; + LastSessionBrowserData _lastSessionData; NetworkResourceTreeTO _selectedTreeTO; @@ -140,4 +142,5 @@ class _BrowserWindow : public _AlienWindow EditorController _editorController; UploadSimulationDialogWeakPtr _uploadSimulationDialog; EditSimulationDialogWeakPtr _editSimulationDialog; + GenomeEditorWindowWeakPtr _genomeEditorWindow; }; diff --git a/source/Gui/CMakeLists.txt b/source/Gui/CMakeLists.txt index 840c07f59..1aa6ec8ec 100644 --- a/source/Gui/CMakeLists.txt +++ b/source/Gui/CMakeLists.txt @@ -54,6 +54,8 @@ PUBLIC ImageToPatternDialog.h InspectorWindow.cpp InspectorWindow.h + LastSessionBrowserData.cpp + LastSessionBrowserData.h LoginDialog.cpp LoginDialog.h LogWindow.cpp @@ -91,6 +93,8 @@ PUBLIC ResizeWorldDialog.h SelectionWindow.cpp SelectionWindow.h + SerializationHelperService.cpp + SerializationHelperService.h Shader.cpp Shader.h ShaderWindow.cpp diff --git a/source/Gui/Definitions.h b/source/Gui/Definitions.h index ac0600d4c..b8b4cdda2 100644 --- a/source/Gui/Definitions.h +++ b/source/Gui/Definitions.h @@ -150,6 +150,7 @@ using ImageToPatternDialog = std::shared_ptr<_ImageToPatternDialog>; class _GenomeEditorWindow; using GenomeEditorWindow = std::shared_ptr<_GenomeEditorWindow>; +using GenomeEditorWindowWeakPtr = std::weak_ptr<_GenomeEditorWindow>; class _RadiationSourcesWindow; using RadiationSourcesWindow = std::shared_ptr<_RadiationSourcesWindow>; diff --git a/source/Gui/LastSessionBrowserData.cpp b/source/Gui/LastSessionBrowserData.cpp new file mode 100644 index 000000000..7a0a6a8ae --- /dev/null +++ b/source/Gui/LastSessionBrowserData.cpp @@ -0,0 +1,38 @@ +#include "LastSessionBrowserData.h" + +#include "Base/GlobalSettings.h" +#include "Network/NetworkResourceRawTO.h" + +void LastSessionBrowserData::load(std::unordered_set const& rawTOs) +{ + auto currentIdentifiers = convertToIdentifiers(rawTOs); + auto lastIdentifiers = GlobalSettings::getInstance().getStringVector( + "windows.browser.last session.simulation ids", std::vector(currentIdentifiers.begin(), currentIdentifiers.end())); + _identifiers = std::unordered_set(lastIdentifiers.begin(), lastIdentifiers.end()); +} + +void LastSessionBrowserData::save(std::unordered_set const& rawTOs) +{ + auto currentIdentifiers = convertToIdentifiers(rawTOs); + GlobalSettings::getInstance().setStringVector( + "windows.browser.last session.simulation ids", std::vector(currentIdentifiers.begin(), currentIdentifiers.end())); +} + +bool LastSessionBrowserData::isNew(NetworkResourceRawTO const& rawTO) const +{ + return !_identifiers.count(convertToIdentifier(rawTO)); +} + +std::unordered_set LastSessionBrowserData::convertToIdentifiers(std::unordered_set const& rawTOs) const +{ + std::unordered_set result; + for (auto const& rawTO : rawTOs) { + result.insert(convertToIdentifier(rawTO)); + } + return result; +} + +std::string LastSessionBrowserData::convertToIdentifier(NetworkResourceRawTO const& rawTO) const +{ + return rawTO->id + "/" + rawTO->timestamp; +} diff --git a/source/Gui/LastSessionBrowserData.h b/source/Gui/LastSessionBrowserData.h new file mode 100644 index 000000000..daca23171 --- /dev/null +++ b/source/Gui/LastSessionBrowserData.h @@ -0,0 +1,20 @@ +#pragma once + +#include +#include + +#include "Network/Definitions.h" + +class LastSessionBrowserData +{ +public: + void load(std::unordered_set const& rawTOs); + void save(std::unordered_set const& rawTOs); + bool isNew(NetworkResourceRawTO const& rawTO) const; + +private: + std::unordered_set convertToIdentifiers(std::unordered_set const& rawTOs) const; + std::string convertToIdentifier(NetworkResourceRawTO const& rawTO) const; + + std::unordered_set _identifiers; +}; diff --git a/source/Gui/MainWindow.cpp b/source/Gui/MainWindow.cpp index 6ee9e35db..931762ce1 100644 --- a/source/Gui/MainWindow.cpp +++ b/source/Gui/MainWindow.cpp @@ -158,7 +158,7 @@ _MainWindow::_MainWindow(SimulationController const& simController, GuiLogger co _shaderWindow = std::make_shared<_ShaderWindow>(_simulationView); //cyclic references - _browserWindow->registerCyclicReferences(_loginDialog, _uploadSimulationDialog, _editSimulationDialog); + _browserWindow->registerCyclicReferences(_loginDialog, _uploadSimulationDialog, _editSimulationDialog, _editorController->getGenomeEditorWindow()); _activateUserDialog->registerCyclicReferences(_createUserDialog); _editorController->registerCyclicReferences(_uploadSimulationDialog); diff --git a/source/Gui/SerializationHelperService.cpp b/source/Gui/SerializationHelperService.cpp new file mode 100644 index 000000000..56dc4f79c --- /dev/null +++ b/source/Gui/SerializationHelperService.cpp @@ -0,0 +1,19 @@ +#include "SerializationHelperService.h" +#include "EngineInterface/SimulationController.h" + +#include "Viewport.h" + + +DeserializedSimulation SerializationHelperService::getDeserializedSerialization(SimulationController const& simController) +{ + DeserializedSimulation result; + result.auxiliaryData.timestep = static_cast(simController->getCurrentTimestep()); + result.auxiliaryData.realTime = simController->getRealTime(); + result.auxiliaryData.zoom = Viewport::getZoomFactor(); + result.auxiliaryData.center = Viewport::getCenterInWorldPos(); + result.auxiliaryData.generalSettings = simController->getGeneralSettings(); + result.auxiliaryData.simulationParameters = simController->getSimulationParameters(); + result.statistics = simController->getStatisticsHistory().getCopiedData(); + result.mainData = simController->getClusteredSimulationData(); + return result; +} diff --git a/source/Gui/SerializationHelperService.h b/source/Gui/SerializationHelperService.h new file mode 100644 index 000000000..432ee6a3c --- /dev/null +++ b/source/Gui/SerializationHelperService.h @@ -0,0 +1,11 @@ +#pragma once + +#include + +#include "EngineInterface/SerializerService.h" + +class SerializationHelperService +{ +public: + static DeserializedSimulation getDeserializedSerialization(SimulationController const& simController); +}; diff --git a/source/Gui/UploadSimulationDialog.cpp b/source/Gui/UploadSimulationDialog.cpp index 1c5a476dd..dc43cc179 100644 --- a/source/Gui/UploadSimulationDialog.cpp +++ b/source/Gui/UploadSimulationDialog.cpp @@ -20,6 +20,7 @@ #include "GenomeEditorWindow.h" #include "HelpStrings.h" #include "LoginDialog.h" +#include "SerializationHelperService.h" namespace { @@ -151,14 +152,7 @@ void _UploadSimulationDialog::onUpload() DeserializedSimulation deserializedSim; if (_resourceType == NetworkResourceType_Simulation) { - deserializedSim.auxiliaryData.timestep = static_cast(_simController->getCurrentTimestep()); - deserializedSim.auxiliaryData.realTime = _simController->getRealTime(); - deserializedSim.auxiliaryData.zoom = Viewport::getZoomFactor(); - deserializedSim.auxiliaryData.center = Viewport::getCenterInWorldPos(); - deserializedSim.auxiliaryData.generalSettings = _simController->getGeneralSettings(); - deserializedSim.auxiliaryData.simulationParameters = _simController->getSimulationParameters(); - deserializedSim.statistics = _simController->getStatisticsHistory().getCopiedData(); - deserializedSim.mainData = _simController->getClusteredSimulationData(); + deserializedSim = SerializationHelperService::getDeserializedSerialization(_simController); SerializedSimulation serializedSim; if (!SerializerService::serializeSimulationToStrings(serializedSim, deserializedSim)) { @@ -197,9 +191,8 @@ void _UploadSimulationDialog::onUpload() return; } if (_resourceType == NetworkResourceType_Simulation) { - _browserWindow->getSimulationCache().insert(resourceId, deserializedSim); + _browserWindow->getSimulationCache().insertOrAssign(resourceId, deserializedSim); } _browserWindow->onRefresh(); - _browserWindow->registerUploadedSimulation(resourceId); }); } diff --git a/source/Network/NetworkService.cpp b/source/Network/NetworkService.cpp index 6fbfe2567..e5d11b5d9 100644 --- a/source/Network/NetworkService.cpp +++ b/source/Network/NetworkService.cpp @@ -436,8 +436,8 @@ bool NetworkService::uploadResource( std::string& resourceId, std::string const& resourceName, std::string const& description, - IntVector2D const& size, - int particles, + IntVector2D const& worldSize, + int numParticles, std::string const& mainData, std::string const& settings, std::string const& statistics, @@ -461,9 +461,9 @@ bool NetworkService::uploadResource( {"password", *_password, "", ""}, {"simName", resourceName, "", ""}, {"simDesc", description, "", ""}, - {"width", std::to_string(size.x), "", ""}, - {"height", std::to_string(size.y), "", ""}, - {"particles", std::to_string(particles), "", ""}, + {"width", std::to_string(worldSize.x), "", ""}, + {"height", std::to_string(worldSize.y), "", ""}, + {"particles", std::to_string(numParticles), "", ""}, {"version", Const::ProgramVersion, "", ""}, {"content", chunks.front(), "", "application/octet-stream"}, {"settings", settings, "", ""}, @@ -493,7 +493,63 @@ bool NetworkService::uploadResource( } ++index; } - _downloadCache.insert(resourceId, ResourceData{mainData, settings, statistics}); + _downloadCache.insertOrAssign(resourceId, ResourceData{mainData, settings, statistics}); + + return true; +} + +bool NetworkService::replaceResource( + std::string const& resourceId, + IntVector2D const& worldSize, + int numParticles, + std::string const& mainData, + std::string const& settings, + std::string const& statistics) +{ + log(Priority::Important, "network: replace resource with id='" + resourceId + "'"); + + std::vector chunks; + for (size_t i = 0; i < mainData.length(); i += MaxChunkSize) { + std::string chunk = mainData.substr(i, MaxChunkSize); + chunks.emplace_back(chunk); + } + + httplib::SSLClient client(_serverAddress); + configureClient(client); + + httplib::MultipartFormDataItems items = { + {"userName", *_loggedInUserName, "", ""}, + {"password", *_password, "", ""}, + {"simId", resourceId, "", ""}, + {"width", std::to_string(worldSize.x), "", ""}, + {"height", std::to_string(worldSize.y), "", ""}, + {"particles", std::to_string(numParticles), "", ""}, + {"version", Const::ProgramVersion, "", ""}, + {"content", chunks.front(), "", "application/octet-stream"}, + {"settings", settings, "", ""}, + {"symbolMap", "", "", ""}, + {"statistics", statistics, "", ""}, + }; + + try { + auto result = executeRequest([&] { return client.Post("/alien-server/replacesimulation.php", items); }); + if (!parseBoolResult(result->body)) { + return false; + } + } catch (...) { + logNetworkError(); + return false; + } + + int index = 1; + for (auto const& chunk : chunks | std::views::drop(1)) { + if (!appendResourceData(resourceId, chunk, toInt(index))) { + deleteResource(resourceId); + return false; + } + ++index; + } + _downloadCache.insertOrAssign(resourceId, ResourceData{mainData, settings, statistics}); return true; } @@ -536,7 +592,7 @@ bool NetworkService::downloadResource(std::string& mainData, std::string& auxili auto result = executeRequest([&] { return client.Get("/alien-server/downloadstatistics.php", params, {}); }); statistics = result->body; } - _downloadCache.insert(simId, ResourceData{mainData, auxiliaryData, statistics}); + _downloadCache.insertOrAssign(simId, ResourceData{mainData, auxiliaryData, statistics}); return true; } } catch (...) { @@ -628,7 +684,7 @@ bool NetworkService::deleteResource(std::string const& simId) } } -bool NetworkService::appendResourceData(std::string& resourceId, std::string const& data, int chunkIndex) +bool NetworkService::appendResourceData(std::string const& resourceId, std::string const& data, int chunkIndex) { httplib::SSLClient client(_serverAddress); configureClient(client); diff --git a/source/Network/NetworkService.h b/source/Network/NetworkService.h index 08b51de86..6600573ea 100644 --- a/source/Network/NetworkService.h +++ b/source/Network/NetworkService.h @@ -52,21 +52,28 @@ class NetworkService std::string& resourceId, std::string const& resourceName, std::string const& description, - IntVector2D const& size, - int particles, + IntVector2D const& worldSize, + int numParticles, std::string const& data, std::string const& settings, std::string const& statistics, NetworkResourceType resourceType, WorkspaceType workspaceType); + static bool replaceResource( + std::string const& resourceId, + IntVector2D const& worldSize, + int numParticles, + std::string const& data, + std::string const& settings, + std::string const& statistics); static bool downloadResource(std::string& mainData, std::string& auxiliaryData, std::string& statistics, std::string const& simId); - static void incDownloadCounter(std::string const& simId); + static void incDownloadCounter(std::string const& simId); static bool editResource(std::string const& simId, std::string const& newName, std::string const& newDescription); static bool moveResource(std::string const& simId, WorkspaceType targetWorkspace); static bool deleteResource(std::string const& simId); private: - static bool appendResourceData(std::string& resourceId, std::string const& data, int chunkIndex); + static bool appendResourceData(std::string const& resourceId, std::string const& data, int chunkIndex); static std::string _serverAddress; static std::optional _loggedInUserName; From ecbb085fb2c154e2fc775ed81c8bdd920fc7925c Mon Sep 17 00:00:00 2001 From: Christian Heinemann Date: Fri, 26 Apr 2024 16:41:23 +0200 Subject: [PATCH 13/16] activate Discord message hook for replacing simulations --- scripts/Server/helpers.php | 2 ++ scripts/Server/hooks.php | 21 +++++++++++++++------ scripts/Server/replacesimulation.php | 25 ++++++++++++------------- 3 files changed, 29 insertions(+), 19 deletions(-) diff --git a/scripts/Server/helpers.php b/scripts/Server/helpers.php index 3054685e5..c6d4a63fb 100644 --- a/scripts/Server/helpers.php +++ b/scripts/Server/helpers.php @@ -1,5 +1,7 @@ "alien-project", @@ -33,7 +42,7 @@ function createAddSimulationMessage($simName, $userName, $simDesc, $width, $heig "embeds" => [ [ "author" => [ - "name" => "New simulation added to the database", + "name" => $message, "icon_url" => "https://alien-project.org/alien-server/galaxy.png" ], "title" => $simName, @@ -60,7 +69,7 @@ function createAddSimulationMessage($simName, $userName, $simDesc, $width, $heig ], JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE); } - function createAddGenomeMessage($simName, $userName, $simDesc, $width, $height, $particles) { + function createMessageForGenome($message, $simName, $userName, $simDesc, $width, $height, $particles) { return json_encode([ "username" => "alien-project", "avatar_url" => "https://alien-project.org/alien-server/logo.png", @@ -68,7 +77,7 @@ function createAddGenomeMessage($simName, $userName, $simDesc, $width, $height, "embeds" => [ [ "author" => [ - "name" => "New genome added to the database", + "name" => $message, "icon_url" => "https://alien-project.org/alien-server/genome.png" ], "title" => $simName, diff --git a/scripts/Server/replacesimulation.php b/scripts/Server/replacesimulation.php index e9b76486a..423281e3c 100644 --- a/scripts/Server/replacesimulation.php +++ b/scripts/Server/replacesimulation.php @@ -16,16 +16,12 @@ function closeAndExit($db) { $pw = $_POST["password"]; if (!checkPw($db, $userName, $pw)) { - echo json_encode(["result"=>false]); - $db->close(); - exit; + closeAndExit($db); } $obj = $db->query("SELECT u.ID as id FROM user u WHERE u.NAME='".addslashes($userName)."'")->fetch_object(); if (!$obj) { - echo json_encode(["result"=>false]); - $db->close(); - exit; + closeAndExit($db); } $success = false; @@ -35,11 +31,14 @@ function closeAndExit($db) { $settings = $_POST['settings']; $simId = $_POST['simId']; $size = strlen($content); - $type = array_key_exists('type', $_POST) ? $_POST['type'] : 0; - $workspace = array_key_exists('workspace', $_POST) ? $_POST['workspace'] : 0; $statistics = array_key_exists('statistics', $_POST) ? $_POST['statistics'] : ""; - if ($userName != 'alien-project' && $workspace == 1) { + $obj = $db->query("SELECT sim.NAME as name, sim.TYPE as type, sim.FROM_RELEASE as workspace FROM simulation sim WHERE sim.ID='".addslashes($simId)."'")->fetch_object(); + if (!$obj) { + closeAndExit($db); + } + + if ($userName != 'alien-project' && $obj->workspace == ALIEN_PROJECT_WORKSPACE_TYPE) { closeAndExit($db); } @@ -56,10 +55,10 @@ function closeAndExit($db) { } // create Discord message - //if ($workspace != PRIVATE_WORKSPACE_TYPE) { - // $discordPayload = createAddResourceMessage($type, $simName, $userName, $simDesc, $width, $height, $particles); - // sendDiscordMessage($discordPayload); - //} + if ($obj->workspace != PRIVATE_WORKSPACE_TYPE) { + $discordPayload = createUpdateResourceMessage($obj->type, $obj->name, $userName, $simDesc, $width, $height, $particles); + sendDiscordMessage($discordPayload); + } echo json_encode(["result"=>true]); From 5dc53e98767e404483f4062cf02ebcaf9c37268f Mon Sep 17 00:00:00 2001 From: Christian Heinemann Date: Fri, 26 Apr 2024 17:37:54 +0200 Subject: [PATCH 14/16] + message before replacing items + ignore upper and lower case in the browser filter --- source/Gui/BrowserWindow.cpp | 98 +++++++++++++------------ source/Network/NetworkResourceRawTO.cpp | 36 ++++++--- 2 files changed, 77 insertions(+), 57 deletions(-) diff --git a/source/Gui/BrowserWindow.cpp b/source/Gui/BrowserWindow.cpp index 060248ac3..6dd9a9657 100644 --- a/source/Gui/BrowserWindow.cpp +++ b/source/Gui/BrowserWindow.cpp @@ -1293,58 +1293,62 @@ void _BrowserWindow::onDownloadResource(BrowserLeaf const& leaf) void _BrowserWindow::onReplaceResource(BrowserLeaf const& leaf) { - printOverlayMessage("Replacing ..."); + auto func = [&] { + printOverlayMessage("Replacing ..."); - delayedExecution([=, this] { - std::string mainData; - std::string settings; - std::string statistics; - IntVector2D worldSize; - int numObjects = 0; - - DeserializedSimulation deserializedSim; - if (leaf.rawTO->resourceType == NetworkResourceType_Simulation) { - deserializedSim = SerializationHelperService::getDeserializedSerialization(_simController); - - SerializedSimulation serializedSim; - if (!SerializerService::serializeSimulationToStrings(serializedSim, deserializedSim)) { - MessageDialog::getInstance().information("Replace simulation", "The simulation could not be serialized for replacing."); - return; - } - mainData = serializedSim.mainData; - settings = serializedSim.auxiliaryData; - statistics = serializedSim.statistics; - worldSize = {deserializedSim.auxiliaryData.generalSettings.worldSizeX, deserializedSim.auxiliaryData.generalSettings.worldSizeY}; - numObjects = deserializedSim.mainData.getNumberOfCellAndParticles(); - } else { - auto genome = _genomeEditorWindow.lock()->getCurrentGenome(); - if (genome.cells.empty()) { - showMessage("Replace genome", "The is no valid genome in the genome editor selected."); - return; + delayedExecution([=, this] { + std::string mainData; + std::string settings; + std::string statistics; + IntVector2D worldSize; + int numObjects = 0; + + DeserializedSimulation deserializedSim; + if (leaf.rawTO->resourceType == NetworkResourceType_Simulation) { + deserializedSim = SerializationHelperService::getDeserializedSerialization(_simController); + + SerializedSimulation serializedSim; + if (!SerializerService::serializeSimulationToStrings(serializedSim, deserializedSim)) { + MessageDialog::getInstance().information("Replace simulation", "The simulation could not be serialized for replacing."); + return; + } + mainData = serializedSim.mainData; + settings = serializedSim.auxiliaryData; + statistics = serializedSim.statistics; + worldSize = {deserializedSim.auxiliaryData.generalSettings.worldSizeX, deserializedSim.auxiliaryData.generalSettings.worldSizeY}; + numObjects = deserializedSim.mainData.getNumberOfCellAndParticles(); + } else { + auto genome = _genomeEditorWindow.lock()->getCurrentGenome(); + if (genome.cells.empty()) { + showMessage("Replace genome", "The is no valid genome in the genome editor selected."); + return; + } + auto genomeData = GenomeDescriptionService::convertDescriptionToBytes(genome); + numObjects = GenomeDescriptionService::getNumNodesRecursively(genomeData, true); + + if (!SerializerService::serializeGenomeToString(mainData, genomeData)) { + showMessage("Replace genome", "The genome could not be serialized for replacing."); + return; + } } - auto genomeData = GenomeDescriptionService::convertDescriptionToBytes(genome); - numObjects = GenomeDescriptionService::getNumNodesRecursively(genomeData, true); - if (!SerializerService::serializeGenomeToString(mainData, genomeData)) { - showMessage("Replace genome", "The genome could not be serialized for replacing."); + if (!NetworkService::replaceResource(leaf.rawTO->id, worldSize, numObjects, mainData, settings, statistics)) { + std::string type = leaf.rawTO->resourceType == NetworkResourceType_Simulation ? "simulation" : "genome"; + showMessage( + "Error", + "Failed to replace " + type + + ".\n\n" + "Possible reasons:\n\n" ICON_FA_CHEVRON_RIGHT " The server is not reachable.\n\n" ICON_FA_CHEVRON_RIGHT + " The total size of your uploads exceeds the allowed storage limit."); return; } - } - - if (!NetworkService::replaceResource(leaf.rawTO->id, worldSize, numObjects, mainData, settings, statistics)) { - std::string type = leaf.rawTO->resourceType == NetworkResourceType_Simulation ? "simulation" : "genome"; - showMessage( - "Error", - "Failed to replace " + type + ".\n\n" - "Possible reasons:\n\n" ICON_FA_CHEVRON_RIGHT " The server is not reachable.\n\n" ICON_FA_CHEVRON_RIGHT - " The total size of your uploads exceeds the allowed storage limit."); - return; - } - if (leaf.rawTO->resourceType == NetworkResourceType_Simulation) { - getSimulationCache().insertOrAssign(leaf.rawTO->id, deserializedSim); - } - onRefresh(); - }); + if (leaf.rawTO->resourceType == NetworkResourceType_Simulation) { + getSimulationCache().insertOrAssign(leaf.rawTO->id, deserializedSim); + } + onRefresh(); + }); + }; + MessageDialog::getInstance().yesNo("Delete", "Do you really want to replace the selected item?", func); } void _BrowserWindow::onEditResource(NetworkResourceTreeTO const& treeTO) diff --git a/source/Network/NetworkResourceRawTO.cpp b/source/Network/NetworkResourceRawTO.cpp index f453c85e3..1f55b666b 100644 --- a/source/Network/NetworkResourceRawTO.cpp +++ b/source/Network/NetworkResourceRawTO.cpp @@ -1,5 +1,6 @@ #include "NetworkResourceRawTO.h" +#include #include #include @@ -54,37 +55,52 @@ int _NetworkResourceRawTO::compare(NetworkResourceRawTO const& left, NetworkReso return 0; } +namespace +{ + bool containsIgnoreCase(std::string const& str, std::string const& substr) + { + std::string strLower = str; + std::string substrLower = substr; + + std::transform(str.begin(), str.end(), strLower.begin(), ::tolower); + std::transform(substr.begin(), substr.end(), substrLower.begin(), ::tolower); + + return strLower.find(substrLower) != std::string::npos; + } +} + bool _NetworkResourceRawTO::matchWithFilter(std::string const& filter) const { + auto match = false; - if (timestamp.find(filter) != std::string::npos) { + if (containsIgnoreCase(timestamp, filter)) { match = true; } - if (userName.find(filter) != std::string::npos) { + if (containsIgnoreCase(userName, filter)) { match = true; } - if (resourceName.find(filter) != std::string::npos) { + if (containsIgnoreCase(resourceName, filter)) { match = true; } - if (std::to_string(numDownloads).find(filter) != std::string::npos) { + if (containsIgnoreCase(std::to_string(numDownloads), filter)) { match = true; } - if (std::to_string(width).find(filter) != std::string::npos) { + if (containsIgnoreCase(std::to_string(width), filter)) { match = true; } - if (std::to_string(height).find(filter) != std::string::npos) { + if (containsIgnoreCase(std::to_string(height), filter)) { match = true; } - if (std::to_string(particles).find(filter) != std::string::npos) { + if (containsIgnoreCase(std::to_string(particles), filter)) { match = true; } - if (std::to_string(contentSize).find(filter) != std::string::npos) { + if (containsIgnoreCase(std::to_string(contentSize), filter)) { match = true; } - if (description.find(filter) != std::string::npos) { + if (containsIgnoreCase(description, filter)) { match = true; } - if (version.find(filter) != std::string::npos) { + if (containsIgnoreCase(version, filter)) { match = true; } return match; From 2032f5e1096594d36150afcc7c5419f145591731 Mon Sep 17 00:00:00 2001 From: Christian Heinemann Date: Fri, 26 Apr 2024 17:53:40 +0200 Subject: [PATCH 15/16] tooltip + button order adjusted --- RELEASE-NOTES.md | 11 +++++++++++ source/Base/Resources.h | 4 ++-- source/Gui/BrowserWindow.cpp | 19 ++++++++++--------- vcpkg.json | 2 +- 4 files changed, 24 insertions(+), 12 deletions(-) diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md index b167cde1c..e58548f7b 100644 --- a/RELEASE-NOTES.md +++ b/RELEASE-NOTES.md @@ -1,5 +1,16 @@ # Release notes +## [4.9.1] - 2024-04-26 +### Added +- gui/browser: label new simulations +- gui/browser: allow to replace simulations and genomes + +### Changed +- gui/browser: ignore upper and lower case in the browser filter + +### Fixed +- gui/browser: preserve subfolder names when renaming folders + ## [4.9.0] - 2024-04-22 ### Added - engine, gui/simulation parameters: conditional and unconditional energy inflow from external energy source diff --git a/source/Base/Resources.h b/source/Base/Resources.h index af78f23b7..24ab55e91 100644 --- a/source/Base/Resources.h +++ b/source/Base/Resources.h @@ -2,8 +2,8 @@ namespace Const { - std::string const ProgramVersion = "4.9.0"; - std::string const DiscordLink = "https://discord.gg/7bjyZdXXQ2"; + std::string const ProgramVersion = "4.9.1"; + std::string const DiscordURL = "https://discord.gg/7bjyZdXXQ2"; std::string const BasePath = "resources/"; diff --git a/source/Gui/BrowserWindow.cpp b/source/Gui/BrowserWindow.cpp index 6dd9a9657..763dafc24 100644 --- a/source/Gui/BrowserWindow.cpp +++ b/source/Gui/BrowserWindow.cpp @@ -288,14 +288,6 @@ void _BrowserWindow::processToolbar() + " to the server and made visible in the browser. You can choose whether you want to share it with other users or whether it should only be visible " "in your private workspace.\nIf you have already selected a folder, your " + resourceTypeString + " will be uploaded there."); - //replace button - ImGui::SameLine(); - ImGui::BeginDisabled(!isOwnerForSelectedItem || !_selectedTreeTO->isLeaf()); - if (AlienImGui::ToolbarButton(ICON_FA_EXCHANGE_ALT)) { - onReplaceResource(_selectedTreeTO->getLeaf()); - } - ImGui::EndDisabled(); - //edit button ImGui::SameLine(); ImGui::BeginDisabled(!isOwnerForSelectedItem); @@ -305,6 +297,15 @@ void _BrowserWindow::processToolbar() ImGui::EndDisabled(); AlienImGui::Tooltip("Change name or description"); + //replace button + ImGui::SameLine(); + ImGui::BeginDisabled(!isOwnerForSelectedItem || !_selectedTreeTO->isLeaf()); + if (AlienImGui::ToolbarButton(ICON_FA_EXCHANGE_ALT)) { + onReplaceResource(_selectedTreeTO->getLeaf()); + } + ImGui::EndDisabled(); + AlienImGui::Tooltip("Replace the selected " + resourceTypeString + " with the one that is currently open. The name, description and reactions will be maintained."); + //move to other workspace button ImGui::SameLine(); ImGui::BeginDisabled(!isOwnerForSelectedItem); @@ -349,7 +350,7 @@ void _BrowserWindow::processToolbar() //Discord button ImGui::SameLine(); if (AlienImGui::ToolbarButton(ICON_FA_COMMENTS)) { - openWeblink(Const::DiscordLink); + openWeblink(Const::DiscordURL); } AlienImGui::Tooltip("Open ALIEN Discord server"); #endif diff --git a/vcpkg.json b/vcpkg.json index 63efa832a..8f90814c4 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -1,6 +1,6 @@ { "name": "alien", - "version": "4.9.0", + "version": "4.9.1", "dependencies": [ { "name": "glew", From 374bfc52c625cc03e406255b6761a4314386ad95 Mon Sep 17 00:00:00 2001 From: Christian Heinemann Date: Fri, 26 Apr 2024 18:15:42 +0200 Subject: [PATCH 16/16] minor fixes --- scripts/Server/replacesimulation.php | 2 ++ source/Gui/BrowserWindow.cpp | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/Server/replacesimulation.php b/scripts/Server/replacesimulation.php index 423281e3c..c8fb47fbf 100644 --- a/scripts/Server/replacesimulation.php +++ b/scripts/Server/replacesimulation.php @@ -27,6 +27,8 @@ function closeAndExit($db) { $success = false; $particles = (int)$_POST['particles']; $version = $_POST['version']; + $width = (int)$_POST['width']; + $height = (int)$_POST['height']; $content = $_POST['content']; $settings = $_POST['settings']; $simId = $_POST['simId']; diff --git a/source/Gui/BrowserWindow.cpp b/source/Gui/BrowserWindow.cpp index 763dafc24..30b2f4e86 100644 --- a/source/Gui/BrowserWindow.cpp +++ b/source/Gui/BrowserWindow.cpp @@ -1349,7 +1349,7 @@ void _BrowserWindow::onReplaceResource(BrowserLeaf const& leaf) onRefresh(); }); }; - MessageDialog::getInstance().yesNo("Delete", "Do you really want to replace the selected item?", func); + MessageDialog::getInstance().yesNo("Delete", "Do you really want to replace the content of the selected item?", func); } void _BrowserWindow::onEditResource(NetworkResourceTreeTO const& treeTO)