mirror of
https://github.com/andrewchilicki/LumonMDR.git
synced 2025-07-01 18:17:27 -04:00
Cleanup
This commit is contained in:
@ -25,8 +25,7 @@ public:
|
||||
void drawImGuiImage(const std::string& imagePath, float scale, std::optional<ImVec4> 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<int, int> 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<Image> 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);
|
||||
|
@ -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<int>(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<int> 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<Number>(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>(badGroup++, std::vector{gridNumber->id}, randomNumber(0,4));
|
||||
badGroups.emplace(badGroup, gridNumber->badGroup);
|
||||
}
|
||||
|
@ -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> imageDisplay;
|
||||
|
||||
std::shared_ptr<NumbersPanel> numbersPanel;
|
||||
std::shared_ptr<IdleScreen> idleScreen;
|
||||
|
||||
bool debugMode = false;
|
||||
bool settingsMode = false;
|
||||
bool idleMode = false;
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
|
@ -3,7 +3,6 @@
|
||||
#include "ImageDisplay.h"
|
||||
#include <imgui.h>
|
||||
#include <iostream>
|
||||
#include <ostream>
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
|
@ -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<int> drawNumbersGrid(const ImVec2& windowPos, const ImVec2& windowSize, const ImVec2& mousePos, bool updateDisplayInfos)
|
||||
{
|
||||
std::optional<int> 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<int>(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;
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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<Settings> loadSettings(const std::string& jsonPath)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (auto json = loadSettingsFromJson(jsonPath))
|
||||
{
|
||||
try {
|
||||
if (auto json = loadSettingsFromJson(jsonPath)) {
|
||||
return json->get<Settings>();
|
||||
}
|
||||
} 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;
|
||||
}
|
||||
}
|
@ -1,11 +1,11 @@
|
||||
#include "UI/UIManager.h"
|
||||
|
||||
#include "imgui.h"
|
||||
#include "backends/imgui_impl_glfw.h"
|
||||
#include <GLFW/glfw3.h>
|
||||
#include <imgui_impl_opengl3.h>
|
||||
#include <iostream>
|
||||
|
||||
#include "UI/UIManager.h"
|
||||
|
||||
void glfw_error_callback(int error, const char* description) {
|
||||
std::cerr << "GLFW Error (" << error << "): " << description << std::endl;
|
||||
}
|
||||
|
Reference in New Issue
Block a user