restarted because i cant do it

visualising sorting through value/step diagrams
This commit is contained in:
noffie 2025-01-07 22:38:06 +01:00
parent f02f77d5df
commit 90ac688f3d
18 changed files with 231 additions and 1142 deletions

View file

@ -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"

View file

@ -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();
}
};

View file

@ -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();
}

View file

@ -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();
};

View file

@ -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();
}

View file

@ -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();
};

View file

@ -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);
}
}
}

View file

@ -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);
};
}

View file

@ -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);
}
}
};

View file

@ -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);
}
}

View file

@ -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);
};
}

View file

@ -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;
};
}

View file

@ -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
}

View file

@ -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;
}

View file

@ -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;
}
};

View file

@ -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
View 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
View 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;
};