summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--3rdparty/imgui/CMakeLists.txt85
-rw-r--r--3rdparty/imnodes/CMakeLists.txt12
-rw-r--r--CMakeLists.txt4
-rw-r--r--conanfile.txt1
-rw-r--r--core/CMakeLists.txt60
-rw-r--r--core/fonts/NotoSansSC-LICENSE.txt91
-rw-r--r--core/fonts/NotoSansSC-Regular.otfbin0 -> 8481960 bytes
-rw-r--r--core/src/Entrypoint/Common.cpp11
-rw-r--r--core/src/Entrypoint/Common.hpp20
-rw-r--r--core/src/Entrypoint/DirectX11.cpp13
-rw-r--r--core/src/Entrypoint/DirectX11.hpp11
-rw-r--r--core/src/Entrypoint/DirectX12.cpp13
-rw-r--r--core/src/Entrypoint/DirectX12.hpp11
-rw-r--r--core/src/Entrypoint/Metal.hpp11
-rw-r--r--core/src/Entrypoint/Metal.mm13
-rw-r--r--core/src/Entrypoint/OpenGL2.cpp70
-rw-r--r--core/src/Entrypoint/OpenGL2.hpp15
-rw-r--r--core/src/Entrypoint/OpenGL3.cpp85
-rw-r--r--core/src/Entrypoint/OpenGL3.hpp15
-rw-r--r--core/src/Entrypoint/Vulkan.cpp13
-rw-r--r--core/src/Entrypoint/Vulkan.hpp11
-rw-r--r--core/src/Entrypoint/main.cpp91
-rw-r--r--core/src/UI/Export.cpp1
-rw-r--r--core/src/UI/Export.hpp1
25 files changed, 647 insertions, 13 deletions
diff --git a/.gitignore b/.gitignore
index 95ff04c..223be0c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -78,4 +78,6 @@ CMakeLists.txt.user*
*.exe
.vscode/c_cpp_properties.json
+.vscode/settings.json
build*/
+imgui.ini
diff --git a/3rdparty/imgui/CMakeLists.txt b/3rdparty/imgui/CMakeLists.txt
index 191f1ea..3382d72 100644
--- a/3rdparty/imgui/CMakeLists.txt
+++ b/3rdparty/imgui/CMakeLists.txt
@@ -1,2 +1,83 @@
-file(GLOB_RECURSE IMGUI_SOURCES ${CMAKE_CURRENT_LIST_DIR}/*.cpp)
-add_library(imgui IMGUI_SOURCES)
+set(IMGUI_SOURCES
+ imgui.h
+ imgui.cpp
+ imconfig.h
+ imgui_internal.h
+ imgui_demo.cpp
+ imgui_draw.cpp
+ imgui_tables.cpp
+ imgui_widgets.cpp
+ imstb_rectpack.h
+ imstb_textedit.h
+ imstb_truetype.h
+
+ # Since we only use GLFW to manage windows, application can't be built without GLFW
+ backend/imgui_impl_glfw.h
+ backend/imgui_impl_glfw.cpp
+)
+
+option(IMGUI_INCLUDE_OPENGL2_BACKEND ON)
+if(IMGUI_INCLUDE_OPENGL2_BACKEND)
+ message("ImGui: - building with OpenGL2 backend")
+ list(APPEND IMGUI_SOURCES
+ backend/imgui_impl_opengl2.h
+ backend/imgui_impl_opengl2.cpp
+ )
+endif()
+
+option(IMGUI_INCLUDE_OPENGL3_BACKEND ON)
+if(IMGUI_INCLUDE_OPENGL3_BACKEND)
+ message("ImGui: - building with OpenGL3 backend")
+ list(APPEND IMGUI_SOURCES
+ backend/imgui_impl_opengl3.h
+ backend/imgui_impl_opengl3.cpp
+ )
+endif()
+
+option(IMGUI_INCLUDE_VULKAN_BACKEND ON)
+if(IMGUI_INCLUDE_VULKAN_BACKEND)
+ message("ImGui: - building with Vulkan backend")
+ list(APPEND IMGUI_SOURCES
+ backend/imgui_impl_vulkan.h
+ backend/imgui_impl_vulkan.cpp
+ )
+endif()
+
+if(WIN32)
+ option(IMGUI_INCLUDE_DX11_BACKEND ON)
+ if(IMGUI_INCLUDE_DX11_BACKEND)
+ message("ImGui: - building with DirectX11 backend")
+ list(APPEND IMGUI_SOURCES
+ backend/imgui_impl_dx11.h
+ backend/imgui_impl_dx11.cpp
+ )
+ endif()
+
+ option(IMGUI_INCLUDE_DX12_BACKEND ON)
+ if(IMGUI_INCLUDE_DX12_BACKEND)
+ message("ImGui: - building with DirectX12 backend")
+ list(APPEND IMGUI_SOURCES
+ backend/imgui_impl_dx12.h
+ backend/imgui_impl_dx12.cpp
+ )
+ endif()
+elseif(APPLE)
+ option(IMGUI_INCLUDE_METAL_BACKEND ON)
+ if(IMGUI_INCLUDE_METAL_BACKEND)
+ message("ImGui: - building with Metal backend")
+ list(APPEND IMGUI_SOURCES
+ backend/imgui_impl_metal.h
+ backend/imgui_impl_metal.mm
+ )
+ endif()
+endif()
+
+add_library(imgui ${IMGUI_SOURCES})
+target_compile_definitions(imgui
+PRIVATE
+ IMGUI_IMPL_OPENGL_LOADER_GLAD=1
+)
+target_include_directories(imgui
+PRIVATE
+ ${CMAKE_SOURCE_DIR}/3rdparty/imgui
+)
diff --git a/3rdparty/imnodes/CMakeLists.txt b/3rdparty/imnodes/CMakeLists.txt
index 16b007a..bb1290c 100644
--- a/3rdparty/imnodes/CMakeLists.txt
+++ b/3rdparty/imnodes/CMakeLists.txt
@@ -1,2 +1,10 @@
-file(GLOB_RECURSE IMNODES_SOURCES ${CMAKE_CURRENT_LIST_DIR}/*.cpp)
-add_library(imnodes IMNODES_SOURCES)
+set(IMNODES_SOURCES
+ imnodes.h
+ imnodes.cpp
+)
+
+add_library(imnodes ${IMNODES_SOURCES})
+target_include_directories(imnodes PRIVATE
+ ${CMAKE_SOURCE_DIR}/3rdparty/imnodes
+ ${CMAKE_SOURCE_DIR}/3rdparty/imgui
+)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 4b6f7ba..aeb7b0e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,5 +1,7 @@
cmake_minimum_required(VERSION 3.5)
project(Cplt LANGUAGES CXX)
+set(CMAKE_CXX_STANDARD 20)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
option(FORCE_COLORED_OUTPUT "Always produce ANSI-colored output (GNU/Clang only)." ON)
if(FORCE_COLORED_OUTPUT)
@@ -10,6 +12,8 @@ if(FORCE_COLORED_OUTPUT)
endif()
endif()
+set(LINUX ${CMAKE_SYSTEM_NAME} MATCHES "Linux")
+
include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
conan_basic_setup()
diff --git a/conanfile.txt b/conanfile.txt
index 2bf6348..4ddf420 100644
--- a/conanfile.txt
+++ b/conanfile.txt
@@ -1,5 +1,6 @@
[requires]
argparse/2.1
+sqlite3/3.35.2
glfw/3.3.2
glad/0.1.34
doctest/2.4.4
diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt
index f2077a3..0eb4900 100644
--- a/core/CMakeLists.txt
+++ b/core/CMakeLists.txt
@@ -1,6 +1,6 @@
-project(CpltCore LANGUAGES CXX)
-set(CMAKE_CXX_STANDARD 20)
-set(CMAKE_CXX_STANDARD_REQUIRED ON)
+option(BUILD_CORE_WITH_UNITY_BUILD OFF)
+option(BUILD_CORE_MAIN "Whether to compile the main executable or not." ON)
+option(BUILD_CORE_TESTS "Whether to compile the tests executable or not." OFF)
function(add_source_group GROUP_NAME GROUP_SOURCES)
set(${GROUP_NAME} ${GROUP_SOURCES})
@@ -11,9 +11,26 @@ function(add_source_group GROUP_NAME GROUP_SOURCES)
endfunction()
set(ENTRYPOINT_MODULE_SOURCES
+ src/Entrypoint/main.cpp
+ src/Entrypoint/Common.hpp
+ src/Entrypoint/Common.cpp
+ src/Entrypoint/OpenGL2.hpp
+ src/Entrypoint/OpenGL2.cpp
+ src/Entrypoint/OpenGL3.hpp
+ src/Entrypoint/OpenGL3.cpp
+ src/Entrypoint/Vulkan.hpp
+ src/Entrypoint/Vulkan.cpp
+ src/Entrypoint/DirectX11.hpp
+ src/Entrypoint/DirectX11.cpp
+ src/Entrypoint/DirectX12.hpp
+ src/Entrypoint/DirectX12.cpp
+ src/Entrypoint/Metal.hpp
+ src/Entrypoint/Metal.mm
)
add_source_group(UI_MODULE_SOURCES
+ src/UI/Export.hpp
+ src/UI/Export.cpp
)
add_source_group(UTILS_MODULE_SOURCES
@@ -33,6 +50,7 @@ set(UTILS_DIALOG_MODULE_SOURCES
src/Utils/Dialog/Dialog.cpp
)
if(APPLE)
+ find_library(COCOA_LIBRARY Cocoa)
list(APPEND UTILS_DIALOG_MODULE_SOURCES
src/Utils/Dialog/Dialog_macos.mm
)
@@ -41,6 +59,8 @@ elseif(WIN32)
src/Utils/Dialog/Dialog_win32.cpp
)
elseif(LINUX)
+ find_package(PkgConfig REQUIRED)
+ pkg_check_modules(GTK3 REQUIRED gtk+-3.0)
list(APPEND UTILS_DIALOG_MODULE_SOURCES
src/Utils/Dialog/Dialog_linux.cpp
)
@@ -60,14 +80,32 @@ function(add_executable_variant TARGET_NAME)
${CMAKE_SOURCE_DIR}/3rdparty/imgui
${CMAKE_SOURCE_DIR}/3rdparty/imnodes
)
- target_link_libraries(${TARGET_NAME} PRIVATE ${CONAN_LIBS})
+ target_link_libraries(${TARGET_NAME}
+ PRIVATE
+ ${CONAN_LIBS}
+ imgui
+ imnodes
+ )
target_compile_definitions(${TARGET_NAME}
PRIVATE
PLATFORM_WIN32=$<BOOL:${WIN32}>
PLATFORM_MACOS=$<BOOL:${APPLE}>
PLATFORM_LINUX=$<BOOL:${LINUX}>
+ IMGUI_INCLUDE_OPENGL2_BACKEND=$<BOOL:${IMGUI_INCLUDE_OPENGL2_BACKEND}>
+ IMGUI_INCLUDE_OPENGL3_BACKEND=$<BOOL:${IMGUI_INCLUDE_OPENGL3_BACKEND}>
+ IMGUI_INCLUDE_VULKAN_BACKEND=$<BOOL:${IMGUI_INCLUDE_VULKAN_BACKEND}>
+ IMGUI_INCLUDE_DX11_BACKEND=$<BOOL:${IMGUI_INCLUDE_DX11_BACKEND}>
+ IMGUI_INCLUDE_DX12_BACKEND=$<BOOL:${IMGUI_INCLUDE_DX12_BACKEND}>
+ IMGUI_INCLUDE_METAL_BACKEND=$<BOOL:${IMGUI_INCLUDE_METAL_BACKEND}>
)
+ if(APPLE)
+ target_link_libraries(${TARGET_NAME} PUBLIC ${COCOA_LIBRARY})
+ elseif(LINUX)
+ target_link_libraries(${TARGET_NAME} PUBLIC ${GTK3_LIBRARIES})
+ target_include_directories(${TARGET_NAME} PRIVATE ${GTK3_INCLUDE_DIRS})
+ endif()
+
# No console window when targetting windows
if(WIN32)
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
@@ -81,11 +119,11 @@ function(add_executable_variant TARGET_NAME)
endif()
endif()
- if(${CMAKE_UNITY_BUILD})
+ if(BUILD_CORE_WITH_UNITY_BUILD)
message("CpltCore: - using unity build")
set_target_properties(${TARGET_NAME}
PROPERTIES
- # UNITY_BUILD property is automatically set when CMAKE_UNITY_BUILD is set
+ UNITY_BUILD ON
UNITY_BUILD_MODE GROUP
)
else()
@@ -93,7 +131,11 @@ function(add_executable_variant TARGET_NAME)
endif()
endfunction()
-add_executable_variant(CpltCore_main)
-target_compile_definitions(CpltCore_main PRIVATE DOCTEST_CONFIG_DISABLE=1)
+if(BUILD_CORE_MAIN)
+ add_executable_variant(CpltCore_main)
+ target_compile_definitions(CpltCore_main PRIVATE DOCTEST_CONFIG_DISABLE=1)
+endif()
-add_executable_variant(CpltCore_test)
+if(BUILD_CORE_TESTS)
+ add_executable_variant(CpltCore_test)
+endif()
diff --git a/core/fonts/NotoSansSC-LICENSE.txt b/core/fonts/NotoSansSC-LICENSE.txt
new file mode 100644
index 0000000..075d1ae
--- /dev/null
+++ b/core/fonts/NotoSansSC-LICENSE.txt
@@ -0,0 +1,91 @@
+This Font Software is licensed under the SIL Open Font License, Version 1.1.
+This license is copied below, and is also available with a FAQ at:
+http://scripts.sil.org/OFL
+
+
+-----------------------------------------------------------
+SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
+-----------------------------------------------------------
+
+PREAMBLE
+The goals of the Open Font License (OFL) are to stimulate worldwide
+development of collaborative font projects, to support the font creation
+efforts of academic and linguistic communities, and to provide a free and
+open framework in which fonts may be shared and improved in partnership
+with others.
+
+The OFL allows the licensed fonts to be used, studied, modified and
+redistributed freely as long as they are not sold by themselves. The
+fonts, including any derivative works, can be bundled, embedded,
+redistributed and/or sold with any software provided that any reserved
+names are not used by derivative works. The fonts and derivatives,
+however, cannot be released under any other type of license. The
+requirement for fonts to remain under this license does not apply
+to any document created using the fonts or their derivatives.
+
+DEFINITIONS
+"Font Software" refers to the set of files released by the Copyright
+Holder(s) under this license and clearly marked as such. This may
+include source files, build scripts and documentation.
+
+"Reserved Font Name" refers to any names specified as such after the
+copyright statement(s).
+
+"Original Version" refers to the collection of Font Software components as
+distributed by the Copyright Holder(s).
+
+"Modified Version" refers to any derivative made by adding to, deleting,
+or substituting -- in part or in whole -- any of the components of the
+Original Version, by changing formats or by porting the Font Software to a
+new environment.
+
+"Author" refers to any designer, engineer, programmer, technical
+writer or other person who contributed to the Font Software.
+
+PERMISSION & CONDITIONS
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of the Font Software, to use, study, copy, merge, embed, modify,
+redistribute, and sell modified and unmodified copies of the Font
+Software, subject to the following conditions:
+
+1) Neither the Font Software nor any of its individual components,
+in Original or Modified Versions, may be sold by itself.
+
+2) Original or Modified Versions of the Font Software may be bundled,
+redistributed and/or sold with any software, provided that each copy
+contains the above copyright notice and this license. These can be
+included either as stand-alone text files, human-readable headers or
+in the appropriate machine-readable metadata fields within text or
+binary files as long as those fields can be easily viewed by the user.
+
+3) No Modified Version of the Font Software may use the Reserved Font
+Name(s) unless explicit written permission is granted by the corresponding
+Copyright Holder. This restriction only applies to the primary font name as
+presented to the users.
+
+4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
+Software shall not be used to promote, endorse or advertise any
+Modified Version, except to acknowledge the contribution(s) of the
+Copyright Holder(s) and the Author(s) or with their explicit written
+permission.
+
+5) The Font Software, modified or unmodified, in part or in whole,
+must be distributed entirely under this license, and must not be
+distributed under any other license. The requirement for fonts to
+remain under this license does not apply to any document created
+using the Font Software.
+
+TERMINATION
+This license becomes null and void if any of the above conditions are
+not met.
+
+DISCLAIMER
+THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
+DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
+OTHER DEALINGS IN THE FONT SOFTWARE.
diff --git a/core/fonts/NotoSansSC-Regular.otf b/core/fonts/NotoSansSC-Regular.otf
new file mode 100644
index 0000000..fdb0506
--- /dev/null
+++ b/core/fonts/NotoSansSC-Regular.otf
Binary files differ
diff --git a/core/src/Entrypoint/Common.cpp b/core/src/Entrypoint/Common.cpp
new file mode 100644
index 0000000..62baf9d
--- /dev/null
+++ b/core/src/Entrypoint/Common.cpp
@@ -0,0 +1,11 @@
+#include "Common.hpp"
+
+#include <iostream>
+
+GLFWwindow* RenderingBackend::GetWindow() const {
+ return mWindow;
+}
+
+void RenderingBackend::GlfwErrorCallback(int error, const char* message) {
+ std::cerr << "GLFW Error " << error << ": " << message << "\n";
+}
diff --git a/core/src/Entrypoint/Common.hpp b/core/src/Entrypoint/Common.hpp
new file mode 100644
index 0000000..2a4dcbf
--- /dev/null
+++ b/core/src/Entrypoint/Common.hpp
@@ -0,0 +1,20 @@
+#pragma once
+
+#include <glad/glad.h>
+
+#include <GLFW/glfw3.h>
+
+class RenderingBackend {
+protected:
+ GLFWwindow* mWindow;
+
+public:
+ virtual ~RenderingBackend() = default;
+ virtual void BeginFrame() = 0;
+ virtual void EndFrame() = 0;
+
+ GLFWwindow* GetWindow() const;
+
+ /// Common GLFW error handle callback for each rendering backend to use.
+ static void GlfwErrorCallback(int error, const char* message);
+};
diff --git a/core/src/Entrypoint/DirectX11.cpp b/core/src/Entrypoint/DirectX11.cpp
new file mode 100644
index 0000000..617447c
--- /dev/null
+++ b/core/src/Entrypoint/DirectX11.cpp
@@ -0,0 +1,13 @@
+#include "DirectX11.hpp"
+
+DirectX11Backend::DirectX11Backend() {
+ // TODO
+}
+
+void DirectX11Backend::BeginFrame() {
+ // TODO
+}
+
+void DirectX11Backend::EndFrame() {
+ // TODO
+}
diff --git a/core/src/Entrypoint/DirectX11.hpp b/core/src/Entrypoint/DirectX11.hpp
new file mode 100644
index 0000000..134a20f
--- /dev/null
+++ b/core/src/Entrypoint/DirectX11.hpp
@@ -0,0 +1,11 @@
+#pragma once
+
+#include "Entrypoint/Common.hpp"
+
+class DirectX11Backend : public RenderingBackend {
+public:
+ DirectX11Backend();
+ virtual ~DirectX11Backend() = default;
+ virtual void BeginFrame() override;
+ virtual void EndFrame() override;
+};
diff --git a/core/src/Entrypoint/DirectX12.cpp b/core/src/Entrypoint/DirectX12.cpp
new file mode 100644
index 0000000..1769d24
--- /dev/null
+++ b/core/src/Entrypoint/DirectX12.cpp
@@ -0,0 +1,13 @@
+#include "DirectX12.hpp"
+
+DirectX12Backend::DirectX12Backend() {
+ // TODO
+}
+
+void DirectX12Backend::BeginFrame() {
+ // TODO
+}
+
+void DirectX12Backend::EndFrame() {
+ // TODO
+}
diff --git a/core/src/Entrypoint/DirectX12.hpp b/core/src/Entrypoint/DirectX12.hpp
new file mode 100644
index 0000000..8b9a4f0
--- /dev/null
+++ b/core/src/Entrypoint/DirectX12.hpp
@@ -0,0 +1,11 @@
+#pragma once
+
+#include "Entrypoint/Common.hpp"
+
+class DirectX12Backend : public RenderingBackend {
+public:
+ DirectX12Backend();
+ virtual ~DirectX12Backend() = default;
+ virtual void BeginFrame() override;
+ virtual void EndFrame() override;
+};
diff --git a/core/src/Entrypoint/Metal.hpp b/core/src/Entrypoint/Metal.hpp
new file mode 100644
index 0000000..cd96d0f
--- /dev/null
+++ b/core/src/Entrypoint/Metal.hpp
@@ -0,0 +1,11 @@
+#pragma once
+
+#include "Entrypoint/Common.hpp"
+
+class MetalBackend : public RenderingBackend {
+public:
+ MetalBackend();
+ virtual ~MetalBackend() = default;
+ virtual void BeginFrame() override;
+ virtual void EndFrame() override;
+};
diff --git a/core/src/Entrypoint/Metal.mm b/core/src/Entrypoint/Metal.mm
new file mode 100644
index 0000000..3f69634
--- /dev/null
+++ b/core/src/Entrypoint/Metal.mm
@@ -0,0 +1,13 @@
+#include "Metal.hpp"
+
+MetalBackend::MetalBackend() {
+ // TODO
+}
+
+void MetalBackend::BeginFrame() {
+ // TODO
+}
+
+void MetalBackend::EndFrame() {
+ // TODO
+}
diff --git a/core/src/Entrypoint/OpenGL2.cpp b/core/src/Entrypoint/OpenGL2.cpp
new file mode 100644
index 0000000..de13a02
--- /dev/null
+++ b/core/src/Entrypoint/OpenGL2.cpp
@@ -0,0 +1,70 @@
+#include "OpenGL2.hpp"
+
+#include <glad/glad.h>
+
+#include <GLFW/glfw3.h>
+#include <backend/imgui_impl_glfw.h>
+#include <backend/imgui_impl_opengl2.h>
+#include <imgui.h>
+#include <stdexcept>
+
+OpenGL2Backend::OpenGL2Backend() {
+#if IMGUI_INCLUDE_OPENGL2_BACKEND
+ glfwSetErrorCallback(GlfwErrorCallback);
+ if (!glfwInit()) {
+ throw std::runtime_error("Failed to initialize GLFW.");
+ }
+
+ mWindow = glfwCreateWindow(1280, 720, "Cplt", nullptr, nullptr);
+ if (mWindow == nullptr) {
+ throw std::runtime_error("Failed to create GLFW window.");
+ }
+ glfwMakeContextCurrent(mWindow);
+ glfwSwapInterval(1); // Enable vsync
+
+ if (gladLoadGLLoader((GLADloadproc)glfwGetProcAddress) == 0) {
+ throw std::runtime_error("Failed to initialize OpenGL.");
+ }
+
+ IMGUI_CHECKVERSION();
+ ImGui::CreateContext();
+
+ ImGui_ImplGlfw_InitForOpenGL(mWindow, true);
+ ImGui_ImplOpenGL2_Init();
+#else
+ throw std::runtime_error("Backend opengl2 is not available in this build.\n");
+#endif
+}
+
+OpenGL2Backend::~OpenGL2Backend() {
+ ImGui_ImplOpenGL2_Shutdown();
+ ImGui_ImplGlfw_Shutdown();
+ ImGui::DestroyContext();
+
+ glfwDestroyWindow(mWindow);
+ glfwTerminate();
+}
+
+void OpenGL2Backend::BeginFrame() {
+ glfwPollEvents();
+
+ ImGui_ImplOpenGL2_NewFrame();
+ ImGui_ImplGlfw_NewFrame();
+ ImGui::NewFrame();
+}
+
+void OpenGL2Backend::EndFrame() {
+ int displayWidth, displayHeight;
+ glfwGetFramebufferSize(mWindow, &displayWidth, &displayHeight);
+ glViewport(0, 0, displayWidth, displayHeight);
+
+ const ImVec4 kClearColor = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
+ glClearColor(kClearColor.x * kClearColor.w, kClearColor.y * kClearColor.w, kClearColor.z * kClearColor.w, kClearColor.w);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ ImGui::Render();
+ ImGui_ImplOpenGL2_RenderDrawData(ImGui::GetDrawData());
+
+ glfwMakeContextCurrent(mWindow);
+ glfwSwapBuffers(mWindow);
+}
diff --git a/core/src/Entrypoint/OpenGL2.hpp b/core/src/Entrypoint/OpenGL2.hpp
new file mode 100644
index 0000000..86fbad7
--- /dev/null
+++ b/core/src/Entrypoint/OpenGL2.hpp
@@ -0,0 +1,15 @@
+#pragma once
+
+#include "Entrypoint/Common.hpp"
+
+#include <glad/glad.h>
+
+#include <GLFW/glfw3.h>
+
+class OpenGL2Backend : public RenderingBackend {
+public:
+ OpenGL2Backend();
+ virtual ~OpenGL2Backend();
+ virtual void BeginFrame() override;
+ virtual void EndFrame() override;
+};
diff --git a/core/src/Entrypoint/OpenGL3.cpp b/core/src/Entrypoint/OpenGL3.cpp
new file mode 100644
index 0000000..c1f66d5
--- /dev/null
+++ b/core/src/Entrypoint/OpenGL3.cpp
@@ -0,0 +1,85 @@
+#include "OpenGL3.hpp"
+
+#include <glad/glad.h>
+
+#include <GLFW/glfw3.h>
+#include <backend/imgui_impl_glfw.h>
+#include <backend/imgui_impl_opengl3.h>
+#include <imgui.h>
+#include <stdexcept>
+
+OpenGL3Backend::OpenGL3Backend() {
+#if IMGUI_INCLUDE_OPENGL3_BACKEND
+ glfwSetErrorCallback(GlfwErrorCallback);
+ if (!glfwInit()) {
+ throw std::runtime_error("Failed to initialize GLFW.");
+ }
+
+# if PLATFORM_APPLE
+ // GL 3.2 + GLSL 150
+ const char* glslVersion = "#version 150";
+ 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
+# else
+ // GL 3.0 + GLSL 130
+ const char* glslVersion = "#version 130";
+ glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
+ glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
+ //glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // 3.2+ only
+ //glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // 3.0+ only
+# endif
+
+ mWindow = glfwCreateWindow(1280, 720, "Cplt", nullptr, nullptr);
+ if (mWindow == nullptr) {
+ throw std::runtime_error("Failed to create GLFW window.");
+ }
+ glfwMakeContextCurrent(mWindow);
+ glfwSwapInterval(1); // Enable vsync
+
+ if (gladLoadGLLoader((GLADloadproc)glfwGetProcAddress) == 0) {
+ throw std::runtime_error("Failed to initialize OpenGL.");
+ }
+
+ IMGUI_CHECKVERSION();
+ ImGui::CreateContext();
+
+ ImGui_ImplGlfw_InitForOpenGL(mWindow, true);
+ ImGui_ImplOpenGL3_Init(glslVersion);
+#else
+ throw std::runtime_error("Backend opengl3 is not available in this build.\n");
+#endif
+}
+
+OpenGL3Backend::~OpenGL3Backend() {
+ ImGui_ImplOpenGL3_Shutdown();
+ ImGui_ImplGlfw_Shutdown();
+ ImGui::DestroyContext();
+
+ glfwDestroyWindow(mWindow);
+ glfwTerminate();
+}
+
+void OpenGL3Backend::BeginFrame() {
+ glfwPollEvents();
+
+ ImGui_ImplOpenGL3_NewFrame();
+ ImGui_ImplGlfw_NewFrame();
+ ImGui::NewFrame();
+}
+
+void OpenGL3Backend::EndFrame() {
+ int displayWidth, displayHeight;
+ glfwGetFramebufferSize(mWindow, &displayWidth, &displayHeight);
+ glViewport(0, 0, displayWidth, displayHeight);
+
+ const ImVec4 kClearColor = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
+ glClearColor(kClearColor.x * kClearColor.w, kClearColor.y * kClearColor.w, kClearColor.z * kClearColor.w, kClearColor.w);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ ImGui::Render();
+ ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
+
+ glfwSwapBuffers(mWindow);
+}
diff --git a/core/src/Entrypoint/OpenGL3.hpp b/core/src/Entrypoint/OpenGL3.hpp
new file mode 100644
index 0000000..29086a2
--- /dev/null
+++ b/core/src/Entrypoint/OpenGL3.hpp
@@ -0,0 +1,15 @@
+#pragma once
+
+#include "Entrypoint/Common.hpp"
+
+#include <glad/glad.h>
+
+#include <GLFW/glfw3.h>
+
+class OpenGL3Backend : public RenderingBackend {
+public:
+ OpenGL3Backend();
+ virtual ~OpenGL3Backend() ;
+ virtual void BeginFrame() override;
+ virtual void EndFrame() override;
+};
diff --git a/core/src/Entrypoint/Vulkan.cpp b/core/src/Entrypoint/Vulkan.cpp
new file mode 100644
index 0000000..5af1772
--- /dev/null
+++ b/core/src/Entrypoint/Vulkan.cpp
@@ -0,0 +1,13 @@
+#include "Vulkan.hpp"
+
+VulkanBackend::VulkanBackend() {
+ // TODO
+}
+
+void VulkanBackend::BeginFrame() {
+ // TODO
+}
+
+void VulkanBackend::EndFrame() {
+ // TODO
+}
diff --git a/core/src/Entrypoint/Vulkan.hpp b/core/src/Entrypoint/Vulkan.hpp
new file mode 100644
index 0000000..6404806
--- /dev/null
+++ b/core/src/Entrypoint/Vulkan.hpp
@@ -0,0 +1,11 @@
+#pragma once
+
+#include "Entrypoint/Common.hpp"
+
+class VulkanBackend : public RenderingBackend {
+public:
+ VulkanBackend();
+ virtual ~VulkanBackend() = default;
+ virtual void BeginFrame() override;
+ virtual void EndFrame() override;
+};
diff --git a/core/src/Entrypoint/main.cpp b/core/src/Entrypoint/main.cpp
new file mode 100644
index 0000000..3adf757
--- /dev/null
+++ b/core/src/Entrypoint/main.cpp
@@ -0,0 +1,91 @@
+#include "Entrypoint/Common.hpp"
+#include "Entrypoint/DirectX11.hpp"
+#include "Entrypoint/DirectX12.hpp"
+#include "Entrypoint/Metal.hpp"
+#include "Entrypoint/OpenGL2.hpp"
+#include "Entrypoint/OpenGL3.hpp"
+#include "Entrypoint/Vulkan.hpp"
+
+#include <glad/glad.h>
+
+#include <GLFW/glfw3.h>
+#include <imgui.h>
+#include <argparse/argparse.hpp>
+#include <iostream>
+#include <memory>
+#include <string>
+
+using namespace std::literals::string_literals;
+
+int main(int argc, char* argv[]) {
+ argparse::ArgumentParser parser;
+ parser.add_argument("--rendering-backend")
+ .help("Which rendering backend to use. If equals 'default', the preferred API for each platform will be used")
+ .default_value("default"s);
+
+ try {
+ parser.parse_args(argc, argv);
+ } catch (const std::runtime_error& error) {
+ std::cout << error.what() << '\n';
+ std::cout << parser;
+ return -1;
+ }
+
+ std::unique_ptr<RenderingBackend> backend;
+ auto backendOption = parser.get<std::string>("--rendering-backend");
+ if (backendOption == "default") {
+ // TODO better api selection mechanism, use lower tier if higher tier is unavilable instead of bailing
+#if PLATFORM_WIN32
+# if IMGUI_INCLUDE_DX12_BACKEND
+ backend = std::make_unique<DirectX12Backend>();
+# elif IMGUI_INCLUDE_DX11_BACKEND
+ backend = std::make_unique<DirectX11Backend>();
+# elif IMGUI_INCLUDE_VULKAN_BACKEND
+ backend = std::make_unique<VulkanBackend>();
+# elif IMGUI_INCLUDE_OPENGL3_BACKEND
+ backend = std::make_unique<OpenGL3Backend>();
+# elif IMGUI_INCLUDE_OPENGL2_BACKEND
+ backend = std::make_unique<OpenGL2Backend>();
+# endif
+#elif PLATFORM_MACOS
+ backend = std::make_unique<MetalBackend>();
+#elif PLATFORM_LINUX
+# if IMGUI_INCLUDE_VULKAN_BACKEND
+ backend = std::make_unique<VulkanBackend>();
+// # elif IMGUI_INCLUDE_OPENGL3_BACKEND
+// backend = std::make_unique<OpenGL3Backend>();
+# elif IMGUI_INCLUDE_OPENGL2_BACKEND
+ backend = std::make_unique<OpenGL2Backend>();
+# endif
+#endif
+ } else if (backendOption == "opengl2") {
+ backend = std::make_unique<OpenGL2Backend>();
+ } else if (backendOption == "opengl3") {
+ backend = std::make_unique<OpenGL3Backend>();
+ } else if (backendOption == "vulkan") {
+ backend = std::make_unique<VulkanBackend>();
+ } else if (backendOption == "dx11") {
+ backend = std::make_unique<DirectX11Backend>();
+ } else if (backendOption == "dx12") {
+ backend = std::make_unique<DirectX12Backend>();
+ } else if (backendOption == "metal") {
+ backend = std::make_unique<MetalBackend>();
+ } else {
+ std::cout << "Unknown backend '" << backendOption << "'.\n";
+ return -1;
+ }
+
+ auto& io = ImGui::GetIO();
+ io.Fonts->AddFontFromFileTTF("fonts/NotoSansSC-Regular.otf", 18, nullptr, io.Fonts->GetGlyphRangesChineseSimplifiedCommon());
+
+ auto window = backend->GetWindow();
+ bool showDemo = true;
+ while (!glfwWindowShouldClose(window)) {
+ backend->BeginFrame();
+ if (showDemo)
+ ImGui::ShowDemoWindow(&showDemo);
+ backend->EndFrame();
+ }
+
+ return 0;
+}
diff --git a/core/src/UI/Export.cpp b/core/src/UI/Export.cpp
new file mode 100644
index 0000000..d6b26dc
--- /dev/null
+++ b/core/src/UI/Export.cpp
@@ -0,0 +1 @@
+#include "Export.hpp"
diff --git a/core/src/UI/Export.hpp b/core/src/UI/Export.hpp
new file mode 100644
index 0000000..6f70f09
--- /dev/null
+++ b/core/src/UI/Export.hpp
@@ -0,0 +1 @@
+#pragma once