SDRPlusPlus/core/src/core.cpp

445 wiersze
16 KiB
C++
Czysty Zwykły widok Historia

2020-09-19 10:48:34 +00:00
#include "imgui.h"
#include "imgui_impl_glfw.h"
#include "imgui_impl_opengl3.h"
#include <stdio.h>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
2020-09-19 22:19:39 +00:00
#include <gui/main_window.h>
#include <gui/style.h>
2020-11-30 20:17:36 +00:00
#include <gui/gui.h>
2020-09-19 22:19:39 +00:00
#include <gui/icons.h>
2020-09-19 10:48:34 +00:00
#include <version.h>
#include <spdlog/spdlog.h>
#include <gui/widgets/bandplan.h>
2020-09-19 10:48:34 +00:00
#include <stb_image.h>
#include <config.h>
2020-09-24 17:36:57 +00:00
#include <core.h>
2021-04-23 17:12:24 +00:00
#include <glfw_window.h>
2020-12-22 13:50:26 +00:00
#include <options.h>
2020-10-07 12:44:39 +00:00
#include <duktape/duktape.h>
#include <duktape/duk_console.h>
2020-12-22 23:11:12 +00:00
#include <filesystem>
2021-06-23 19:45:38 +00:00
#include <gui/menus/theme.h>
2020-09-19 10:48:34 +00:00
#define STB_IMAGE_RESIZE_IMPLEMENTATION
#include <stb_image_resize.h>
#include <gui/gui.h>
#include <signal_path/signal_path.h>
2020-09-19 10:48:34 +00:00
#ifdef _WIN32
#include <Windows.h>
#endif
2021-02-11 21:49:33 +00:00
#ifndef INSTALL_PREFIX
#ifdef __APPLE__
#define INSTALL_PREFIX "/usr/local"
#else
#define INSTALL_PREFIX "/usr"
#endif
2021-02-11 21:49:33 +00:00
#endif
2020-09-24 17:36:57 +00:00
namespace core {
ConfigManager configManager;
2020-10-07 12:44:39 +00:00
ScriptManager scriptManager;
2020-12-08 03:36:37 +00:00
ModuleManager moduleManager;
ModuleComManager modComManager;
2021-04-23 17:12:24 +00:00
GLFWwindow* window;
2020-10-01 23:44:18 +00:00
void setInputSampleRate(double samplerate) {
// NOTE: Zoom controls won't work
spdlog::info("New DSP samplerate: {0}", samplerate);
2020-10-01 23:44:18 +00:00
gui::waterfall.setBandwidth(samplerate);
2020-12-14 17:14:04 +00:00
gui::waterfall.setViewOffset(0);
gui::waterfall.setViewBandwidth(samplerate);
2020-10-01 23:44:18 +00:00
sigpath::signalPath.setSampleRate(samplerate);
2021-06-20 19:17:11 +00:00
gui::mainWindow.setViewBandwidthSlider(samplerate);
2020-10-01 23:44:18 +00:00
}
2020-09-24 17:36:57 +00:00
};
2020-09-19 10:48:34 +00:00
bool maximized = false;
bool fullScreen = false;
static void glfw_error_callback(int error, const char* description) {
spdlog::error("Glfw Error {0}: {1}", error, description);
}
static void maximized_callback(GLFWwindow* window, int n) {
if (n == GLFW_TRUE) {
maximized = true;
}
else {
maximized = false;
}
}
2020-10-07 12:44:39 +00:00
duk_ret_t test_func(duk_context *ctx) {
printf("Hello from C++\n");
return 1;
}
2020-09-19 10:48:34 +00:00
// main
2020-12-22 13:50:26 +00:00
int sdrpp_main(int argc, char *argv[]) {
2020-09-19 10:48:34 +00:00
spdlog::info("SDR++ v" VERSION_STR);
2020-12-22 13:50:26 +00:00
// Load default options and parse command line
options::loadDefaults();
if (!options::parse(argc, argv)) { return -1; }
2021-02-06 20:28:27 +00:00
#ifdef _WIN32
if (!options::opts.showConsole) { FreeConsole(); }
#endif
2020-12-22 23:11:12 +00:00
// Check root directory
if (!std::filesystem::exists(options::opts.root)) {
spdlog::warn("Root directory {0} does not exist, creating it", options::opts.root);
if (!std::filesystem::create_directory(options::opts.root)) {
spdlog::error("Could not create root directory {0}", options::opts.root);
return -1;
}
}
if (!std::filesystem::is_directory(options::opts.root)) {
spdlog::error("{0} is not a directory", options::opts.root);
return -1;
}
2020-12-10 04:18:40 +00:00
// ======== DEFAULT CONFIG ========
json defConfig;
defConfig["bandColors"]["amateur"] = "#FF0000FF";
defConfig["bandColors"]["aviation"] = "#00FF00FF";
defConfig["bandColors"]["broadcast"] = "#0000FFFF";
defConfig["bandColors"]["marine"] = "#00FFFFFF";
defConfig["bandColors"]["military"] = "#FFFF00FF";
defConfig["bandPlan"] = "General";
defConfig["bandPlanEnabled"] = true;
2021-04-13 23:45:21 +00:00
defConfig["bandPlanPos"] = 0;
defConfig["centerTuning"] = false;
defConfig["colorMap"] = "Classic";
2021-04-13 02:57:42 +00:00
defConfig["fastFFT"] = false;
2020-12-10 04:18:40 +00:00
defConfig["fftHeight"] = 300;
2021-04-13 16:31:38 +00:00
defConfig["fftSize"] = 65536;
defConfig["fftWindow"] = 1;
2020-12-10 04:18:40 +00:00
defConfig["frequency"] = 100000000.0;
2021-04-13 02:57:42 +00:00
defConfig["fullWaterfallUpdate"] = false;
2020-12-10 04:18:40 +00:00
defConfig["max"] = 0.0;
defConfig["maximized"] = false;
2021-04-22 21:49:35 +00:00
// Menu
defConfig["menuElements"] = json::array();
defConfig["menuElements"][0]["name"] = "Source";
defConfig["menuElements"][0]["open"] = true;
defConfig["menuElements"][1]["name"] = "Radio";
defConfig["menuElements"][1]["open"] = true;
defConfig["menuElements"][2]["name"] = "Recorder";
defConfig["menuElements"][2]["open"] = true;
defConfig["menuElements"][3]["name"] = "Sinks";
defConfig["menuElements"][3]["open"] = true;
2021-07-03 17:46:21 +00:00
defConfig["menuElements"][3]["name"] = "Frequency Manager";
defConfig["menuElements"][3]["open"] = true;
2021-05-04 19:05:45 +00:00
defConfig["menuElements"][4]["name"] = "VFO Color";
defConfig["menuElements"][4]["open"] = true;
2021-04-22 21:49:35 +00:00
2021-05-04 19:05:45 +00:00
defConfig["menuElements"][5]["name"] = "Scripting";
defConfig["menuElements"][5]["open"] = false;
2021-04-22 21:49:35 +00:00
2021-05-04 19:05:45 +00:00
defConfig["menuElements"][6]["name"] = "Band Plan";
2021-04-22 21:49:35 +00:00
defConfig["menuElements"][6]["open"] = true;
2021-05-04 19:05:45 +00:00
defConfig["menuElements"][7]["name"] = "Display";
defConfig["menuElements"][7]["open"] = true;
2020-12-10 04:18:40 +00:00
defConfig["menuWidth"] = 300;
2021-02-28 16:32:22 +00:00
defConfig["min"] = -120.0;
2020-12-22 23:11:12 +00:00
2021-04-23 01:58:10 +00:00
// Module instances
2021-06-28 00:22:51 +00:00
defConfig["moduleInstances"]["Airspy Source"] = "airspy_source";
defConfig["moduleInstances"]["AirspyHF+ Source"] = "airspyhf_source";
2021-06-27 00:20:11 +00:00
defConfig["moduleInstances"]["BladeRF Source"] = "bladerf_source";
2021-06-28 00:22:51 +00:00
defConfig["moduleInstances"]["File Source"] = "file_source";
2021-04-13 16:35:31 +00:00
defConfig["moduleInstances"]["HackRF Source"] = "hackrf_source";
2021-06-28 00:22:51 +00:00
defConfig["moduleInstances"]["LimeSDR Source"] = "limesdr_source";
2021-02-13 21:48:42 +00:00
defConfig["moduleInstances"]["RTL-SDR Source"] = "rtl_sdr_source";
2021-06-28 00:22:51 +00:00
defConfig["moduleInstances"]["RTL-TCP Source"] = "rtl_tcp_source";
2021-03-30 01:37:40 +00:00
defConfig["moduleInstances"]["SDRplay Source"] = "sdrplay_source";
2021-06-28 00:22:51 +00:00
defConfig["moduleInstances"]["SoapySDR Source"] = "soapy_source";
defConfig["moduleInstances"]["PlutoSDR Source"] = "plutosdr_source";
2020-12-24 13:43:14 +00:00
defConfig["moduleInstances"]["Audio Sink"] = "audio_sink";
2020-12-22 23:11:12 +00:00
2021-06-28 00:22:51 +00:00
defConfig["moduleInstances"]["Radio"] = "radio";
2021-07-03 17:46:21 +00:00
defConfig["moduleInstances"]["Frequency Manager"] = "frequency_manager";
2021-06-28 00:22:51 +00:00
defConfig["moduleInstances"]["Recorder"] = "recorder";
2021-06-23 19:45:38 +00:00
// Themes
defConfig["theme"] = "Dark";
2020-12-10 04:18:40 +00:00
defConfig["modules"] = json::array();
defConfig["offset"] = 0.0;
2021-04-23 01:58:10 +00:00
defConfig["showMenu"] = true;
2020-12-10 04:18:40 +00:00
defConfig["showWaterfall"] = true;
defConfig["source"] = "";
2021-05-05 02:31:37 +00:00
defConfig["streams"]["Radio"]["muted"] = false;
defConfig["streams"]["Radio"]["sink"] = "Audio";
defConfig["streams"]["Radio"]["volume"] = 1.0f;
2020-12-10 04:18:40 +00:00
defConfig["windowSize"]["h"] = 720;
defConfig["windowSize"]["w"] = 1280;
defConfig["vfoOffsets"] = json::object();
2021-05-04 18:41:23 +00:00
defConfig["vfoColors"]["Radio"] = "#FFFFFF";
2020-12-22 21:39:24 +00:00
#ifdef _WIN32
defConfig["modulesDirectory"] = "./modules";
defConfig["resourcesDirectory"] = "./res";
#else
2021-02-11 22:10:01 +00:00
defConfig["modulesDirectory"] = INSTALL_PREFIX "/lib/sdrpp/plugins";
defConfig["resourcesDirectory"] = INSTALL_PREFIX "/share/sdrpp";
2020-12-22 21:39:24 +00:00
#endif
2020-09-19 10:48:34 +00:00
// Load config
2020-12-22 17:42:30 +00:00
spdlog::info("Loading config");
2020-12-22 13:50:26 +00:00
core::configManager.setPath(options::opts.root + "/config.json");
2020-12-10 04:18:40 +00:00
core::configManager.load(defConfig);
2020-09-24 17:36:57 +00:00
core::configManager.enableAutoSave();
2020-09-19 10:48:34 +00:00
2021-04-22 21:49:35 +00:00
core::configManager.aquire();
2021-04-22 21:49:35 +00:00
// Fix missing elements in config
for (auto const& item : defConfig.items()) {
if (!core::configManager.conf.contains(item.key())) {
2021-05-04 18:41:23 +00:00
spdlog::info("Missing key in config {0}, repairing", item.key());
core::configManager.conf[item.key()] = defConfig[item.key()];
}
}
2021-04-22 21:49:35 +00:00
// Remove unused elements
auto items = core::configManager.conf.items();
for (auto const& item : items) {
if (!defConfig.contains(item.key())) {
2021-05-04 18:41:23 +00:00
spdlog::info("Unused key in config {0}, repairing", item.key());
2021-04-22 21:49:35 +00:00
core::configManager.conf.erase(item.key());
}
}
2021-04-23 01:58:10 +00:00
core::configManager.release(true);
2020-09-19 10:48:34 +00:00
// Setup window
glfwSetErrorCallback(glfw_error_callback);
if (!glfwInit()) {
return 1;
}
2020-12-24 22:38:45 +00:00
#ifdef __APPLE__
// GL 3.2 + GLSL 150
const char* glsl_version = "#version 150";
2020-09-19 10:48:34 +00:00
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // 3.2+ only
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // Required on Mac
2020-12-24 22:38:45 +00:00
#else
// GL 3.0 + GLSL 120
const char* glsl_version = "#version 120";
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
#endif
2020-09-19 10:48:34 +00:00
2020-09-24 17:36:57 +00:00
core::configManager.aquire();
int winWidth = core::configManager.conf["windowSize"]["w"];
int winHeight = core::configManager.conf["windowSize"]["h"];
maximized = core::configManager.conf["maximized"];
2020-12-22 21:39:24 +00:00
std::string resDir = core::configManager.conf["resourcesDirectory"];
2020-12-22 23:11:12 +00:00
json bandColors = core::configManager.conf["bandColors"];
2020-09-24 17:36:57 +00:00
core::configManager.release();
2020-09-19 10:48:34 +00:00
if (!std::filesystem::is_directory(resDir)) {
spdlog::error("Resource directory doesn't exist! Please make sure that you've configured it correctly in config.json (check readme for details)");
return 1;
}
2020-09-19 10:48:34 +00:00
// Create window with graphics context
GLFWmonitor* monitor = glfwGetPrimaryMonitor();
2021-04-23 17:12:24 +00:00
core::window = glfwCreateWindow(winWidth, winHeight, "SDR++ v" VERSION_STR " (Built at " __TIME__ ", " __DATE__ ")", NULL, NULL);
if (core::window == NULL)
2020-09-19 10:48:34 +00:00
return 1;
2021-04-23 17:12:24 +00:00
glfwMakeContextCurrent(core::window);
2020-09-19 10:48:34 +00:00
#if (GLFW_VERSION_MAJOR == 3) && (GLFW_VERSION_MINOR >= 3)
2020-09-19 10:48:34 +00:00
if (maximized) {
2021-04-23 17:12:24 +00:00
glfwMaximizeWindow(core::window);
2020-09-19 10:48:34 +00:00
}
2021-04-23 17:12:24 +00:00
glfwSetWindowMaximizeCallback(core::window, maximized_callback);
2020-10-22 15:55:49 +00:00
#endif
2020-09-19 10:48:34 +00:00
// Load app icon
if (!std::filesystem::is_regular_file(resDir + "/icons/sdrpp.png")) {
spdlog::error("Icon file '{0}' doesn't exist!", resDir + "/icons/sdrpp.png");
return 1;
}
2020-09-19 10:48:34 +00:00
GLFWimage icons[10];
2020-12-22 22:10:49 +00:00
icons[0].pixels = stbi_load(((std::string)(resDir + "/icons/sdrpp.png")).c_str(), &icons[0].width, &icons[0].height, 0, 4);
2020-09-19 10:48:34 +00:00
icons[1].pixels = (unsigned char*)malloc(16 * 16 * 4); icons[1].width = icons[1].height = 16;
icons[2].pixels = (unsigned char*)malloc(24 * 24 * 4); icons[2].width = icons[2].height = 24;
icons[3].pixels = (unsigned char*)malloc(32 * 32 * 4); icons[3].width = icons[3].height = 32;
icons[4].pixels = (unsigned char*)malloc(48 * 48 * 4); icons[4].width = icons[4].height = 48;
icons[5].pixels = (unsigned char*)malloc(64 * 64 * 4); icons[5].width = icons[5].height = 64;
icons[6].pixels = (unsigned char*)malloc(96 * 96 * 4); icons[6].width = icons[6].height = 96;
icons[7].pixels = (unsigned char*)malloc(128 * 128 * 4); icons[7].width = icons[7].height = 128;
icons[8].pixels = (unsigned char*)malloc(196 * 196 * 4); icons[8].width = icons[8].height = 196;
icons[9].pixels = (unsigned char*)malloc(256 * 256 * 4); icons[9].width = icons[9].height = 256;
stbir_resize_uint8(icons[0].pixels, icons[0].width, icons[0].height, icons[0].width * 4, icons[1].pixels, 16, 16, 16 * 4, 4);
stbir_resize_uint8(icons[0].pixels, icons[0].width, icons[0].height, icons[0].width * 4, icons[2].pixels, 24, 24, 24 * 4, 4);
stbir_resize_uint8(icons[0].pixels, icons[0].width, icons[0].height, icons[0].width * 4, icons[3].pixels, 32, 32, 32 * 4, 4);
stbir_resize_uint8(icons[0].pixels, icons[0].width, icons[0].height, icons[0].width * 4, icons[4].pixels, 48, 48, 48 * 4, 4);
stbir_resize_uint8(icons[0].pixels, icons[0].width, icons[0].height, icons[0].width * 4, icons[5].pixels, 64, 64, 64 * 4, 4);
stbir_resize_uint8(icons[0].pixels, icons[0].width, icons[0].height, icons[0].width * 4, icons[6].pixels, 96, 96, 96 * 4, 4);
stbir_resize_uint8(icons[0].pixels, icons[0].width, icons[0].height, icons[0].width * 4, icons[7].pixels, 128, 128, 128 * 4, 4);
stbir_resize_uint8(icons[0].pixels, icons[0].width, icons[0].height, icons[0].width * 4, icons[8].pixels, 196, 196, 196 * 4, 4);
stbir_resize_uint8(icons[0].pixels, icons[0].width, icons[0].height, icons[0].width * 4, icons[9].pixels, 256, 256, 256 * 4, 4);
2021-04-23 17:12:24 +00:00
glfwSetWindowIcon(core::window, 10, icons);
2020-09-19 10:48:34 +00:00
stbi_image_free(icons[0].pixels);
for (int i = 1; i < 10; i++) {
free(icons[i].pixels);
}
if (glewInit() != GLEW_OK) {
spdlog::error("Failed to initialize OpenGL loader!");
return 1;
}
// Setup Dear ImGui context
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO(); (void)io;
io.IniFilename = NULL;
// Setup Platform/Renderer bindings
2021-04-23 17:12:24 +00:00
ImGui_ImplGlfw_InitForOpenGL(core::window, true);
2021-04-01 18:57:03 +00:00
2021-04-20 20:53:23 +00:00
if (!ImGui_ImplOpenGL3_Init(glsl_version)) {
// If init fail, try to fall back on GLSL 1.2
spdlog::warn("Could not init using OpenGL with normal GLSL version, falling back to GLSL 1.2");
if (!ImGui_ImplOpenGL3_Init("#version 120")) {
spdlog::error("Failed to initialize OpenGL with GLSL 1.2");
return -1;
}
2021-04-01 18:57:03 +00:00
}
2020-09-19 10:48:34 +00:00
2021-06-23 19:45:38 +00:00
if (!style::loadFonts(resDir)) { return -1; }
thememenu::init(resDir);
2020-09-19 10:48:34 +00:00
2021-04-23 17:12:24 +00:00
LoadingScreen::setWindow(core::window);
2020-09-19 10:48:34 +00:00
2020-11-30 20:17:36 +00:00
LoadingScreen::show("Loading icons");
2020-09-19 10:48:34 +00:00
spdlog::info("Loading icons");
2020-12-22 21:39:24 +00:00
if (!icons::load(resDir)) { return -1; }
2020-09-19 10:48:34 +00:00
2020-11-30 20:17:36 +00:00
LoadingScreen::show("Loading band plans");
2020-09-19 10:48:34 +00:00
spdlog::info("Loading band plans");
2020-12-22 23:11:12 +00:00
bandplan::loadFromDir(resDir + "/bandplans");
2020-09-19 10:48:34 +00:00
2020-11-30 20:17:36 +00:00
LoadingScreen::show("Loading band plan colors");
2020-09-19 10:48:34 +00:00
spdlog::info("Loading band plans color table");
2020-12-22 23:11:12 +00:00
bandplan::loadColorTable(bandColors);
2020-09-19 10:48:34 +00:00
2021-06-20 19:17:11 +00:00
gui::mainWindow.init();
2020-09-19 10:48:34 +00:00
spdlog::info("Ready.");
bool _maximized = maximized;
int fsWidth, fsHeight, fsPosX, fsPosY;
// Main loop
2021-04-23 17:12:24 +00:00
while (!glfwWindowShouldClose(core::window)) {
2020-09-19 10:48:34 +00:00
glfwPollEvents();
// Start the Dear ImGui frame
ImGui_ImplOpenGL3_NewFrame();
ImGui_ImplGlfw_NewFrame();
ImGui::NewFrame();
//ImGui::ShowDemoWindow();
2020-09-19 10:48:34 +00:00
if (_maximized != maximized) {
_maximized = maximized;
2020-09-24 17:36:57 +00:00
core::configManager.aquire();
core::configManager.conf["maximized"]= _maximized;
2020-09-19 10:48:34 +00:00
if (!maximized) {
2021-04-23 17:12:24 +00:00
glfwSetWindowSize(core::window, core::configManager.conf["windowSize"]["w"], core::configManager.conf["windowSize"]["h"]);
2020-09-19 10:48:34 +00:00
}
2020-09-24 17:36:57 +00:00
core::configManager.release(true);
2020-09-19 10:48:34 +00:00
}
int _winWidth, _winHeight;
2021-04-23 17:12:24 +00:00
glfwGetWindowSize(core::window, &_winWidth, &_winHeight);
2020-09-19 10:48:34 +00:00
if (ImGui::IsKeyPressed(GLFW_KEY_F11)) {
fullScreen = !fullScreen;
if (fullScreen) {
spdlog::info("Fullscreen: ON");
fsWidth = _winWidth;
fsHeight = _winHeight;
2021-04-23 17:12:24 +00:00
glfwGetWindowPos(core::window, &fsPosX, &fsPosY);
2020-09-19 10:48:34 +00:00
const GLFWvidmode * mode = glfwGetVideoMode(glfwGetPrimaryMonitor());
2021-04-23 17:12:24 +00:00
glfwSetWindowMonitor(core::window, monitor, 0, 0, mode->width, mode->height, 0);
2020-09-19 10:48:34 +00:00
}
else {
spdlog::info("Fullscreen: OFF");
2021-04-23 17:12:24 +00:00
glfwSetWindowMonitor(core::window, nullptr, fsPosX, fsPosY, fsWidth, fsHeight, 0);
2020-09-19 10:48:34 +00:00
}
}
if ((_winWidth != winWidth || _winHeight != winHeight) && !maximized && _winWidth > 0 && _winHeight > 0) {
winWidth = _winWidth;
winHeight = _winHeight;
2020-09-24 17:36:57 +00:00
core::configManager.aquire();
core::configManager.conf["windowSize"]["w"] = winWidth;
core::configManager.conf["windowSize"]["h"] = winHeight;
core::configManager.release(true);
2020-09-19 10:48:34 +00:00
}
if (winWidth > 0 && winHeight > 0) {
ImGui::SetNextWindowPos(ImVec2(0, 0));
ImGui::SetNextWindowSize(ImVec2(_winWidth, _winHeight));
2021-06-20 19:17:11 +00:00
gui::mainWindow.draw();
2020-09-19 10:48:34 +00:00
}
// Rendering
ImGui::Render();
int display_w, display_h;
2021-04-23 17:12:24 +00:00
glfwGetFramebufferSize(core::window, &display_w, &display_h);
2020-09-19 10:48:34 +00:00
glViewport(0, 0, display_w, display_h);
2021-06-23 19:45:38 +00:00
//glClearColor(0.0666f, 0.0666f, 0.0666f, 1.0f);
glClearColor(gui::themeManager.clearColor.x, gui::themeManager.clearColor.y, gui::themeManager.clearColor.z, gui::themeManager.clearColor.w);
2020-09-19 10:48:34 +00:00
glClear(GL_COLOR_BUFFER_BIT);
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
2020-12-04 19:12:36 +00:00
glfwSwapInterval(1); // Enable vsync
2021-04-23 17:12:24 +00:00
glfwSwapBuffers(core::window);
2020-09-19 10:48:34 +00:00
}
// Cleanup
ImGui_ImplOpenGL3_Shutdown();
ImGui_ImplGlfw_Shutdown();
ImGui::DestroyContext();
2021-04-23 17:12:24 +00:00
glfwDestroyWindow(core::window);
2020-09-19 10:48:34 +00:00
glfwTerminate();
sigpath::signalPath.stop();
2020-09-19 10:48:34 +00:00
return 0;
2020-10-22 15:55:49 +00:00
}