restarted because i cant do it
visualising sorting through value/step diagrams
This commit is contained in:
parent
f02f77d5df
commit
90ac688f3d
18 changed files with 231 additions and 1142 deletions
|
@ -111,7 +111,7 @@ function(set_common_properties target)
|
|||
endfunction()
|
||||
|
||||
# ========================================================
|
||||
# GUI Setup
|
||||
# Executable
|
||||
# ========================================================
|
||||
|
||||
set(GUI_TARGET_NAME "${PROJECT_NAME}")
|
||||
|
@ -156,24 +156,7 @@ endif()
|
|||
|
||||
set_common_properties(${GUI_TARGET_NAME})
|
||||
|
||||
# =============
|
||||
# spdlog
|
||||
# =============
|
||||
set(SPDLOG_NO_EXCEPTIONS ON CACHE BOOL "" FORCE)
|
||||
|
||||
FetchContent_Declare(
|
||||
spdlog
|
||||
GIT_REPOSITORY https://github.com/gabime/spdlog.git
|
||||
GIT_TAG v1.15.0
|
||||
)
|
||||
FetchContent_MakeAvailable(spdlog)
|
||||
target_link_libraries(${GUI_TARGET_NAME} PRIVATE spdlog)
|
||||
|
||||
put_targets_into_folder(
|
||||
FOLDER "ThirdParty/spdlog"
|
||||
TARGETS
|
||||
spdlog
|
||||
)
|
||||
|
||||
put_targets_into_folder(
|
||||
FOLDER "ThirdParty/raylib"
|
||||
|
|
|
@ -1,107 +0,0 @@
|
|||
#pragma once
|
||||
#include <chrono>
|
||||
#include <iostream>
|
||||
#include <optional>
|
||||
#include <assert.h>
|
||||
#include <types.hpp>
|
||||
|
||||
struct timer_result
|
||||
{
|
||||
double seconds = 0;
|
||||
double difftime = 0;
|
||||
};
|
||||
|
||||
struct Timer {
|
||||
enum State : u8
|
||||
{
|
||||
running = 0,
|
||||
paused = 1
|
||||
};
|
||||
State state = paused;
|
||||
|
||||
std::clock_t begin;
|
||||
std::clock_t elapsed = 0;
|
||||
std::optional<std::ostream*> out;
|
||||
std::optional<timer_result*> result;
|
||||
|
||||
Timer() : begin(std::clock()) {}
|
||||
Timer(std::ostream& o) : begin(std::clock()), out(&o) {}
|
||||
Timer(timer_result& r) : begin(std::clock()), result(&r) {}
|
||||
Timer(std::ostream& o, timer_result& r) : begin(std::clock()), out(&o), result(&r) {}
|
||||
Timer(State initial_state) : state(initial_state), begin(std::clock())
|
||||
{
|
||||
if (state == paused)
|
||||
begin = 0;
|
||||
}
|
||||
|
||||
Timer(std::ostream& o, State initial_state) : state(initial_state), begin(std::clock()), out(&o)
|
||||
{
|
||||
if (state == paused)
|
||||
begin = 0;
|
||||
}
|
||||
Timer(timer_result& r, State initial_state) : state(initial_state), begin(std::clock()), result(&r)
|
||||
{
|
||||
if (state == paused)
|
||||
begin = 0;
|
||||
}
|
||||
|
||||
Timer(std::ostream& o, timer_result& r, State initial_state) : state(initial_state), begin(std::clock()), out(&o), result(&r)
|
||||
{
|
||||
if (state == paused)
|
||||
begin = 0;
|
||||
}
|
||||
|
||||
void reset(State init_state) {
|
||||
if (state == paused)
|
||||
begin = 0;
|
||||
else
|
||||
begin = std::clock();
|
||||
elapsed = 0;
|
||||
state = init_state;
|
||||
lap();
|
||||
}
|
||||
|
||||
void set_state(State new_state)
|
||||
{
|
||||
if (this->state == new_state)
|
||||
return;
|
||||
|
||||
if (new_state == running)
|
||||
{
|
||||
begin = std::clock();
|
||||
}
|
||||
else // pausing
|
||||
{
|
||||
assert(begin != 0);
|
||||
elapsed += std::clock() - begin;
|
||||
begin = 0;
|
||||
}
|
||||
|
||||
lap();
|
||||
this->state = new_state;
|
||||
}
|
||||
|
||||
void lap()
|
||||
{
|
||||
std::clock_t total_time = elapsed;
|
||||
if (state == running)
|
||||
{
|
||||
total_time += std::clock() - begin;
|
||||
}
|
||||
|
||||
if (result)
|
||||
{
|
||||
result.value()->seconds = static_cast<double>(total_time) / CLOCKS_PER_SEC;
|
||||
result.value()->difftime = static_cast<double>(total_time) / CLOCKS_PER_SEC;
|
||||
}
|
||||
if (out)
|
||||
{
|
||||
*out.value() << static_cast<double>(total_time) / CLOCKS_PER_SEC << " seconds.\n";
|
||||
*out.value() << "Total time = " << static_cast<double>(total_time) / CLOCKS_PER_SEC << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
~Timer() {
|
||||
lap();
|
||||
}
|
||||
};
|
|
@ -1,129 +0,0 @@
|
|||
#include "BigSortComponent.hpp"
|
||||
#include <raylibs/raygui.h>
|
||||
#include "raylibs/raygui.h"
|
||||
|
||||
BigSortComponent::BigSortComponent() : m_Sorter(2000)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
int BigSortComponent::draw()
|
||||
{
|
||||
// raygui: controls drawing
|
||||
//----------------------------------------------------------------------------------
|
||||
if (m_FunctionDropdown_EditMode)
|
||||
GuiLock();
|
||||
|
||||
GuiGroupBox({ anchor01.x + 0, anchor01.y + 8, 456, 304 }, "Run Sorting");
|
||||
{
|
||||
if (GuiTextBox({ anchor02.x + 8, anchor02.y + 8, 216, 24 }, m_FunctionTextBox_Text, 128, m_FunctionTextBox_EditMode)) m_FunctionTextBox_EditMode = !m_FunctionTextBox_EditMode;
|
||||
|
||||
|
||||
GuiGroupBox({ anchor02.x + 0, anchor02.y + 0, 232, 72 }, "Add & Check Function");
|
||||
{
|
||||
if (GuiButton({ anchor02.x + 72, anchor02.y + 40, 72, 24 }, "Check"))
|
||||
{
|
||||
// FATAL: asserts
|
||||
sol::optional<sol::protected_function> func = m_LuaState[m_FunctionTextBox_Text];
|
||||
if (!func)
|
||||
{
|
||||
m_ErrorWindow.error("Function does not exits", "A function was selected, that does not exist.");
|
||||
// TODO: formating works differently
|
||||
spdlog::error("BigSortComponent: Function does not exist %s", m_FunctionTextBox_Text);
|
||||
repack_function_list();
|
||||
}
|
||||
}
|
||||
|
||||
if (GuiButton({ anchor02.x + 152, anchor02.y + 40, 72, 24 }, "Add"))
|
||||
{
|
||||
// TODO: Check for validity
|
||||
add_function(m_FunctionTextBox_Text);
|
||||
}
|
||||
}
|
||||
|
||||
if (GuiButton({ anchor01.x + 8, anchor01.y + 48, 56, 24 }, "Run"))
|
||||
{
|
||||
// TODO: Run Test
|
||||
}
|
||||
|
||||
GuiLine({ anchor01.x + 8, anchor01.y + 96, 440, 12 }, nullptr);
|
||||
|
||||
// TODO: format infos into strings;
|
||||
GuiLabel({ anchor01.x + 8, anchor01.y + 176, 144, 24 }, "Is Sorted: <bool>");
|
||||
GuiLabel({ anchor01.x + 8, anchor01.y + 200, 144, 24 }, "Time elapsed: <double>: ");
|
||||
GuiGroupBox({ anchor03.x + 0, anchor03.y + 0, 288, 104 }, "Calls");
|
||||
GuiLabel({ anchor03.x + 8, anchor03.y + 8, 120, 24 }, "Swap: <size_t>");
|
||||
GuiLabel({ anchor03.x + 8, anchor03.y + 32, 120, 24 }, "Size: <size_t>");
|
||||
GuiLabel({ anchor03.x + 136, anchor03.y + 8, 120, 24 }, "Greater: <size_t>");
|
||||
GuiLabel({ anchor03.x + 136, anchor03.y + 32, 120, 24 }, "Lesser: <size_t>");
|
||||
GuiLabel({ anchor03.x + 136, anchor03.y + 56, 120, 24 }, "Equal: <size_t>");
|
||||
GuiLabel({ anchor01.x + 8, anchor01.y + 152, 144, 24 }, "Array size: <size_t>");
|
||||
GuiLabel({ anchor01.x + 8, anchor01.y + 112, 144, 24 }, "Tests ran: <size_t>");
|
||||
GuiLabel({ anchor01.x + 152, anchor01.y + 112, 144, 24 }, "Test number: <size_t>");
|
||||
|
||||
if (GuiButton({ anchor01.x + 112, anchor01.y + 264, 88, 24 }, "Next"))
|
||||
{
|
||||
// TODO: implement Test result stack movement
|
||||
}
|
||||
if (GuiButton({ anchor01.x + 8, anchor01.y + 264, 88, 24 }, "Previous"))
|
||||
{
|
||||
// TODO: Display previous result
|
||||
}
|
||||
|
||||
if (GuiButton({ anchor01.x + 320, anchor01.y + 264, 120, 24 }, "Clear All Test"))
|
||||
{
|
||||
m_SortResults.clear();
|
||||
}
|
||||
|
||||
if (GuiDropdownBox({ anchor01.x + 8, anchor01.y + 16, 184, 24 }, m_FunctionList.c_str(), &m_FunctionDropdown_Active, m_FunctionDropdown_EditMode)) m_FunctionDropdown_EditMode = !m_FunctionDropdown_EditMode;
|
||||
}
|
||||
GuiUnlock();
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
return m_ErrorWindow.draw();
|
||||
}
|
||||
|
||||
int BigSortComponent::input()
|
||||
{
|
||||
return m_ErrorWindow.input();
|
||||
}
|
||||
|
||||
void BigSortComponent::onAttach()
|
||||
{
|
||||
sva::Sorter::setup(m_LuaState);
|
||||
m_LuaState["list"] = m_Sorter;
|
||||
}
|
||||
|
||||
void BigSortComponent::run_test()
|
||||
{
|
||||
std::string function_name = m_FunctionNames[m_FunctionDropdown_Active];
|
||||
spdlog::debug("%s: Running sorting function: %s", function_name.c_str(), function_name.c_str());
|
||||
m_SortResults.push_back(m_Sorter.run(m_LuaState[function_name]));
|
||||
|
||||
if (!m_SortResults.back().is_sorted)
|
||||
{
|
||||
spdlog::debug("%s: Could not sort the array", function_name.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void BigSortComponent::add_function(const std::string& function_name)
|
||||
{
|
||||
m_FunctionNames.push_back(function_name);
|
||||
if (m_FunctionList.empty())
|
||||
{
|
||||
m_FunctionList = function_name;
|
||||
return;
|
||||
}
|
||||
m_FunctionList += ';' + function_name;
|
||||
}
|
||||
|
||||
void BigSortComponent::repack_function_list()
|
||||
{
|
||||
m_FunctionList.clear();
|
||||
for (const auto& fn : m_FunctionNames)
|
||||
{
|
||||
m_FunctionList += fn + ';';
|
||||
}
|
||||
m_FunctionList.pop_back();
|
||||
}
|
|
@ -1,48 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "../gui/GuiComponent.hpp"
|
||||
#include "../Sorter.hpp"
|
||||
#include <raylibs/raygui.h>
|
||||
#include <string>
|
||||
#include "../gui/CoreComponents.hpp"
|
||||
|
||||
class BigSortComponent : public sva::GuiComponent
|
||||
{
|
||||
Vector2 m_ComponentOffset = { 0,0 };
|
||||
|
||||
// BigSortComponent: controls initialization
|
||||
//----------------------------------------------------------------------------------
|
||||
Vector2 anchor01 = { 8, 8 };
|
||||
Vector2 anchor02 = { 224, 24 };
|
||||
Vector2 anchor03 = { 160, 152 };
|
||||
|
||||
bool m_FunctionDropdown_EditMode = false;
|
||||
int m_FunctionDropdown_Active = 0;
|
||||
|
||||
bool m_FunctionTextBox_EditMode = false;
|
||||
char m_FunctionTextBox_Text[256] = "Name own Function";
|
||||
|
||||
sva::ErrorWindow m_ErrorWindow;
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
public:
|
||||
BigSortComponent();
|
||||
|
||||
int draw() override;
|
||||
int input() override;
|
||||
void onAttach() override;
|
||||
|
||||
private:
|
||||
sol::state m_LuaState;
|
||||
|
||||
std::vector<std::string> m_FunctionNames;
|
||||
std::string m_FunctionList;
|
||||
|
||||
sva::Sorter m_Sorter;
|
||||
std::vector<sva::Sorter::SortResult> m_SortResults;
|
||||
sva::Sorter::SortResult* m_ActiveSortResult = nullptr;
|
||||
|
||||
void run_test();
|
||||
void add_function(const std::string&);
|
||||
void repack_function_list();
|
||||
};
|
|
@ -1,84 +0,0 @@
|
|||
#include "./SaveClosePopup.hpp"
|
||||
|
||||
SafeClosePopup::~SafeClosePopup()
|
||||
{
|
||||
CloseWindow();
|
||||
}
|
||||
|
||||
void SafeClosePopup::onAttach()
|
||||
{
|
||||
m_WindowOpen = false;
|
||||
}
|
||||
|
||||
int SafeClosePopup::draw()
|
||||
{
|
||||
if (WindowShouldClose())
|
||||
{
|
||||
if (m_WindowOpen) {
|
||||
CloseWindow();
|
||||
}
|
||||
else {
|
||||
OpenWindow();
|
||||
}
|
||||
onResize();
|
||||
}
|
||||
|
||||
if (m_WindowOpen)
|
||||
{
|
||||
GuiUnlock();
|
||||
anchor03 = { .x = m_WndRect.x + (168 * m_WndScalar), .y = m_WndRect.y + (88 * m_WndScalar) };
|
||||
|
||||
m_WindowOpen = !GuiWindowBox(m_WndRect, "#191# Are you sure you want to close this program?");
|
||||
{ // Drawing in different colours
|
||||
int border_color = GuiGetStyle(DEFAULT, BORDER_COLOR_NORMAL);
|
||||
int base_color = GuiGetStyle(DEFAULT, BASE_COLOR_NORMAL);
|
||||
|
||||
GuiSetStyle(DEFAULT, BORDER_COLOR_NORMAL, 0x7192C2FF);
|
||||
GuiSetStyle(DEFAULT, BASE_COLOR_NORMAL, 0xBBCDD3FF);
|
||||
|
||||
m_CQB_YesButton = GuiButton({ anchor03.x + (-152 * m_WndScalar), anchor03.y + (32 * m_WndScalar), 120 * m_WndScalar, 24 * m_WndScalar }, "#112#Yes");
|
||||
|
||||
GuiSetStyle(DEFAULT, BORDER_COLOR_NORMAL, border_color);
|
||||
GuiSetStyle(DEFAULT, BASE_COLOR_NORMAL, base_color);
|
||||
}
|
||||
m_CQB_NoButton = GuiButton({ anchor03.x + (24 * m_WndScalar), anchor03.y + (32 * m_WndScalar), 120 * m_WndScalar, 24 * m_WndScalar }, "#113#No");
|
||||
GuiLabel({ anchor03.x + (-104 * m_WndScalar), anchor03.y + (-40 * m_WndScalar), 208 * m_WndScalar, 24 * m_WndScalar }, "Are you sure you want to close this?");
|
||||
GuiLabel({ anchor03.x + (-56 * m_WndScalar), anchor03.y + (-8 * m_WndScalar), 120 * m_WndScalar, 24 * m_WndScalar }, "Press \"Yes\" to close");
|
||||
if (m_CQB_YesButton)
|
||||
{
|
||||
*m_WndRunning = false;
|
||||
return 1;
|
||||
}
|
||||
if (m_CQB_NoButton) CloseWindow();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SafeClosePopup::rinput(Vector2& mouse_position)
|
||||
{
|
||||
if (IsKeyReleased(KEY_ENTER)) {
|
||||
*m_WndRunning = false;
|
||||
return 1;
|
||||
}
|
||||
GuiLock();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void SafeClosePopup::onResize()
|
||||
{
|
||||
anchor03 = { static_cast<float>(m_WndWidth) / 2 , static_cast<float>(m_WndHeight) / 2 };
|
||||
m_WndRect = { anchor03.x + -168, anchor03.y + -88, 328, 160 };
|
||||
scale(m_WndScalar);
|
||||
}
|
||||
|
||||
void SafeClosePopup::OpenWindow()
|
||||
{
|
||||
GuiLock();
|
||||
m_WindowOpen = true;
|
||||
}
|
||||
|
||||
void SafeClosePopup::CloseWindow()
|
||||
{
|
||||
m_WindowOpen = false;
|
||||
GuiUnlock();
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "../gui/CoreComponents.hpp"
|
||||
|
||||
|
||||
|
||||
/****************************************************
|
||||
* A "Are you sure you want to exit?" Window.
|
||||
*
|
||||
* Yes is default
|
||||
****************************************************/
|
||||
class SafeClosePopup final : public sva::GuiMovableWindow
|
||||
{
|
||||
Vector2 anchor03 = { 0,0 };
|
||||
|
||||
bool m_CQB_YesButton = false;
|
||||
bool m_CQB_NoButton = false;
|
||||
|
||||
public:
|
||||
|
||||
~SafeClosePopup() override;
|
||||
|
||||
void onAttach() override;
|
||||
|
||||
int draw() override;
|
||||
|
||||
int rinput(Vector2& mouse_position) override;
|
||||
|
||||
void onResize() override;
|
||||
|
||||
public:
|
||||
void OpenWindow();
|
||||
|
||||
void CloseWindow();
|
||||
};
|
||||
|
118
src/Sorter.cpp
118
src/Sorter.cpp
|
@ -1,118 +0,0 @@
|
|||
#include "Sorter.hpp"
|
||||
|
||||
#include "Profiling/Timer.hpp"
|
||||
|
||||
#define BOOL_FMT "%s"
|
||||
#define BOOL_ARG(exp) (exp) ? "true" : "false"
|
||||
|
||||
namespace sva {
|
||||
Sorter::Sorter(size_t size) : m_SortArray(size)
|
||||
{
|
||||
populate(size);
|
||||
spdlog::debug("Sorter: created -- size: %lld, is-sorted: " BOOL_FMT, size, BOOL_ARG(is_sorted()));
|
||||
}
|
||||
|
||||
Sorter::SortResult Sorter::run(const sol::protected_function& sort_func)
|
||||
{
|
||||
SortResult res;
|
||||
timer_result tres;
|
||||
|
||||
if (m_ActiveSortResult) spdlog::error("Sorter: A Sort already running...");
|
||||
m_ActiveSortResult = &res;
|
||||
|
||||
Timer timer(tres, timer.paused);
|
||||
spdlog::debug("Sorter: running function");
|
||||
|
||||
timer.set_state(timer.running);
|
||||
|
||||
sol::function_result result = sort_func();
|
||||
|
||||
timer.set_state(timer.paused);
|
||||
|
||||
if (!result.valid())
|
||||
{
|
||||
spdlog::critical("Sol.Lua: Function result is invalid");
|
||||
}
|
||||
|
||||
if (m_ActiveSortResult) spdlog::error("Sorter: Something went wrong while running the test. There is no active result");
|
||||
m_ActiveSortResult = nullptr;
|
||||
return res;
|
||||
}
|
||||
|
||||
void Sorter::setup(sol::state& state)
|
||||
{
|
||||
state.open_libraries(sol::lib::coroutine, sol::lib::table);
|
||||
state.new_usertype<Sorter>("Sorter",
|
||||
"size", &Sorter::list_size,
|
||||
"swap", &Sorter::list_swap,
|
||||
"greater", &Sorter::list_greater,
|
||||
"less", &Sorter::list_less,
|
||||
"equal", &Sorter::list_equal
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
bool Sorter::list_greater(size_t a, size_t b) const
|
||||
{
|
||||
if (m_ActiveSortResult)
|
||||
m_ActiveSortResult->calls.nGreater++;
|
||||
return m_SortArray[a] > m_SortArray[b];
|
||||
}
|
||||
|
||||
bool Sorter::list_less(size_t a, size_t b) const
|
||||
{
|
||||
if (m_ActiveSortResult)
|
||||
m_ActiveSortResult->calls.nLesser++;
|
||||
return m_SortArray[a] < m_SortArray[b];
|
||||
}
|
||||
|
||||
bool Sorter::list_equal(size_t a, size_t b) const
|
||||
{
|
||||
if (m_ActiveSortResult)
|
||||
m_ActiveSortResult->calls.nEqual++;
|
||||
return m_SortArray[a] == m_SortArray[b];
|
||||
}
|
||||
|
||||
void Sorter::list_swap(size_t a, size_t b)
|
||||
{
|
||||
if (m_ActiveSortResult)
|
||||
m_ActiveSortResult->calls.nSwap++;
|
||||
// list[index1] ^= list[index2];
|
||||
// list[index2] ^= list[index1];
|
||||
// list[index1] ^= list[index2];
|
||||
auto tmp = m_SortArray[a];
|
||||
m_SortArray[a] = m_SortArray[b];
|
||||
m_SortArray[b] = tmp;
|
||||
}
|
||||
|
||||
size_t Sorter::list_size() const
|
||||
{
|
||||
if (m_ActiveSortResult)
|
||||
m_ActiveSortResult->calls.nSize++;
|
||||
return m_SortArray.size();
|
||||
}
|
||||
|
||||
bool Sorter::is_sorted() const
|
||||
{
|
||||
if (m_SortArray.size() <= 1)
|
||||
return true;
|
||||
for (size_t i = 1; i < m_SortArray.size(); i++)
|
||||
{
|
||||
if (m_SortArray[i - 1] > m_SortArray[i])
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Sorter::populate(size_t size)
|
||||
{
|
||||
std::random_device dev;
|
||||
std::mt19937_64 rng(dev());
|
||||
std::uniform_int_distribution<std::mt19937_64::result_type> dist(0, SIZE_MAX);
|
||||
|
||||
for (size_t i = 0; i < size; i++)
|
||||
{
|
||||
m_SortArray.at(i) = dist(rng);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,47 +0,0 @@
|
|||
#pragma once
|
||||
#include <random>
|
||||
|
||||
#include <sol/sol.hpp>
|
||||
#include <spdlog/spdlog.h>
|
||||
|
||||
namespace sva {
|
||||
class Sorter
|
||||
{
|
||||
public:
|
||||
struct SortResult
|
||||
{
|
||||
bool is_sorted;
|
||||
double elapsed_time;
|
||||
struct
|
||||
{
|
||||
size_t nSwap;
|
||||
size_t nSize;
|
||||
size_t nGreater;
|
||||
size_t nLesser;
|
||||
size_t nEqual;
|
||||
} calls;
|
||||
};
|
||||
|
||||
private:
|
||||
std::vector<size_t> m_SortArray;
|
||||
|
||||
SortResult* m_ActiveSortResult;
|
||||
public:
|
||||
Sorter(size_t size);
|
||||
|
||||
SortResult run(const sol::protected_function& sort_func);
|
||||
|
||||
static void setup(sol::state& state);
|
||||
|
||||
protected:
|
||||
void list_swap(size_t, size_t);
|
||||
bool list_greater(size_t, size_t) const;
|
||||
bool list_less(size_t, size_t) const;
|
||||
bool list_equal(size_t, size_t) const;
|
||||
size_t list_size() const;
|
||||
|
||||
bool is_sorted() const;
|
||||
|
||||
void populate(size_t);
|
||||
};
|
||||
}
|
|
@ -1,57 +0,0 @@
|
|||
#pragma once
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include "GuiComponent.hpp"
|
||||
|
||||
class ComponentStack final
|
||||
{
|
||||
inline static std::vector < std::shared_ptr<sva::GuiComponent> > s_Components;
|
||||
|
||||
public:
|
||||
inline static bool* s_WndRunning;
|
||||
inline static size_t s_WndWidth, s_WndHeight;
|
||||
inline static float s_WndScalar = 1.f;
|
||||
|
||||
|
||||
template<typename T, typename ...Args> requires std::is_base_of_v<sva::GuiComponent, T>
|
||||
static std::shared_ptr<T> push(Args&&... args)
|
||||
{
|
||||
std::shared_ptr<T> comp = std::make_shared<T>(std::forward<Args>(args)...);
|
||||
|
||||
s_Components.push_back(comp);
|
||||
comp->wndrsize(s_WndWidth, s_WndHeight);
|
||||
comp->attach(s_WndRunning);
|
||||
comp->scale(s_WndScalar);
|
||||
|
||||
return comp;
|
||||
}
|
||||
|
||||
static int run()
|
||||
{
|
||||
for (std::shared_ptr<sva::GuiComponent>& component : s_Components)
|
||||
{
|
||||
int r = component->input();
|
||||
if (r != 0) return r;
|
||||
r = component->draw();
|
||||
if (r != 0) return r;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void resize()
|
||||
{
|
||||
for (auto& comp : s_Components)
|
||||
{
|
||||
comp->wndrsize(s_WndWidth, s_WndHeight);
|
||||
}
|
||||
}
|
||||
|
||||
static void scale_all(float scalar)
|
||||
{
|
||||
s_WndScalar = scalar;
|
||||
for (const auto& comp : s_Components)
|
||||
{
|
||||
comp->scale(scalar);
|
||||
}
|
||||
}
|
||||
};
|
|
@ -1,98 +0,0 @@
|
|||
#include "./CoreComponents.hpp"
|
||||
|
||||
namespace sva {
|
||||
/*
|
||||
* GuiMovableWindow
|
||||
*/
|
||||
GuiMovableWindow::GuiMovableWindow() : m_WndRect({ 20,20, 200, 100 })
|
||||
{
|
||||
m_Title = "Example movable Window";
|
||||
}
|
||||
|
||||
int GuiMovableWindow::input()
|
||||
{
|
||||
if (!m_WindowOpen) return 0;
|
||||
Vector2 mouse_pos = GetMousePosition();
|
||||
|
||||
if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT) && !m_DragWindow)
|
||||
{
|
||||
if (CheckCollisionPointRec(mouse_pos, { m_WndRect.x, m_WndRect.y, m_WndRect.width - 24, 20 }))
|
||||
{
|
||||
m_DragWindow = true;
|
||||
m_PanOffset = { mouse_pos.x - m_WndRect.x, mouse_pos.y - m_WndRect.y };
|
||||
}
|
||||
}
|
||||
|
||||
if (m_DragWindow)
|
||||
{
|
||||
m_WndRect.x = (mouse_pos.x - m_PanOffset.x);
|
||||
m_WndRect.y = (mouse_pos.y - m_PanOffset.y);
|
||||
if (IsMouseButtonReleased(MOUSE_BUTTON_LEFT)) m_DragWindow = false;
|
||||
}
|
||||
return rinput(mouse_pos);
|
||||
}
|
||||
|
||||
int GuiMovableWindow::rinput(Vector2& mouse_position)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int GuiMovableWindow::rdraw()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int GuiMovableWindow::draw()
|
||||
{
|
||||
if (!m_WindowOpen) return 0;
|
||||
|
||||
m_WindowOpen = !GuiWindowBox(m_WndRect, m_Title.c_str());
|
||||
|
||||
return rdraw();
|
||||
}
|
||||
|
||||
void GuiMovableWindow::scale(float scale)
|
||||
{
|
||||
GuiComponent::scale(scale);
|
||||
m_WndRect.width *= scale;
|
||||
m_WndRect.height *= scale;
|
||||
}
|
||||
|
||||
/*
|
||||
* Error Window
|
||||
*/
|
||||
|
||||
void ErrorWindow::onAttach()
|
||||
{
|
||||
m_WindowOpen = false;
|
||||
}
|
||||
|
||||
int ErrorWindow::rdraw()
|
||||
{
|
||||
GuiLabel({ m_WndRect.x + m_TextAnchor.x, m_WndRect.y + m_TextAnchor.y, m_WndRect.width, m_WndRect.height }, m_Msg.c_str());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ErrorWindow::onResize()
|
||||
{
|
||||
m_WndRect.x = (static_cast<float>(m_WndWidth) - m_WndRect.width) / 2;
|
||||
m_WndRect.y = (static_cast<float>(m_WndHeight) - m_WndRect.height) / 2;
|
||||
}
|
||||
|
||||
void ErrorWindow::error(std::string title, std::string msg)
|
||||
{
|
||||
m_Msg = std::move(msg);
|
||||
float text_padding = 20;
|
||||
m_WndRect.width = static_cast<float>(MeasureText(m_Msg.c_str(), GuiGetStyle(DEFAULT, TEXT_SIZE))) + text_padding;
|
||||
m_WndRect.height = (m_WndRect.width * 2) / 3;
|
||||
|
||||
m_TextAnchor = {
|
||||
.x = text_padding / 2,
|
||||
.y = m_WndRect.height / 2 - static_cast<float>(GuiGetStyle(DEFAULT, TEXT_SIZE))
|
||||
};
|
||||
|
||||
m_WindowOpen = true;
|
||||
m_Title = std::move(title);
|
||||
}
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
#pragma once
|
||||
#include "GuiComponent.hpp"
|
||||
#include <raylibs/raygui.h>
|
||||
#include <string>
|
||||
|
||||
namespace sva {
|
||||
class GuiMovableWindow : public sva::GuiComponent
|
||||
{
|
||||
private:
|
||||
bool m_DragWindow = false;
|
||||
Vector2 m_PanOffset = { 0,0 };
|
||||
protected:
|
||||
Rectangle m_WndRect;
|
||||
bool m_WindowOpen = true;
|
||||
std::string m_Title;
|
||||
public:
|
||||
GuiMovableWindow();
|
||||
|
||||
virtual int input() override;
|
||||
|
||||
virtual int rinput(Vector2& mouse_position);
|
||||
virtual int rdraw();
|
||||
|
||||
virtual int draw() override;
|
||||
|
||||
virtual void scale(float scale) override;
|
||||
};
|
||||
|
||||
class ErrorWindow : public GuiMovableWindow
|
||||
{
|
||||
std::string m_Msg;
|
||||
Vector2 m_TextAnchor = { 0,0 };
|
||||
public:
|
||||
void onAttach() override;
|
||||
|
||||
int rdraw() override;
|
||||
|
||||
void onResize() override;
|
||||
|
||||
void error(std::string title, std::string msg);
|
||||
};
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
namespace sva {
|
||||
|
||||
class GuiComponent
|
||||
{
|
||||
public:
|
||||
void wndrsize(size_t width, size_t height) { m_WndWidth = width; m_WndHeight = height; onResize(); }
|
||||
virtual void onResize() {}
|
||||
virtual int draw() { if (!m_WndRunning) { return 1; } return 0; }
|
||||
virtual int input() { return 0; }
|
||||
|
||||
virtual ~GuiComponent() = default;
|
||||
|
||||
void attach(bool* wnd_running) { m_WndRunning = wnd_running; onAttach(); }
|
||||
virtual void onAttach() {}
|
||||
|
||||
virtual void scale(float scale) { m_WndScalar = scale; }
|
||||
|
||||
protected:
|
||||
bool* m_WndRunning = nullptr;
|
||||
size_t m_WndWidth = 0;
|
||||
size_t m_WndHeight = 0;
|
||||
float m_WndScalar = 1;
|
||||
};
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// StyleAsCode exporter v2.0 - Style data exported as a values array //
|
||||
// //
|
||||
// USAGE: On init call: GuiLoadStyleDark(); //
|
||||
// //
|
||||
// more info and bugs-report: github.com/raysan5/raygui //
|
||||
// feedback and support: ray[at]raylibtech.com //
|
||||
// //
|
||||
// Copyright (c) 2020-2023 raylib technologies (@raylibtech) //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define DARK_STYLE_PROPS_COUNT 8
|
||||
|
||||
// Custom style name: dark
|
||||
static const GuiStyleProp darkStyleProps[DARK_STYLE_PROPS_COUNT] = {
|
||||
{ 0, 0, 0x7b7b7bff }, // DEFAULT_BORDER_COLOR_NORMAL
|
||||
{ 0, 1, 0x595959ff }, // DEFAULT_BASE_COLOR_NORMAL
|
||||
{ 0, 2, 0xdededeff }, // DEFAULT_TEXT_COLOR_NORMAL
|
||||
{ 0, 9, 0x232323ff }, // DEFAULT_BORDER_COLOR_DISABLED
|
||||
{ 0, 10, 0x606060ff }, // DEFAULT_BASE_COLOR_DISABLED
|
||||
{ 0, 11, 0x9f9f9fff }, // DEFAULT_TEXT_COLOR_DISABLED
|
||||
{ 0, 18, 0x68cbd0ff }, // DEFAULT_LINE_COLOR
|
||||
{ 0, 19, 0x262626ff }, // DEFAULT_BACKGROUND_COLOR
|
||||
};
|
||||
|
||||
// Style loading function: dark
|
||||
static void GuiLoadStyleDark(void)
|
||||
{
|
||||
// Load style properties provided
|
||||
// NOTE: Default properties are propagated
|
||||
for (int i = 0; i < DARK_STYLE_PROPS_COUNT; i++)
|
||||
{
|
||||
GuiSetStyle(darkStyleProps[i].controlId, darkStyleProps[i].propertyId, darkStyleProps[i].propertyValue);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
|
||||
// TODO: Custom user style setup: Set specific properties here (if required)
|
||||
// i.e. Controls specific BORDER_WIDTH, TEXT_PADDING, TEXT_ALIGNMENT
|
||||
}
|
|
@ -1,61 +0,0 @@
|
|||
#include "safesol.h"
|
||||
|
||||
safesol::LuaResultType safesol::script(const std::string& script)
|
||||
{
|
||||
sol::load_result result = lua.load(script);
|
||||
if (!result.valid()) {
|
||||
sol::error err = result;
|
||||
std::cout << "Error loading script: " << err.what() << std::endl;
|
||||
return LuaResultType::LOAD_ERROR;
|
||||
}
|
||||
|
||||
sol::protected_function_result script_result = result();
|
||||
|
||||
if (!script_result.valid()) {
|
||||
sol::error err = script_result;
|
||||
std::cout << "Error running script: " << err.what() << std::endl;
|
||||
return LuaResultType::SCRIPT_ERROR;
|
||||
}
|
||||
|
||||
return LuaResultType::SUCCESS;
|
||||
}
|
||||
|
||||
safesol::LuaResultType safesol::script(const char* script)
|
||||
{
|
||||
sol::load_result result = lua.load(script);
|
||||
if (!result.valid()) {
|
||||
sol::error err = result;
|
||||
std::cout << "Error loading script: " << err.what() << std::endl;
|
||||
return LuaResultType::LOAD_ERROR;
|
||||
}
|
||||
|
||||
sol::protected_function_result script_result = result();
|
||||
|
||||
if (!script_result.valid()) {
|
||||
sol::error err = script_result;
|
||||
std::cout << "Error running script: " << err.what() << std::endl;
|
||||
return LuaResultType::SCRIPT_ERROR;
|
||||
}
|
||||
|
||||
return LuaResultType::SUCCESS;
|
||||
}
|
||||
|
||||
safesol::LuaResultType safesol::load(const std::string& file)
|
||||
{
|
||||
sol::load_result result = lua.load_file(file);
|
||||
if (!result.valid()) {
|
||||
sol::error err = result;
|
||||
std::cout << "Error loading file: " << err.what() << std::endl;
|
||||
return LuaResultType::LOAD_ERROR;
|
||||
}
|
||||
|
||||
sol::protected_function_result script_result = result();
|
||||
|
||||
if (!script_result.valid()) {
|
||||
sol::error err = script_result;
|
||||
std::cout << "Error running script: " << err.what() << std::endl;
|
||||
return LuaResultType::SCRIPT_ERROR;
|
||||
}
|
||||
|
||||
return LuaResultType::SUCCESS;
|
||||
}
|
|
@ -1,59 +0,0 @@
|
|||
#pragma once
|
||||
#include <std.hpp>
|
||||
#include <sol/sol.hpp>
|
||||
|
||||
class safesol
|
||||
{
|
||||
public:
|
||||
enum class LuaResultType : u8
|
||||
{
|
||||
SUCCESS = 0,
|
||||
LOAD_ERROR = 1,
|
||||
SCRIPT_ERROR,
|
||||
RUN_ERROR,
|
||||
UNKNOWN_ERROR
|
||||
};
|
||||
|
||||
sol::state lua;
|
||||
|
||||
|
||||
LuaResultType script(const std::string& script);
|
||||
LuaResultType script(const char* script);
|
||||
|
||||
LuaResultType load(const std::string& file);
|
||||
|
||||
template<typename ...Args>
|
||||
sol::protected_function_result default_caller(const sol::protected_function& function, Args&&... args)
|
||||
{
|
||||
return function(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template<typename ...Args>
|
||||
LuaResultType run(const std::string& function_name, Args&&... args)
|
||||
{
|
||||
return run_on_caller(function_name, default_caller, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template<typename ...Args, typename Caller = std::function<sol::protected_function_result(const sol::protected_function&, Args&&...)>>
|
||||
LuaResultType run_on_caller(const std::string& function_name, const Caller& caller, Args&&... args)
|
||||
{
|
||||
std::cout << "Looking for function: " << function_name << std::endl;
|
||||
|
||||
auto function = lua[function_name];
|
||||
if (!function.valid()) {
|
||||
std::cout << "Error: function " << function_name << " not found" << std::endl;
|
||||
return LuaResultType::RUN_ERROR;
|
||||
}
|
||||
|
||||
std::cout << "Found function, attempting to run" << std::endl;
|
||||
|
||||
auto result = caller(function, std::forward<Args>(args)...);
|
||||
if (!result.valid()) {
|
||||
sol::error err = result;
|
||||
std::cout << "Error running function " << function_name << ": " << err.what() << std::endl;
|
||||
return LuaResultType::RUN_ERROR;
|
||||
}
|
||||
|
||||
return LuaResultType::SUCCESS;
|
||||
}
|
||||
};
|
176
src/main.cpp
176
src/main.cpp
|
@ -1,176 +1,12 @@
|
|||
/**************************************************************
|
||||
* Sortiva - Sorting Visualisation Tool
|
||||
*
|
||||
* This project falls under the MIT Licence.
|
||||
* But I would find it very nice of you,
|
||||
* if you could add my name and the project
|
||||
* to some kind of credits.
|
||||
* Thank you.
|
||||
*
|
||||
* Kind regards,
|
||||
* Jann Hoffmann.
|
||||
*
|
||||
* Signature: "Darling, I'm Home!" - Jann Hoffmann
|
||||
**************************************************************/
|
||||
|
||||
#include <iostream>
|
||||
|
||||
|
||||
/* raylib includes */
|
||||
#include <raylib.h>
|
||||
#include <sol/debug.hpp>
|
||||
|
||||
#include "gui/ComponentStack.hpp"
|
||||
|
||||
// gui components
|
||||
#include "Components/SaveClosePopup.hpp"
|
||||
#include "Components/BigSortComponent.hpp"
|
||||
|
||||
#include <spdlog/spdlog.h>
|
||||
|
||||
constexpr int window_width = 800;
|
||||
constexpr int window_height = 650;
|
||||
constexpr char window_title[] = "Sortiva";
|
||||
|
||||
|
||||
enum class logerr_level
|
||||
{
|
||||
Debug = 0,
|
||||
Window,
|
||||
SVA,
|
||||
};
|
||||
|
||||
struct AppArgsConfig {
|
||||
// every value has to have a default assigned at init.
|
||||
float scalar = 1;
|
||||
const char* path; // this is an exception as it can not, not be passed
|
||||
};
|
||||
|
||||
AppArgsConfig sva_parse_args(int argc, char** argv);
|
||||
|
||||
#include <stdio.h>
|
||||
#include "sortiva.hpp"
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
spdlog::set_level(spdlog::level::debug);
|
||||
#endif
|
||||
spdlog::set_pattern("\n\t%^%v%$\n");
|
||||
spdlog::debug("Darling, I'm Home");
|
||||
spdlog::set_pattern("[%T %z] [%^%l%$] [thread %t] %v");
|
||||
printf("Darling, I'm Home!\n");
|
||||
|
||||
Sortiva app;
|
||||
app.run();
|
||||
|
||||
/*
|
||||
* Parsing args...
|
||||
*/
|
||||
|
||||
AppArgsConfig acnf = sva_parse_args(argc, argv);
|
||||
|
||||
|
||||
/* Window and rendering */
|
||||
|
||||
InitWindow(window_width, window_height, window_title);
|
||||
|
||||
if (!IsWindowReady())
|
||||
{
|
||||
spdlog::critical("Window could not be created...");
|
||||
return 0;
|
||||
}
|
||||
|
||||
ClearWindowState(ConfigFlags::FLAG_WINDOW_TRANSPARENT);
|
||||
SetWindowState(ConfigFlags::FLAG_WINDOW_ALWAYS_RUN);
|
||||
SetWindowState(ConfigFlags::FLAG_WINDOW_RESIZABLE);
|
||||
|
||||
SetWindowFocused();
|
||||
|
||||
spdlog::debug("Window created successfully.");
|
||||
|
||||
int font_size = static_cast<int>(static_cast<float>(GuiGetStyle(DEFAULT, TEXT_SIZE)) * acnf.scalar);
|
||||
GuiSetStyle(DEFAULT, TEXT_SIZE, font_size);
|
||||
spdlog::debug("New Text size is: %d", font_size);
|
||||
|
||||
bool is_running = true;
|
||||
ComponentStack::s_WndRunning = &is_running;
|
||||
|
||||
ComponentStack::s_WndWidth = GetRenderWidth();
|
||||
ComponentStack::s_WndHeight = GetRenderHeight();
|
||||
|
||||
int run_result = 0;
|
||||
|
||||
ComponentStack::push<BigSortComponent>();
|
||||
ComponentStack::scale_all(acnf.scalar);
|
||||
|
||||
// always on top...
|
||||
SafeClosePopup safe_close_popup;
|
||||
safe_close_popup.attach(&is_running);
|
||||
safe_close_popup.wndrsize(ComponentStack::s_WndWidth, ComponentStack::s_WndHeight);
|
||||
safe_close_popup.scale(acnf.scalar);
|
||||
|
||||
|
||||
while (is_running) {
|
||||
|
||||
if (IsWindowResized())
|
||||
{
|
||||
ComponentStack::s_WndWidth = GetRenderWidth();
|
||||
ComponentStack::s_WndHeight = GetRenderHeight();
|
||||
|
||||
safe_close_popup.wndrsize(ComponentStack::s_WndWidth, ComponentStack::s_WndHeight);
|
||||
ComponentStack::resize();
|
||||
}
|
||||
|
||||
BeginDrawing();
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
run_result = safe_close_popup.input();
|
||||
if (run_result != 0) break;
|
||||
|
||||
run_result = ComponentStack::run();
|
||||
if (run_result != 0) break;
|
||||
|
||||
run_result = safe_close_popup.draw();
|
||||
if (run_result != 0) break;
|
||||
|
||||
EndDrawing();
|
||||
}
|
||||
|
||||
|
||||
CloseWindow();
|
||||
|
||||
switch (run_result)
|
||||
{
|
||||
case 1:
|
||||
return 0;
|
||||
case 2:
|
||||
spdlog::warn("Program exiting abnormally.");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return run_result;
|
||||
}
|
||||
|
||||
AppArgsConfig sva_parse_args(int argc, char** argv)
|
||||
{
|
||||
// created with defaults
|
||||
AppArgsConfig config;
|
||||
|
||||
printf("argc: %d\n", argc);
|
||||
|
||||
config.path = argv[0];
|
||||
|
||||
if (argc > 1)
|
||||
{
|
||||
if (!strcmp(argv[1], "--scale"))
|
||||
{
|
||||
spdlog::warn("The Scale mode is not fully supported");
|
||||
if (argc < 3)
|
||||
{
|
||||
spdlog::error("No argument passed to --scale option");
|
||||
exit(1);
|
||||
}
|
||||
config.scalar = std::stof(argv[2]);
|
||||
}
|
||||
}
|
||||
|
||||
return config;
|
||||
return 0;
|
||||
}
|
196
src/sortiva.cpp
Normal file
196
src/sortiva.cpp
Normal file
|
@ -0,0 +1,196 @@
|
|||
#include "sortiva.hpp"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <stdio.h>
|
||||
|
||||
#define RL_COLOR(COLOR) rl::##COLOR
|
||||
|
||||
namespace rl {
|
||||
#include <raylib.h>
|
||||
}
|
||||
|
||||
Sortiva::Sortiva()
|
||||
{
|
||||
rl::InitWindow(1280, 720, "Sortiva");
|
||||
if (!rl::IsWindowReady())
|
||||
{
|
||||
printf("Window could not be initialized\n");
|
||||
exit(-1);
|
||||
}
|
||||
rl::SetWindowState(rl::FLAG_WINDOW_RESIZABLE | rl::FLAG_WINDOW_TRANSPARENT);
|
||||
|
||||
m_Width = rl::GetScreenWidth();
|
||||
m_Height = rl::GetScreenHeight();
|
||||
|
||||
rl::SetTargetFPS(60);
|
||||
}
|
||||
|
||||
Sortiva::~Sortiva()
|
||||
{
|
||||
rl::CloseWindow();
|
||||
}
|
||||
|
||||
void Sortiva::run()
|
||||
{
|
||||
setup();
|
||||
while (m_Running)
|
||||
{
|
||||
if (rl::WindowShouldClose()) m_Running = false;
|
||||
if (rl::IsWindowResized())
|
||||
{
|
||||
m_Width = rl::GetScreenWidth();
|
||||
m_Height = rl::GetScreenHeight();
|
||||
}
|
||||
|
||||
rl::ClearBackground({ 25, 25, 25, 255 });
|
||||
rl::BeginDrawing();
|
||||
|
||||
draw();
|
||||
|
||||
rl::EndDrawing();
|
||||
}
|
||||
}
|
||||
|
||||
constexpr rl::Color sorter_colors[] = {
|
||||
{ 253, 249, 0, 255 }, // Yellow
|
||||
{ 255, 203, 0, 255 }, // Gold
|
||||
{ 255, 161, 0, 255 }, // Orange
|
||||
{ 255, 109, 194, 255 }, // Pink
|
||||
{ 230, 41, 55, 255 }, // Red
|
||||
{ 190, 33, 55, 255 }, // Maroon
|
||||
{ 0, 228, 48, 255 }, // Green
|
||||
{ 0, 158, 47, 255 }, // Lime
|
||||
{ 0, 117, 44, 255 }, // Dark Green
|
||||
{ 102, 191, 255, 255 }, // Sky Blue
|
||||
{ 0, 121, 241, 255 }, // Blue
|
||||
{ 0, 82, 172, 255 }, // Dark Blue
|
||||
{ 255, 0, 255, 255 }, // Magenta
|
||||
{ 200, 122, 255, 255 }, // Purple
|
||||
{ 135, 60, 190, 255 }, // Violet
|
||||
{ 112, 31, 126, 255 }, // Dark Purple
|
||||
{ 211, 176, 131, 255 }, // Beige
|
||||
{ 127, 106, 79, 255 }, // Brown
|
||||
{ 76, 63, 47, 255 }, // Dark Brown
|
||||
};
|
||||
|
||||
constexpr int sorter_colors_size = sizeof(sorter_colors) / sizeof(rl::Color);
|
||||
|
||||
constexpr rl::Color sorter_block_colors[] = {
|
||||
{ 200, 200, 200, 255 }, // Light Gray
|
||||
{ 80, 80, 80, 255 }, // Dark Gray
|
||||
};
|
||||
|
||||
constexpr int sorter_block_colors_size = sizeof(sorter_block_colors) / sizeof(rl::Color);
|
||||
|
||||
void Sortiva::draw()
|
||||
{
|
||||
float margin = static_cast<float>(m_Width) / m_Height * 10;
|
||||
rl::DrawRectangle(1 + margin, 1 + margin, m_Width - 2 * margin, m_Height - 2 * margin, { 60,60,60,255 });
|
||||
|
||||
margin = static_cast<float>(m_Width) / m_Height * 20;
|
||||
|
||||
|
||||
int steps = (m_Steps.size() / m_Values) + 2;
|
||||
|
||||
float hoffset = (static_cast<float>(m_Height) - margin * 2) / static_cast<float>(m_Values);
|
||||
float woffset = (static_cast<float>(m_Width) - margin * 2) / static_cast<float>(steps);
|
||||
|
||||
for (int i = 0; i < steps; ++i)
|
||||
{
|
||||
rl::DrawRectangle(
|
||||
margin + (woffset * static_cast<float>(i)),
|
||||
margin,
|
||||
woffset,
|
||||
m_Height - 2 * margin,
|
||||
sorter_block_colors[i % sorter_block_colors_size]
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
steps = m_Steps.size() / m_Values;
|
||||
|
||||
// colors to values - ratio ; adds high variance to the color selection
|
||||
int colid = sorter_colors_size / m_Values;
|
||||
|
||||
// font settings
|
||||
constexpr rl::Color textColor = RL_COLOR(BLACK);
|
||||
int fsize = margin;
|
||||
|
||||
for (int i = 0; i < m_Values; ++i)
|
||||
{
|
||||
float hp = hoffset * (i + .5f);
|
||||
rl::Vector2 pos = { margin * 3.f, hp };
|
||||
rl::Color col = sorter_colors[(m_Steps[i] * colid) % sorter_colors_size];
|
||||
|
||||
rl::DrawRing(pos, margin / 4, margin / 2, 20.f, 340.f, 10, col);
|
||||
|
||||
rl::DrawLineEx(
|
||||
pos,
|
||||
{ woffset + margin, hp },
|
||||
margin / 4,
|
||||
col
|
||||
);
|
||||
|
||||
rl::DrawText(
|
||||
rl::TextFormat("%d", m_Steps[i]),
|
||||
pos.x - 20 - fsize / 2,
|
||||
pos.y - fsize / 2,
|
||||
fsize,
|
||||
textColor
|
||||
);
|
||||
}
|
||||
|
||||
for (int i = 0; i < m_Values; ++i)
|
||||
{
|
||||
float hp = hoffset * (i + .5f);
|
||||
for (int s = 0; s < steps; ++s) {
|
||||
rl::DrawLineEx(
|
||||
{ woffset * (s + 1) + margin, hp },
|
||||
{ woffset * (s + 2) + margin, hp },
|
||||
margin / 4,
|
||||
// calculating the 1d position; multiplies the colors/values ratio
|
||||
sorter_colors[(m_Steps[(m_Values * s) + i] * colid) % sorter_colors_size]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < m_Values; ++i)
|
||||
{
|
||||
float hp = hoffset * (i + .5f);
|
||||
rl::Vector2 pos = { woffset * (steps + 2) - margin, hp };
|
||||
rl::Color col = sorter_colors[(m_Steps[m_Values * (steps - 1) + i] * colid) % sorter_colors_size];
|
||||
|
||||
rl::DrawCircleV(pos, margin / 2, col);
|
||||
|
||||
rl::DrawLineEx(
|
||||
{ woffset * (steps + 1) + margin, hp },
|
||||
pos,
|
||||
margin / 4,
|
||||
col
|
||||
);
|
||||
|
||||
rl::DrawText(
|
||||
rl::TextFormat("%d", m_Steps[m_Values * (steps - 1) + i]),
|
||||
pos.x + margin / 2 + fsize / 2,
|
||||
pos.y - fsize / 2,
|
||||
fsize,
|
||||
textColor
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Sortiva::setup()
|
||||
{
|
||||
m_Steps.clear();
|
||||
|
||||
m_Steps = {
|
||||
2,1,3,
|
||||
1,2,3,
|
||||
3,1,2,
|
||||
1,2,3,
|
||||
};
|
||||
|
||||
}
|
28
src/sortiva.hpp
Normal file
28
src/sortiva.hpp
Normal file
|
@ -0,0 +1,28 @@
|
|||
#pragma once
|
||||
#include <vector>
|
||||
|
||||
|
||||
class Sortiva final
|
||||
{
|
||||
public:
|
||||
Sortiva();
|
||||
~Sortiva();
|
||||
|
||||
void run();
|
||||
private:
|
||||
int m_Width;
|
||||
int m_Height;
|
||||
bool m_Running;
|
||||
|
||||
/*
|
||||
* Draw Functions
|
||||
*/
|
||||
void draw();
|
||||
|
||||
|
||||
void setup();
|
||||
|
||||
int m_Values = 3;
|
||||
|
||||
std::vector<uint16_t> m_Steps;
|
||||
};
|
Loading…
Reference in a new issue