From 1485f1325e7473eacdfdc02a452bc8a7287a8818 Mon Sep 17 00:00:00 2001 From: andrewchilicki Date: Sat, 8 Feb 2025 16:37:29 -0500 Subject: [PATCH] Cleanup --- libs/Image/ImageDisplay.cpp | 15 +-- libs/Numbers/NumberGrid.cpp | 116 ++++++----------- src/UI/UIManager.cpp | 38 +++--- src/UI/UIManager.h | 2 - src/UI/Widgets/IdleScreen.cpp | 18 +-- src/UI/Widgets/NumbersPanel.cpp | 214 +++++++++++++++----------------- src/UI/Widgets/NumbersPanel.h | 5 +- src/UI/Widgets/Settings.h | 28 +++-- src/main.cpp | 4 +- 9 files changed, 183 insertions(+), 257 deletions(-) diff --git a/libs/Image/ImageDisplay.cpp b/libs/Image/ImageDisplay.cpp index bdfbd34..b8e0409 100644 --- a/libs/Image/ImageDisplay.cpp +++ b/libs/Image/ImageDisplay.cpp @@ -25,8 +25,7 @@ public: void drawImGuiImage(const std::string& imagePath, float scale, std::optional tint) final { auto filePath = assetDir + imagePath; - if (auto image = getImageForFile(filePath)) - { + if (auto image = getImageForFile(filePath)) { ImGui::Image((ImTextureID)(intptr_t)image->texture, ImVec2(image->width*scale, image->height*scale), ImVec2(0,0), ImVec2(1,1), tint.value_or(ImVec4(1,1,1,1))); } @@ -35,8 +34,7 @@ public: std::pair getImageSize(const std::string &imagePath) final { auto filePath = assetDir + imagePath; - if (auto image = getImageForFile(filePath)) - { + if (auto image = getImageForFile(filePath)) { return std::make_pair(image->width, image->height); } return std::make_pair(0, 0); @@ -44,8 +42,7 @@ public: std::optional getImageForFile(const std::string& filePath) { - if (auto it = imageCache.find(filePath); it != imageCache.end()) - { + if (auto it = imageCache.find(filePath); it != imageCache.end()) { // Return from cache return it->second; } @@ -58,8 +55,7 @@ public: { // Load texture from file FILE* f = fopen(filePath.c_str(), "rb"); - if (f == NULL) - { + if (f == NULL) { std::cerr << "Failed to open file " << filePath << std::endl; return std::nullopt; } @@ -96,8 +92,9 @@ public: int image_width = 0; int image_height = 0; unsigned char* image_data = stbi_load_from_memory((const unsigned char*)data, (int)data_size, &image_width, &image_height, NULL, 4); - if (image_data == NULL) + if (image_data == NULL) { return false; + } GLuint image_texture; glGenTextures(1, &image_texture); diff --git a/libs/Numbers/NumberGrid.cpp b/libs/Numbers/NumberGrid.cpp index 3095899..c10607f 100644 --- a/libs/Numbers/NumberGrid.cpp +++ b/libs/Numbers/NumberGrid.cpp @@ -26,46 +26,36 @@ public: bool activeGroupStillVisible = false; bool newActiveBadGroup = false; - for (auto it = badGroups.begin(); it != badGroups.end(); ) - { - if (it->second->numberIds.empty()) - { + for (auto it = badGroups.begin(); it != badGroups.end(); ) { + if (it->second->numberIds.empty()) { it = badGroups.erase(it); - } - else - { + } else { ++it; } } // Update visible groups and check if active group is still visible - for (const auto &[groupId, badGroup] : badGroups) - { - for (const auto &numId : badGroup->numberIds) - { + for (const auto &[groupId, badGroup] : badGroups) { + for (const auto &numId : badGroup->numberIds) { auto num = numberIdMap.at(numId); - if (num->displayInfos.isVisible) - { + if (num->displayInfos.isVisible) { visibleBadGroups.emplace(groupId); - if (badGroup->isActive && groupId == *activeBadGroup) - { + if (badGroup->isActive && groupId == *activeBadGroup) { activeGroupStillVisible = true; } } } } - if (activeBadGroup && !activeGroupStillVisible) - { + if (activeBadGroup && !activeGroupStillVisible) { activeBadGroup.reset(); newActiveBadGroup = true; newBadGroupCountdown = randomNumber(5, 15) * 100; } // Select a new active group if necessary - if (!activeBadGroup && !visibleBadGroups.empty() && newBadGroupCountdown == 0) - { + if (!activeBadGroup && !visibleBadGroups.empty() && newBadGroupCountdown == 0) { auto randomIndex = randomNumber(0, static_cast(visibleBadGroups.size()) - 1); auto it = visibleBadGroups.begin(); std::advance(it, randomIndex); @@ -73,39 +63,27 @@ public: } // Update active groups / their scale - for (const auto &[groupId, badGroup] : badGroups) - { + for (const auto &[groupId, badGroup] : badGroups) { badGroup->isActive = activeBadGroup && groupId == *activeBadGroup; - if (badGroup->isActive) - { - if (newActiveBadGroup) - { + if (badGroup->isActive) { + if (newActiveBadGroup) { badGroup->scale = 0; - } - else - { - if (!badGroup->reachedMax) - { - if (badGroup->scale < 0.23) - { + } else { + if (!badGroup->reachedMax) { + if (badGroup->scale < 0.23) { badGroup->scale += (0.0001 * randomNumber(1, 10)); } - } else - { + } else { badGroup->scale -= (0.0001 * randomNumber(1, 10)); } - if (badGroup->scale >= 0.23) - { - if (!badGroup->superActive || badGroup->scale >= 0.24) - { + if (badGroup->scale >= 0.23) { + if (!badGroup->superActive || badGroup->scale >= 0.24) { badGroup->reachedMax = true; - } else - { + } else { badGroup->scale += 0.00001; } - } else if (badGroup->scale <= 0.0) - { + } else if (badGroup->scale <= 0.0) { badGroup->isActive = false; badGroup->superActive = false; badGroup->reachedMax = false; @@ -113,24 +91,20 @@ public: newBadGroupCountdown = randomNumber(5, 15) * 100; } } - } else - { + } else { badGroup->scale = 0; } } - if (newBadGroupCountdown > 0) - { + if (newBadGroupCountdown > 0) { newBadGroupCountdown--; } } NumberPtr getGridNumber(int x, int y) final { - if (auto itr = grid.find(x); itr != grid.end()) - { - if (auto itr2 = itr->second.find(y); itr2 != itr->second.end()) - { + if (auto itr = grid.find(x); itr != grid.end()) { + if (auto itr2 = itr->second.find(y); itr2 != itr->second.end()) { return itr2->second; } } @@ -139,8 +113,7 @@ public: NumberPtr getGridNumber(int id) final { - if (auto itr = numberIdMap.find(id); itr != numberIdMap.end()) - { + if (auto itr = numberIdMap.find(id); itr != numberIdMap.end()) { return itr->second; } return nullptr; @@ -170,16 +143,13 @@ private: { int numberId = 0; std::set badNumbers; - for (int x = 0; x < size; x++) - { - for (int y = 0; y < size; y++) - { + for (int x = 0; x < size; x++) { + for (int y = 0; y < size; y++) { grid[x][y] = std::make_shared(numberId, x, y, randomNumber(0,9), randomBool()); numberIdMap[numberId] = grid[x][y]; // Determine if bad - if (perlinBadNumbers.noise2D_01(x*badScale,y*badScale) > badThresh) - { + if (perlinBadNumbers.noise2D_01(x*badScale,y*badScale) > badThresh) { badNumbers.insert(numberId); } @@ -188,44 +158,34 @@ private: } // Assign 'bad groups' - auto checkAdjacent = [&](int x, int y) -> BadGroupPtr - { - if (auto gridNum = getGridNumber(x, y)) - { + auto checkAdjacent = [&](int x, int y) -> BadGroupPtr { + if (auto gridNum = getGridNumber(x, y)) { return gridNum->badGroup; } return nullptr; }; int badGroup = 0; - for (const auto &badNumId : badNumbers) - { + for (const auto &badNumId : badNumbers) { auto gridNumber = numberIdMap.at(badNumId); - if (!gridNumber->badGroup) - { - for (int checkX = -1; checkX <= 1; checkX++) - { - for (int checkY = -1; checkY <= 1; checkY++) - { - if (checkX == 0 && checkY == 0) - { + if (!gridNumber->badGroup) { + for (int checkX = -1; checkX <= 1; checkX++) { + for (int checkY = -1; checkY <= 1; checkY++) { + if (checkX == 0 && checkY == 0) { continue; } - if (auto badGroupPtr = checkAdjacent(gridNumber->gridX + checkX, gridNumber->gridY + checkY)) - { + if (auto badGroupPtr = checkAdjacent(gridNumber->gridX + checkX, gridNumber->gridY + checkY)) { gridNumber->badGroup = badGroupPtr; gridNumber->badGroup->numberIds.emplace_back(gridNumber->id); break; } } - if (gridNumber->badGroup) - { + if (gridNumber->badGroup) { break; } } - if (!gridNumber->badGroup) - { + if (!gridNumber->badGroup) { gridNumber->badGroup = std::make_shared(badGroup++, std::vector{gridNumber->id}, randomNumber(0,4)); badGroups.emplace(badGroup, gridNumber->badGroup); } diff --git a/src/UI/UIManager.cpp b/src/UI/UIManager.cpp index a3f8356..8c24738 100644 --- a/src/UI/UIManager.cpp +++ b/src/UI/UIManager.cpp @@ -11,7 +11,7 @@ namespace ColorValues { - ImColor lumonBlue = ImColor(101,213,235,255); + ImColor lumonBlue = ImColor(157,227,235,255); } class UIManagerImpl : public UIManager @@ -39,26 +39,25 @@ public: void update() final { - if (ImGui::IsKeyPressed(ImGuiKey_Tab)) - { - debugMode = !debugMode; + // Toggle settings mode with 'TAB' + if (ImGui::IsKeyPressed(ImGuiKey_Tab)) { + settingsMode = !settingsMode; } - if (ImGui::IsKeyPressed(ImGuiKey_I)) - { + // Toggle idle mode with 'I' + if (ImGui::IsKeyPressed(ImGuiKey_I)) { idleMode = !idleMode; } - if (idleMode) - { + if (idleMode) { idleScreen->update(); - if (ImGui::IsMouseClicked(ImGuiMouseButton_Left)) - { + + // Exit idle mode with 'LEFT CLICK' + if (ImGui::IsMouseClicked(ImGuiMouseButton_Left)) { idleMode = false; numbersPanel->triggerLoadAnimation(); } - } else - { + } else { numbersPanel->update(); } } @@ -76,22 +75,18 @@ public: ImGui::SetNextWindowSize(ImVec2(viewportSize.x, viewportSize.y)); if (ImGui::Begin("Main", nullptr, ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse)) { - if (idleMode) - { + if (idleMode) { idleScreen->drawIdleScreen(); - } else - { + } else { numbersPanel->drawNumbersPanel(); } } ImGui::End(); - if (debugMode) - { + if (settingsMode) { ImGui::SetNextWindowPos(viewportPos); ImGui::SetNextWindowSize(ImVec2(viewportSize.x * settingsWidthRatio, viewportSize.y)); - if (ImGui::Begin("Settings")) - { + if (ImGui::Begin("Settings")) { numbersPanel->drawSettings(); } ImGui::End(); @@ -107,11 +102,10 @@ public: private: std::shared_ptr imageDisplay; - std::shared_ptr numbersPanel; std::shared_ptr idleScreen; - bool debugMode = false; + bool settingsMode = false; bool idleMode = false; }; diff --git a/src/UI/UIManager.h b/src/UI/UIManager.h index 727e834..09e8035 100644 --- a/src/UI/UIManager.h +++ b/src/UI/UIManager.h @@ -13,10 +13,8 @@ namespace ColorValues class UIManager { public: virtual void init() = 0; - virtual void draw() = 0; virtual void update() = 0; - virtual void cleanup() = 0; virtual ~UIManager() = default; diff --git a/src/UI/Widgets/IdleScreen.cpp b/src/UI/Widgets/IdleScreen.cpp index 37f3647..ed09888 100644 --- a/src/UI/Widgets/IdleScreen.cpp +++ b/src/UI/Widgets/IdleScreen.cpp @@ -3,7 +3,6 @@ #include "ImageDisplay.h" #include #include -#include #include "../UIManager.h" @@ -18,10 +17,9 @@ public: void update() final { - // Adjust logo scale and speed based on viewport size so it is consistent + // Want scale proportionally to the window size auto viewportSize = ImGui::GetMainViewport()->Size; - if (lastViewportSize.x != viewportSize.x || lastViewportSize.y != viewportSize.y) - { + if (lastViewportSize.x != viewportSize.x || lastViewportSize.y != viewportSize.y) { float displaySizeScalePrev = lastViewportSize.x/1280.f; float displaySizeScale = viewportSize.x/1280.f; float adjustedScale = displaySizeScale / displaySizeScalePrev; @@ -46,19 +44,15 @@ public: ImVec2 minPosition = ImVec2(windowPos.x, windowPos.y); ImVec2 maxPosition = ImVec2(windowPos.x + windowSize.x - scale*logoSize.x, windowPos.y + windowSize.y - scale*logoSize.y); - if (currentLogoPosition.x >= maxPosition.x) - { + if (currentLogoPosition.x >= maxPosition.x) { nextOffset.x = -1; - } else if (currentLogoPosition.x < minPosition.x) - { + } else if (currentLogoPosition.x < minPosition.x) { nextOffset.x = 1; } - if (currentLogoPosition.y >= maxPosition.y) - { + if (currentLogoPosition.y >= maxPosition.y) { nextOffset.y = -1; - } else if (currentLogoPosition.y < minPosition.y) - { + } else if (currentLogoPosition.y < minPosition.y) { nextOffset.y = 1; } diff --git a/src/UI/Widgets/NumbersPanel.cpp b/src/UI/Widgets/NumbersPanel.cpp index 7fadae5..a71b0cd 100644 --- a/src/UI/Widgets/NumbersPanel.cpp +++ b/src/UI/Widgets/NumbersPanel.cpp @@ -23,14 +23,12 @@ public: // Update max bad groups for each bin auto badGroups = numberGrid->getBadGroups(); - for (auto &[id, group] : badGroups) - { + for (auto &[id, group] : badGroups) { bins[group->binIdx].maxBadGroups++; } // Load settings - if (auto loadedSettings = loadSettings(settingsSavePath)) - { + if (auto loadedSettings = loadSettings(settingsSavePath)) { displaySettings = loadedSettings->displaySettings; controlSettings = loadedSettings->controlSettings; std::cout << "Successfully loaded settings from disk." << std::endl; @@ -43,8 +41,7 @@ public: ImGuiIO& io = ImGui::GetIO(); font = io.Fonts->AddFontFromFileTTF("./assets/Montserrat-Bold.ttf", 50.f); io.Fonts->Build(); - if (font == nullptr) - { + if (font == nullptr) { font = ImGui::GetDefaultFont(); std::cerr << "Failed to load 'Montserrat-Bold' font." << std::endl; } @@ -82,29 +79,26 @@ public: void triggerLoadAnimation() final { // Reset 'regenerate scale' on all numbers - for (auto &[x, gridY] : numberGrid->getGrid()) - { - for (auto &[y, gridNumber] : gridY) - { + for (auto &[x, gridY] : numberGrid->getGrid()) { + for (auto &[y, gridNumber] : gridY) { gridNumber->regenerateScale = 0.f; } } - } private: std::optional drawNumbersGrid(const ImVec2& windowPos, const ImVec2& windowSize, const ImVec2& mousePos, bool updateDisplayInfos) { std::optional refiningToBin = std::nullopt; - for (auto &[x, gridY] : numberGrid->getGrid()) - { - for (auto &[y, gridNumber] : gridY) - { + for (auto &[x, gridY] : numberGrid->getGrid()) { + for (auto &[y, gridNumber] : gridY) { + std::string numberToDraw = "numbers/" + std::to_string(gridNumber->num) + ".png"; auto [width, height] = imageDisplay->getImageSize(numberToDraw); double badScale = gridNumber->badGroup ? gridNumber->badGroup->scale : 0.0; - if (updateDisplayInfos) - { + + if (updateDisplayInfos) { + // Only need to update when viewport has changed ImVec2 localNumberPos = ImVec2((x * displaySettings.gridSpacing + panelOffset.x)*panelScale, (y * displaySettings.gridSpacing + panelOffset.y)*panelScale); gridNumber->displayInfos.centerX = localNumberPos.x + windowPos.x; gridNumber->displayInfos.centerY = localNumberPos.y + windowPos.y; @@ -114,104 +108,97 @@ private: double heightOffset = (baseNumberScale*height/2.f); gridNumber->displayInfos.isVisible = gridNumber->displayInfos.centerX + widthOffset < windowPos.x + windowSize.x && gridNumber->displayInfos.centerX - widthOffset > windowPos.x && gridNumber->displayInfos.centerY + heightOffset < windowPos.y + windowSize.y - displayPresets.numberWindowBufferBottom && gridNumber->displayInfos.centerY - heightOffset > windowPos.y + displayPresets.numberWindowBufferTop; - } - if (!gridNumber->displayInfos.isVisible) - { + // Don't draw numbers out of viewport + if (!gridNumber->displayInfos.isVisible) { continue; } auto centerPos = ImVec2(gridNumber->displayInfos.centerX, gridNumber->displayInfos.centerY); - if (gridNumber->badGroup && gridNumber->badGroup->refined) - { - float startX = gridNumber->displayInfos.centerX; - float startY = gridNumber->displayInfos.centerY; - - if (gridNumber->displayInfos.refinedX == -1) - { - gridNumber->displayInfos.refinedX = startX; - gridNumber->displayInfos.refinedY = startY; - } - - auto binIdx = gridNumber->badGroup->binIdx; - if (binIdx > 4) - { - std::cout << "Error: Bin index greater than expected. Setting to max." << std::endl; - binIdx = 4; - } - - float distX = bins[binIdx].pos.x - gridNumber->displayInfos.refinedX; - float distY = bins[binIdx].pos.y - gridNumber->displayInfos.refinedY; - float distance = sqrt(distX * distX + distY * distY); - - const float moveSpeed = 3.0f; - if (distance > moveSpeed) - { - float dirX = distX / distance; - float dirY = distY / distance; - gridNumber->displayInfos.refinedX += dirX * moveSpeed; - gridNumber->displayInfos.refinedY += dirY * moveSpeed; - centerPos = ImVec2(gridNumber->displayInfos.refinedX, gridNumber->displayInfos.refinedY); - - refiningToBin = gridNumber->badGroup->binIdx; - } - else - { - gridNumber->badGroup.reset(); // No longer a bad number - gridNumber->num = numberGrid->randomNumber(0,9); - gridNumber->regenerateScale = 0.f; - } - } - + // Animate number on screen float numberAlpha = 255; - if (gridNumber->regenerateScale < 1.f) - { + if (gridNumber->regenerateScale < 1.f) { gridNumber->regenerateScale += numberGrid->randomNumber(0,10)*0.001f; numberAlpha = static_cast(std::clamp(gridNumber->regenerateScale*2.f*255.f, 0.f, 255.f)); } // Offset from noise scale double noiseScale = perlin.noise3D((x * displaySettings.noiseScale), (y * displaySettings.noiseScale), t*displaySettings.noiseSpeed); - if (gridNumber->displayInfos.horizontalOffset) - { + if (gridNumber->displayInfos.horizontalOffset) { centerPos.x += noiseScale*displaySettings.noiseScaleOffset; - } else - { + } else { centerPos.y += noiseScale*displaySettings.noiseScaleOffset; } // Colour auto col = ColorValues::lumonBlue.Value; col.w = numberAlpha; - if (revealMap && gridNumber->badGroup) - { + if (revealMap && gridNumber->badGroup) { col = gridNumber->badGroup->isActive ? ImVec4(255,255,0,numberAlpha) : ImVec4(255,0,0,255); } // Scale from mouse hovering auto numberScale = getScaleFromCursor(centerPos, mousePos); - if (gridNumber->badGroup && gridNumber->badGroup->isActive) - { - if (numberScale > 1.0f) - { - gridNumber->badGroup->superActive = true; + // Handle if part of bad group + if (gridNumber->badGroup) { + if (gridNumber->badGroup->isActive) { + // Make number 'super active' + if (numberScale > 1.0f) { + gridNumber->badGroup->superActive = true; + } + // Mark as refined on 'LEFT CLICK' + if (numberScale >= (0.5f + displaySettings.mouseScaleMultiplier) && ImGui::IsKeyDown(ImGuiKey_MouseLeft)) { + gridNumber->badGroup->refined = true; + bins[gridNumber->badGroup->binIdx].badGroupsRefined++; + } } - if (numberScale >= (0.5f + displaySettings.mouseScaleMultiplier) && ImGui::IsKeyDown(ImGuiKey_MouseLeft)) - { - gridNumber->badGroup->refined = true; - bins[gridNumber->badGroup->binIdx].badGroupsRefined++; + + // Add jitter to 'super active' bad numbers + if (gridNumber->badGroup->superActive) { + centerPos.x += numberGrid->randomNumber(-10, 10)*badScale; + centerPos.y += numberGrid->randomNumber(-10, 10)*badScale; + } + + // Animate position if number has been refined + if (gridNumber->badGroup->refined) { + float startX = gridNumber->displayInfos.centerX; + float startY = gridNumber->displayInfos.centerY; + + if (gridNumber->displayInfos.refinedX == -1) { + gridNumber->displayInfos.refinedX = startX; + gridNumber->displayInfos.refinedY = startY; + } + + auto binIdx = gridNumber->badGroup->binIdx; + if (binIdx > 4) { + std::cout << "Error: Bin index greater than expected. Setting to max." << std::endl; + binIdx = 4; + } + + float distX = bins[binIdx].pos.x - gridNumber->displayInfos.refinedX; + float distY = bins[binIdx].pos.y - gridNumber->displayInfos.refinedY; + float distance = sqrt(distX * distX + distY * distY); + + if (distance > displaySettings.refinedToBinSpeed) { + float dirX = distX / distance; + float dirY = distY / distance; + gridNumber->displayInfos.refinedX += dirX * displaySettings.refinedToBinSpeed; + gridNumber->displayInfos.refinedY += dirY * displaySettings.refinedToBinSpeed; + centerPos = ImVec2(gridNumber->displayInfos.refinedX, gridNumber->displayInfos.refinedY); + + refiningToBin = gridNumber->badGroup->binIdx; + } else { + gridNumber->badGroup.reset(); // No longer a bad number + gridNumber->num = numberGrid->randomNumber(0,9); + gridNumber->regenerateScale = 0.f; + } } } - if (gridNumber->badGroup && gridNumber->badGroup->superActive) - { - centerPos.x += numberGrid->randomNumber(-10, 10)*badScale; - centerPos.y += numberGrid->randomNumber(-10, 10)*badScale; - } - + // Draw number float combinedScale = gridNumber->regenerateScale*displaySettings.imageScale*numberScale*panelScale + badScale; ImGui::SetCursorPos(ImVec2(centerPos.x - ImGui::GetWindowPos().x - ((width*combinedScale)/2.f), centerPos.y - ImGui::GetWindowPos().y - ((height*combinedScale)/2.f))); imageDisplay->drawImGuiImage(numberToDraw, combinedScale, col); @@ -226,10 +213,11 @@ private: { std::string binPercentPath = "bins/bin-percent.png"; auto [widthP, heightP] = imageDisplay->getImageSize(binPercentPath); - for (auto &b : bins) - { + for (auto &b : bins) { + // Scale based on viewport size auto pos = b.updatePos(windowSize, windowPos, displayPresets.numberWindowBufferBottom - displayPresets.binOffset); + // Draw bin images std::string binPath = "bins/bin0" + std::to_string(b.id) + ".png"; auto [width, height] = imageDisplay->getImageSize(binPath); ImGui::SetCursorPos(ImVec2(pos.x - windowPos.x - (width*displayPresets.binImageScale/2.f), pos.y - windowPos.y - (height*displayPresets.binImageScale/2.f))); @@ -239,6 +227,7 @@ private: ImGui::SetCursorPos(ImVec2(percentPos.x - windowPos.x - (widthP*displayPresets.binImageScale/2.f), percentPos.y - windowPos.y - (heightP*displayPresets.binImageScale/2.f))); imageDisplay->drawImGuiImage(binPercentPath, displayPresets.binImageScale, ColorValues::lumonBlue); + // Draw percentage bar and text ImVec2 trCorner = ImVec2(percentPos.x - (widthP*displayPresets.binImageScale/2.f), percentPos.y - (heightP*displayPresets.binImageScale/2.f)); ImVec2 brCorner = ImVec2(percentPos.x + (widthP*displayPresets.binImageScale/2.f), percentPos.y + (heightP*displayPresets.binImageScale/2.f)); @@ -249,9 +238,8 @@ private: drawList->AddRectFilled(trCorner, ImVec2(trCorner.x + ((brCorner.x - trCorner.x)* percentD), brCorner.y), ImColor(ColorValues::lumonBlue.Value.x, ColorValues::lumonBlue.Value.y, ColorValues::lumonBlue.Value.z, 0.3f)); - // Bin open - if (numberRefiningToBin && *numberRefiningToBin == b.id - 1) - { + // Animate bin open + if (numberRefiningToBin && *numberRefiningToBin == b.id - 1) { std::string binOpenPath = "bins/bin-open.png"; auto [widthO, heightO] = imageDisplay->getImageSize(binOpenPath); ImGui::SetCursorPos(ImVec2(pos.x - windowPos.x - (widthO*displayPresets.binImageScale/2.f), pos.y - windowPos.y - (heightO*displayPresets.binImageScale/2.f) - (height*displayPresets.binImageScale))); @@ -268,6 +256,7 @@ private: drawList->AddRect(headerBoxMin, headerBoxMax, ColorValues::lumonBlue); ImVec2 headerTextPos = ImVec2(headerBoxMin.x + 25.f, (headerBoxMin.y+headerBoxMax.y)/2.f - displayPresets.fontSize/2.f); drawList->AddText(font, displayPresets.fontSize, headerTextPos, ColorValues::lumonBlue, "@andrewchilicki"); + // Lumon logo std::string logoPath = "lumon-logo.png"; auto [widthH, heightH] = imageDisplay->getImageSize(logoPath); @@ -275,8 +264,7 @@ private: imageDisplay->drawImGuiImage(logoPath, displayPresets.headerImageScale, ColorValues::lumonBlue); // Horizontal lines - auto drawLine = [&](const float y) - { + auto drawLine = [&](const float y) { drawList->AddLine(ImVec2(windowPos.x, y), ImVec2(windowPos.x + windowSize.x, y), ColorValues::lumonBlue, displayPresets.lineThickness); }; @@ -294,40 +282,33 @@ private: static bool viewportInit = false; bool viewportChanged = !viewportInit; // Handle arrow key input - if (ImGui::IsKeyPressed(ImGuiKey_LeftArrow)) - { + if (ImGui::IsKeyPressed(ImGuiKey_LeftArrow)) { panelOffset.x += controlSettings.arrowSensitivity; viewportChanged = true; - } else if (ImGui::IsKeyPressed(ImGuiKey_RightArrow)) - { + } else if (ImGui::IsKeyPressed(ImGuiKey_RightArrow)) { panelOffset.x -= controlSettings.arrowSensitivity; viewportChanged = true; } - if (ImGui::IsKeyPressed(ImGuiKey_UpArrow)) - { + if (ImGui::IsKeyPressed(ImGuiKey_UpArrow)) { panelOffset.y += controlSettings.arrowSensitivity; viewportChanged = true; - } else if (ImGui::IsKeyPressed(ImGuiKey_DownArrow)) - { + } else if (ImGui::IsKeyPressed(ImGuiKey_DownArrow)) { panelOffset.y -= controlSettings.arrowSensitivity; viewportChanged = true; } // Handle zoom - if (ImGui::IsKeyPressed(ImGuiKey_Comma)) - { + if (ImGui::IsKeyPressed(ImGuiKey_Comma)) { panelScale -= controlSettings.zoomSensitivity; viewportChanged = true; - } else if (ImGui::IsKeyPressed(ImGuiKey_Period)) - { + } else if (ImGui::IsKeyPressed(ImGuiKey_Period)) { panelScale += controlSettings.zoomSensitivity; viewportChanged = true; } - // panelScale = std::clamp(panelScale, 0.8f, 1.8f); + panelScale = std::clamp(panelScale, displaySettings.minZoomScale, displaySettings.maxZoomScale); - if (viewportChanged) - { + if (viewportChanged) { // Clamp movement to within grid boundaries float gridWidthScaled = gridSize * displaySettings.gridSpacing * panelScale; float gridHeightScaled = gridSize * displaySettings.gridSpacing * panelScale; @@ -337,8 +318,7 @@ private: float minOffsetY = -gridHeightScaled + windowSize.y - displayPresets.numberWindowBufferTop; float maxOffsetY = displayPresets.numberWindowBufferTop; - if (!viewportInit) - { + if (!viewportInit) { // Start at center of grid panelOffset.x = (windowSize.x - gridWidthScaled) / 2.0f / panelScale; panelOffset.y = (windowSize.y - gridHeightScaled) / 2.0f / panelScale; @@ -355,8 +335,7 @@ private: void drawSettings() final { ImGui::SetWindowFontScale(displayPresets.settingsFontScale); - if (ImGui::Button("Save Settings")) - { + if (ImGui::Button("Save Settings")) { saveSettings(Settings{displaySettings, controlSettings}, settingsSavePath); } ImGui::Separator(); @@ -366,6 +345,9 @@ private: ImGui::InputFloat("Numbers Grid Spacing", &displaySettings.gridSpacing); ImGui::InputFloat("Mouse Scale Radius", &displaySettings.mouseScaleRadius); ImGui::InputFloat("Mouse Scale Multiplier", &displaySettings.mouseScaleMultiplier); + ImGui::InputFloat("Min Scale Multiplier", &displaySettings.minZoomScale); + ImGui::InputFloat("Max Scale Multiplier", &displaySettings.maxZoomScale); + ImGui::InputFloat("Refined to Bin Speed", &displaySettings.refinedToBinSpeed); ImGui::Text("Noise:"); ImGui::InputFloat("Noise Speed", &displaySettings.noiseSpeed); ImGui::InputFloat("Noise Scale", &displaySettings.noiseScale); @@ -380,11 +362,12 @@ private: bool updateDisplaySettings(PresetDisplaySettings &settings, float globalScale) { + // Want preset display settings to scale proportionally to the window size auto viewportSize = ImGui::GetMainViewport()->Size; - if (lastViewportSize.x == viewportSize.x && lastViewportSize.y == viewportSize.y && lastGlobalScale == globalScale) - { + if (lastViewportSize.x == viewportSize.x && lastViewportSize.y == viewportSize.y && lastGlobalScale == globalScale) { return false; } + float displaySizeScalePrev = lastViewportSize.x/1280.f * lastGlobalScale; float displaySizeScale = viewportSize.x/1280.f * globalScale; float newScale = displaySizeScale / displaySizeScalePrev; @@ -415,8 +398,7 @@ private: float distY = mousePos.y - globalNumberPos.y; float distance = sqrt(distX * distX + distY * distY); - if (distance < displaySettings.mouseScaleRadius) - { + if (distance < displaySettings.mouseScaleRadius) { return 1.0f + (displaySettings.mouseScaleRadius - distance) / displaySettings.mouseScaleRadius * displaySettings.mouseScaleMultiplier; } return 1.0f; @@ -443,6 +425,7 @@ private: // Debug options bool revealMap = false; + // TODO - Move to class struct Bin { int id; @@ -451,8 +434,7 @@ private: int badGroupsRefined = 0; int maxBadGroups = 0; - ImVec2 updatePos(const ImVec2 &windowSize, const ImVec2 &windowPos, float offsetY) - { + ImVec2 updatePos(const ImVec2 &windowSize, const ImVec2 &windowPos, float offsetY) { pos = ImVec2(windowPos.x + (windowSize.x / 6)*id, windowPos.y + windowSize.y - offsetY); return pos; } diff --git a/src/UI/Widgets/NumbersPanel.h b/src/UI/Widgets/NumbersPanel.h index bddd2e5..78d34ff 100644 --- a/src/UI/Widgets/NumbersPanel.h +++ b/src/UI/Widgets/NumbersPanel.h @@ -6,14 +6,13 @@ class ImageDisplay; class NumbersPanel { public: virtual void init() = 0; - virtual void update() = 0; + virtual void drawNumbersPanel() = 0; + virtual void drawSettings() = 0; virtual void triggerLoadAnimation() = 0; - virtual void drawSettings() = 0; - virtual ~NumbersPanel() = default; }; diff --git a/src/UI/Widgets/Settings.h b/src/UI/Widgets/Settings.h index c578cf2..a330be9 100644 --- a/src/UI/Widgets/Settings.h +++ b/src/UI/Widgets/Settings.h @@ -7,6 +7,7 @@ struct PresetDisplaySettings { + // Preset sizing and offsets for UI float numberWindowBufferTop = 125.f; float numberWindowBufferBottom = 115.f; @@ -57,8 +58,7 @@ inline void saveSettingsJson(const nlohmann::json& settingsJson, const std::stri file.flush(); file.close(); std::cout << "Settings saved to disk." << std::endl; - } - catch (const std::exception& e) { + } catch (const std::exception& e) { std::cerr << "Error saving settings: " << e.what() << std::endl; } } @@ -72,20 +72,27 @@ struct DisplaySettings float mouseScaleRadius = 100.f; float mouseScaleMultiplier = 2.f; + float maxZoomScale = 0.8f; + float minZoomScale = 0.2f; float noiseSpeed = 0.004f; float noiseScale = 1.f; float noiseScaleOffset = 15; + float refinedToBinSpeed = 3.0f; + NLOHMANN_DEFINE_TYPE_INTRUSIVE(DisplaySettings, globalScale, imageScale, gridSpacing, mouseScaleRadius, mouseScaleMultiplier, + maxZoomScale, + minZoomScale, noiseSpeed, noiseScale, - noiseScaleOffset + noiseScaleOffset, + refinedToBinSpeed ); }; @@ -107,26 +114,21 @@ struct Settings inline std::optional loadSettings(const std::string& jsonPath) { - try - { - if (auto json = loadSettingsFromJson(jsonPath)) - { + try { + if (auto json = loadSettingsFromJson(jsonPath)) { return json->get(); } - } catch (const std::exception& e) - { + } catch (const std::exception& e) { std::cerr << "Error loading settings: " << e.what() << std::endl; } return std::nullopt; } inline void saveSettings(const Settings& settings, const std::string& jsonPath) { - try - { + try { nlohmann::json json = settings; saveSettingsJson(json, jsonPath); - } catch (const std::exception& e) - { + } catch (const std::exception& e) { std::cerr << "Error saving settings: " << e.what() << std::endl; } } \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 254307b..de35ec2 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,11 +1,11 @@ +#include "UI/UIManager.h" + #include "imgui.h" #include "backends/imgui_impl_glfw.h" #include #include #include -#include "UI/UIManager.h" - void glfw_error_callback(int error, const char* description) { std::cerr << "GLFW Error (" << error << "): " << description << std::endl; }