Compare commits
2 Commits
fe4c49d092
...
cbcd699ab0
| Author | SHA1 | Date | |
|---|---|---|---|
| cbcd699ab0 | |||
| ff27caab4f |
@@ -20,14 +20,29 @@ cmake_minimum_required(VERSION 3.30)
|
||||
project(fennec)
|
||||
|
||||
# External dependencies should be loaded here
|
||||
|
||||
# CppTrace is a dependency of the project, added as a git submodule
|
||||
add_subdirectory(external/cpptrace)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 23)
|
||||
set(CMAKE_C_STANDARD 23)
|
||||
set(FENNEC_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
add_custom_target(fennec-dependencies
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "Running dependencies."
|
||||
COMMENT "Running dependencies."
|
||||
)
|
||||
|
||||
macro(fennec_add_sources)
|
||||
list(APPEND FENNEC_EXTRA_SOURCES ${ARGN})
|
||||
endmacro()
|
||||
|
||||
macro(fennec_add_definitions)
|
||||
list(APPEND FENNEC_COMPILE_DEFINITIONS ${ARGN})
|
||||
endmacro()
|
||||
|
||||
macro(fennec_add_link_libraries)
|
||||
list(APPEND FENNEC_LINK_LIBRARIES ${ARGN})
|
||||
endmacro()
|
||||
|
||||
# include scripts
|
||||
include("${FENNEC_SOURCE_DIR}/cmake/version.cmake")
|
||||
include("${FENNEC_SOURCE_DIR}/cmake/platform.cmake")
|
||||
@@ -85,6 +100,7 @@ add_library(fennec STATIC
|
||||
include/fennec/containers/set.h
|
||||
include/fennec/containers/traversal.h
|
||||
include/fennec/containers/tuple.h
|
||||
include/fennec/containers/variant.h
|
||||
|
||||
|
||||
include/fennec/containers/detail/_tuple.h
|
||||
@@ -138,11 +154,6 @@ add_library(fennec STATIC
|
||||
|
||||
include/fennec/memory/detail/_ptr_traits.h
|
||||
|
||||
# CONCURRENCY ==========================================================================================================
|
||||
include/fennec/concurrency/thread.h
|
||||
include/fennec/concurrency/mutex.h
|
||||
include/fennec/concurrency/atomic.h
|
||||
|
||||
# DEBUG ================================================================================================================
|
||||
source/debug/assert_impl.cpp
|
||||
|
||||
@@ -203,15 +214,15 @@ add_library(fennec STATIC
|
||||
include/fennec/platform/interface/platform.h source/platform/interface/platform.cpp
|
||||
include/fennec/platform/interface/display.h source/platform/interface/display.cpp
|
||||
include/fennec/platform/interface/gfxcontext.h
|
||||
include/fennec/platform/interface/gfxsurface.h
|
||||
|
||||
|
||||
# EXTRA SOURCES ========================================================================================================
|
||||
|
||||
${FENNEC_EXTRA_SOURCES}
|
||||
include/fennec/containers/variant.h
|
||||
)
|
||||
|
||||
add_dependencies(fennec metaprogramming)
|
||||
add_dependencies(fennec metaprogramming fennec-dependencies)
|
||||
|
||||
target_compile_definitions(fennec PUBLIC
|
||||
${FENNEC_COMPILE_DEFINITIONS}
|
||||
@@ -223,8 +234,9 @@ target_link_options(fennec PRIVATE ${FENNEC_PRIVATE_LINK_OPTIONS}) # Do not comp
|
||||
# This implementation is designed to be as readable as possible, and expose information that would otherwise be obfuscated
|
||||
|
||||
target_link_libraries(fennec PRIVATE
|
||||
cpptrace::cpptrace
|
||||
${FENNEC_LINK_LIBRARIES}
|
||||
|
||||
cpptrace::cpptrace
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
# Readings
|
||||
|
||||
Here is a list of relevant books and articles on various concepts related to
|
||||
Here is a list of relevant books and articles on various concepts related to
|
||||
developing a game engine and its subsystems.
|
||||
|
||||
- Game Engine Architecture, Ed. 3 – Jason Gregory
|
||||
|
||||
@@ -90,7 +90,7 @@ fennec Standards:
|
||||
immediate events to listeners so that outside functionality may decide how to handle the impending crash.
|
||||
In Debug Mode there is nothing that can be done to stop the crash, as soon as the branch finishes,
|
||||
`abort()` will be called.
|
||||
|
||||
|
||||
|
||||
<br>
|
||||
|
||||
|
||||
@@ -22,4 +22,4 @@ add_compile_options("-mxsave" "-Wall" "-Wextra" "-pedantic" "-Werror")
|
||||
|
||||
set(FENNEC_PRIVATE_LINK_OPTIONS "-nostdlib" "-fno-exceptions" "-fno-rtti" "-fdiagnostics-all-candidates")
|
||||
|
||||
list(APPEND FENNEC_COMPILE_DEFINITIONS FENNEC_COMPILER_GCC=1 FENNEC_NO_INLINE=[[gnu::noinline]])
|
||||
list(APPEND FENNEC_COMPILE_DEFINITIONS _GLIBCXX_INCLUDE_NEXT_C_HEADERS FENNEC_COMPILER_GCC=1 FENNEC_NO_INLINE=[[gnu::noinline]])
|
||||
@@ -23,13 +23,13 @@ macro(fennec_check_platform)
|
||||
include("${FENNEC_SOURCE_DIR}/cmake/unix.cmake")
|
||||
|
||||
# compile definitions
|
||||
list(APPEND FENNEC_COMPILE_DEFINITIONS
|
||||
fennec_add_definitions(
|
||||
FENNEC_PLATFORM_NAME="Linux"
|
||||
FENNEC_PLATFORM_LINUX=1
|
||||
)
|
||||
|
||||
# extra source files
|
||||
list(APPEND FENNEC_EXTRA_SOURCES
|
||||
fennec_add_sources(
|
||||
include/fennec/platform/linux/platform.h source/platform/linux/platform.cpp
|
||||
)
|
||||
|
||||
|
||||
@@ -27,8 +27,8 @@ endif()
|
||||
|
||||
if(TARGET OpenGL::GL AND TARGET GLEW::GLEW)
|
||||
message(STATUS "Found OpenGL: ${OPENGL_gl_LIBRARY}")
|
||||
list(APPEND FENNEC_LINK_LIBRARIES OpenGL::GL GLEW::GLEW)
|
||||
list(APPEND FENNEC_COMPILE_DEFINITIONS FENNEC_GRAPHICS_OPENGL=1)
|
||||
fennec_add_link_libraries(OpenGL::GL GLEW::GLEW)
|
||||
fennec_add_definitions(FENNEC_GRAPHICS_OPENGL=1)
|
||||
else()
|
||||
message(FATAL_ERROR "No Suitable OpenGL implementation found.")
|
||||
endif()
|
||||
@@ -39,15 +39,19 @@ if(FENNEC_GRAPHICS_WANT_EGL)
|
||||
endif()
|
||||
|
||||
message(STATUS "Found EGL: ${OPENGL_egl_LIBRARY}")
|
||||
list(APPEND FENNEC_LINK_LIBRARIES OpenGL::EGL)
|
||||
list(APPEND FENNEC_COMPILE_DEFINITIONS FENNEC_GRAPHICS_EGL=1)
|
||||
list(APPEND FENNEC_EXTRA_SOURCES
|
||||
|
||||
fennec_add_link_libraries(OpenGL::EGL)
|
||||
fennec_add_definitions(FENNEC_GRAPHICS_EGL=1)
|
||||
|
||||
fennec_add_sources(
|
||||
include/fennec/platform/opengl/lib/fwd.h
|
||||
include/fennec/platform/opengl/lib/enum.h
|
||||
include/fennec/platform/opengl/lib/buffer.h
|
||||
include/fennec/platform/opengl/lib/texture.h
|
||||
include/fennec/platform/opengl/lib/vertex_array.h
|
||||
|
||||
include/fennec/platform/opengl/egl/fwd.h
|
||||
include/fennec/platform/opengl/egl/context.h source/platform/opengl/egl/context.cpp
|
||||
include/fennec/platform/opengl/egl/surface.h source/platform/opengl/egl/surface.cpp
|
||||
)
|
||||
endif()
|
||||
@@ -19,11 +19,11 @@
|
||||
# generic unix functionality
|
||||
|
||||
# compile definitions
|
||||
list(APPEND FENNEC_COMPILE_DEFINITIONS
|
||||
fennec_add_definitions(
|
||||
FENNEC_PLATFORM_UNIX=1
|
||||
)
|
||||
|
||||
# extra source files
|
||||
list(APPEND FENNEC_EXTRA_SOURCES
|
||||
fennec_add_sources(
|
||||
include/fennec/platform/unix/platform.h source/platform/unix/platform.cpp
|
||||
)
|
||||
@@ -19,6 +19,20 @@
|
||||
# https://gist.github.com/mariobadr/acc3c8adf4b4e722705be38c3deac59a
|
||||
# this script finds libwayland and dependencies
|
||||
|
||||
# some of this code is based on SDL3's use of wayland-scanner
|
||||
|
||||
macro(fennec_wayland_get_header _SCANNER _XML _FILE)
|
||||
set(_WAYLAND_PROT_H_CODE "${WAYLAND_HEADERS_DIR}/${_FILE}-client-protocols.h")
|
||||
|
||||
add_custom_command(
|
||||
TARGET fennec-dependencies PRE_BUILD
|
||||
COMMAND ${_SCANNER}
|
||||
ARGS client-header "${_XML}" "${_WAYLAND_PROT_H_CODE}"
|
||||
)
|
||||
|
||||
fennec_add_sources(${_WAYLAND_PROT_H_CODE})
|
||||
endmacro()
|
||||
|
||||
macro(fennec_check_wayland)
|
||||
set(WAYLAND_CLIENT_FOUND 0)
|
||||
|
||||
@@ -30,6 +44,7 @@ macro(fennec_check_wayland)
|
||||
WAYLAND_CLIENT_LIBRARY
|
||||
NAMES wayland-client libwayland-client
|
||||
)
|
||||
find_program(WAYLAND_SCANNER NAMES wayland-scanner)
|
||||
|
||||
# EGL is required
|
||||
find_path(
|
||||
@@ -41,13 +56,29 @@ macro(fennec_check_wayland)
|
||||
NAMES wayland-egl libwayland-egl
|
||||
)
|
||||
|
||||
if( (WAYLAND_CLIENT_INCLUDE_DIR AND WAYLAND_CLIENT_LIBRARY)
|
||||
if( (WAYLAND_CLIENT_INCLUDE_DIR AND WAYLAND_CLIENT_LIBRARY AND WAYLAND_SCANNER)
|
||||
AND (WAYLAND_EGL_INCLUDE_DIR AND WAYLAND_EGL_LIBRARY))
|
||||
message(STATUS "Found Wayland: ${WAYLAND_CLIENT_LIBRARY}")
|
||||
|
||||
set(WAYLAND_PROTOCOLS_DIR ${FENNEC_SOURCE_DIR}/include/fennec/platform/linux/wayland/lib/protocols)
|
||||
set(WAYLAND_HEADERS_DIR ${FENNEC_SOURCE_DIR}/include/fennec/platform/linux/wayland/lib/headers)
|
||||
|
||||
# Search for base protocol xml
|
||||
find_file(WAYLAND_PROTOCOL NAMES wayland.xml PATHS /usr/share/wayland /usr/share/wayland-protocols)
|
||||
file(COPY ${WAYLAND_PROTOCOL} DESTINATION ${WAYLAND_PROTOCOLS_DIR})
|
||||
|
||||
# include sub-dependencies
|
||||
include("${FENNEC_SOURCE_DIR}/cmake/xkb.cmake")
|
||||
fennec_check_xkb()
|
||||
|
||||
# generate protocols, based on SDL3
|
||||
file(GLOB WAYLAND_PROTOCOLS_XML RELATIVE "${WAYLAND_PROTOCOLS_DIR}" "${WAYLAND_PROTOCOLS_DIR}/*.xml")
|
||||
foreach(_XML IN LISTS WAYLAND_PROTOCOLS_XML)
|
||||
get_filename_component(_FILE ${_XML} NAME_WLE)
|
||||
fennec_wayland_get_header("${WAYLAND_SCANNER}" "${WAYLAND_PROTOCOLS_DIR}/${_XML}" "${_FILE}")
|
||||
endforeach()
|
||||
|
||||
# Add sources and libraries
|
||||
get_filename_component(
|
||||
WAYLAND_CLIENT_LIBRARY
|
||||
${WAYLAND_CLIENT_LIBRARY}
|
||||
@@ -63,19 +94,19 @@ macro(fennec_check_wayland)
|
||||
set(WAYLAND_EGL_FOUND 1)
|
||||
set(FENNEC_GRAPHICS_WANT_EGL 1)
|
||||
|
||||
list(APPEND FENNEC_EXTRA_SOURCES
|
||||
fennec_add_sources(
|
||||
# Dynamic Library Files
|
||||
include/fennec/platform/linux/wayland/lib/fwd.h
|
||||
include/fennec/platform/linux/wayland/lib/sym.h
|
||||
include/fennec/platform/linux/wayland/lib/wayland-client.h
|
||||
include/fennec/platform/linux/wayland/lib/wayland-util.h
|
||||
include/fennec/platform/linux/wayland/lib/wayland.h
|
||||
include/fennec/platform/linux/wayland/lib/loader.h source/platform/linux/wayland/lib/loader.cpp
|
||||
|
||||
# Fennec Files
|
||||
include/fennec/platform/linux/wayland/display.h source/platform/linux/wayland/display.cpp
|
||||
include/fennec/platform/linux/wayland/window.h source/platform/linux/wayland/window.cpp
|
||||
)
|
||||
|
||||
list(APPEND FENNEC_COMPILE_DEFINITIONS
|
||||
fennec_add_definitions(
|
||||
FENNEC_HAS_WAYLAND=1
|
||||
FENNEC_LIB_WAYLAND="${WAYLAND_CLIENT_LIBRARY}"
|
||||
FENNEC_LIB_WAYLAND_EGL="${WAYLAND_EGL_LIBRARY}"
|
||||
|
||||
@@ -41,7 +41,7 @@ macro(fennec_check_xkb)
|
||||
|
||||
set(XKB_FOUND 1)
|
||||
|
||||
list(APPEND FENNEC_EXTRA_SOURCES
|
||||
fennec_add_sources(
|
||||
# Dynamic Library Files
|
||||
include/fennec/platform/linux/xkb/lib/fwd.h
|
||||
include/fennec/platform/linux/xkb/lib/sym.h
|
||||
@@ -51,7 +51,7 @@ macro(fennec_check_xkb)
|
||||
# Fennec files
|
||||
)
|
||||
|
||||
list(APPEND FENNEC_COMPILE_DEFINITIONS
|
||||
fennec_add_definitions(
|
||||
FENNEC_HAS_XKB=1
|
||||
FENNEC_LIB_XKB="${XKB_LIBRARY}"
|
||||
)
|
||||
|
||||
2
external/cpptrace
vendored
2
external/cpptrace
vendored
Submodule external/cpptrace updated: 69179bbe8f...787d8af6f6
@@ -396,10 +396,10 @@ class GraphPrinter:
|
||||
|
||||
class Iterator:
|
||||
def __init__(self, val):
|
||||
self.node_pool = val['_node_pool']['_table']['_alloc']['_data']
|
||||
self.max_nodes = val['_node_pool']['_table']['_alloc']['_capacity']
|
||||
self.conn_map = val['_conn_map']['_alloc']['_data']
|
||||
self.max_conn = val['_conn_map']['_size']
|
||||
self.node_pool = val['_vertex_pool']['_table']['_alloc']['_data']
|
||||
self.max_nodes = val['_vertex_pool']['_table']['_alloc']['_capacity']
|
||||
self.conn_map = val['_edge_map']['_alloc']['_data']
|
||||
self.max_conn = val['_edge_map']['_size']
|
||||
self.index = 0
|
||||
|
||||
def __iter__(self):
|
||||
@@ -447,7 +447,7 @@ class GraphPrinter:
|
||||
|
||||
def __init__(self, val):
|
||||
self.val = val
|
||||
self.size = val['_node_pool']['_size']
|
||||
self.size = val['_vertex_pool']['_size']
|
||||
|
||||
def to_string(self):
|
||||
if self.size == 0:
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
// =====================================================================================================================
|
||||
// fennec, a free and open source game engine
|
||||
// Copyright © 2025 Medusa Slockbower
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
// =====================================================================================================================
|
||||
|
||||
#ifndef FENNEC_CONCURRENCY_THREAD_H
|
||||
#define FENNEC_CONCURRENCY_THREAD_H
|
||||
|
||||
#endif // FENNEC_CONCURRENCY_THREAD_H
|
||||
@@ -149,7 +149,7 @@ public:
|
||||
///
|
||||
/// \returns The number of edges in the graph
|
||||
constexpr size_t num_edges() const {
|
||||
return _conn_pool.size();
|
||||
return _edge_pool.size();
|
||||
}
|
||||
|
||||
///
|
||||
@@ -170,7 +170,7 @@ public:
|
||||
/// \param b The second vertex
|
||||
/// \returns `true` if the edge exists, `false` otherwise
|
||||
constexpr bool exists(size_t a, size_t b) const {
|
||||
return _conn_map[a][b] != nullptr;
|
||||
return _edge_map[a][b] != nullptr;
|
||||
}
|
||||
|
||||
///
|
||||
@@ -189,8 +189,8 @@ public:
|
||||
/// \param b The second vertex
|
||||
/// \returns `true` if both edges exist, `false` otherwise
|
||||
constexpr bool is_undirected(size_t a, size_t b) const {
|
||||
const auto* e0 = _conn_map[a][b];
|
||||
const auto* e1 = _conn_map[b][a];
|
||||
const auto* e0 = _edge_map[a][b];
|
||||
const auto* e1 = _edge_map[b][a];
|
||||
if (not (e0 != nullptr && e1 != nullptr)) {
|
||||
return false;
|
||||
}
|
||||
@@ -232,9 +232,9 @@ public:
|
||||
if (empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
edge_t* it = _conn_map[a][b];
|
||||
edge_t* it = _edge_map[a][b];
|
||||
if (it) {
|
||||
return _conn_pool[*it];
|
||||
return _edge_pool[*it];
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
@@ -248,9 +248,9 @@ public:
|
||||
if (empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
const edge_t* it = _conn_map[a][b];
|
||||
const edge_t* it = _edge_map[a][b];
|
||||
if (it) {
|
||||
return _conn_pool[*it];
|
||||
return _edge_pool[*it];
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
@@ -261,10 +261,10 @@ public:
|
||||
/// \returns A list containing all vertices `x` with edges from `vertex` to `x...`
|
||||
list<size_t> outgoing(size_t vertex) {
|
||||
list<size_t> res;
|
||||
if (empty() || vertex >= _conn_map.size()) {
|
||||
if (empty() || vertex >= _edge_map.size()) {
|
||||
return res;
|
||||
}
|
||||
for (const auto& it : _conn_map[vertex]) {
|
||||
for (const auto& it : _edge_map[vertex]) {
|
||||
res.push_back(it.first);
|
||||
}
|
||||
return res;
|
||||
@@ -276,11 +276,11 @@ public:
|
||||
/// \returns A list containing all vertices `x` with edges from `x...` to `vertex`
|
||||
list<size_t> incoming(size_t vertex) {
|
||||
list<size_t> res;
|
||||
if (empty() || vertex >= _conn_map.size()) {
|
||||
if (empty() || vertex >= _edge_map.size()) {
|
||||
return res;
|
||||
}
|
||||
for (size_t n = 0; n < _conn_map.size(); ++n) {
|
||||
if (_conn_map[n][vertex]) {
|
||||
for (size_t n = 0; n < _edge_map.size(); ++n) {
|
||||
if (_edge_map[n][vertex]) {
|
||||
res.push_back(n);
|
||||
}
|
||||
}
|
||||
@@ -293,11 +293,11 @@ public:
|
||||
/// \returns A list containing all vertices `x` that have symmetric edges with `vertex`
|
||||
list<size_t> symmetric(size_t vertex) {
|
||||
list<size_t> res;
|
||||
if (empty() || vertex >= _conn_map.size()) {
|
||||
if (empty() || vertex >= _edge_map.size()) {
|
||||
return res;
|
||||
}
|
||||
for (const auto& it : _conn_map[vertex]) {
|
||||
if (_conn_map[it.first][vertex]) {
|
||||
for (const auto& it : _edge_map[vertex]) {
|
||||
if (_edge_map[it.first][vertex]) {
|
||||
res.push_back(it.first);
|
||||
}
|
||||
}
|
||||
@@ -314,11 +314,11 @@ public:
|
||||
/// \returns A list containing all vertices `x` that have symmetric edges with `vertex`
|
||||
list<size_t> undirected(size_t vertex) {
|
||||
list<size_t> res;
|
||||
if (empty() || vertex >= _conn_map.size()) {
|
||||
if (empty() || vertex >= _edge_map.size()) {
|
||||
return res;
|
||||
}
|
||||
for (const auto& it : _conn_map[vertex]) {
|
||||
const auto* at = _conn_map[it.first][vertex];
|
||||
for (const auto& it : _edge_map[vertex]) {
|
||||
const auto* at = _edge_map[it.first][vertex];
|
||||
if (at != nullptr && *at == it.second) {
|
||||
res.push_back(it.first);
|
||||
}
|
||||
@@ -332,10 +332,10 @@ public:
|
||||
/// \param vertex The id of the vertex
|
||||
/// \returns A pointer to a map containing edges mapped from this vertex
|
||||
const auto* edges(size_t vertex) {
|
||||
if (empty() || vertex >= _conn_map.size()) {
|
||||
if (empty() || vertex >= _edge_map.size()) {
|
||||
return nullptr;
|
||||
}
|
||||
return &_conn_map[vertex];
|
||||
return &_edge_map[vertex];
|
||||
}
|
||||
|
||||
/// @}
|
||||
@@ -392,19 +392,19 @@ public:
|
||||
return;
|
||||
}
|
||||
|
||||
if (_conn_map.size() < _vertex_pool.capacity()) {
|
||||
_conn_map.resize(_vertex_pool.capacity());
|
||||
if (_edge_map.size() < _vertex_pool.capacity()) {
|
||||
_edge_map.resize(_vertex_pool.capacity());
|
||||
}
|
||||
|
||||
auto it = _conn_map[a][b];
|
||||
auto it = _edge_map[a][b];
|
||||
size_t conn;
|
||||
if (it != nullptr) {
|
||||
conn = *it;
|
||||
_conn_pool[conn] = vertex_t(fennec::forward<ArgsT>(args)...);
|
||||
_edge_pool[conn] = vertex_t(fennec::forward<ArgsT>(args)...);
|
||||
} else {
|
||||
conn = _conn_pool.emplace(fennec::forward<ArgsT>(args)...);
|
||||
conn = _edge_pool.emplace(fennec::forward<ArgsT>(args)...);
|
||||
}
|
||||
_conn_map[a].emplace(b, conn);
|
||||
_edge_map[a].emplace(b, conn);
|
||||
}
|
||||
|
||||
///
|
||||
@@ -419,21 +419,21 @@ public:
|
||||
return;
|
||||
}
|
||||
|
||||
if (_conn_map.size() < _vertex_pool.capacity()) {
|
||||
_conn_map.resize(_vertex_pool.capacity());
|
||||
if (_edge_map.size() < _vertex_pool.capacity()) {
|
||||
_edge_map.resize(_vertex_pool.capacity());
|
||||
}
|
||||
|
||||
auto it = _conn_map[a][b];
|
||||
auto it = _edge_map[a][b];
|
||||
size_t conn;
|
||||
if (it != nullptr) {
|
||||
conn = *it;
|
||||
_conn_pool[conn] = vertex_t(fennec::forward<ArgsT>(args)...);
|
||||
_edge_pool[conn] = vertex_t(fennec::forward<ArgsT>(args)...);
|
||||
} else {
|
||||
conn = _conn_pool.emplace(fennec::forward<ArgsT>(args)...);
|
||||
conn = _edge_pool.emplace(fennec::forward<ArgsT>(args)...);
|
||||
}
|
||||
|
||||
_conn_map[a].emplace(b, conn);
|
||||
_conn_map[b].emplace(a, conn);
|
||||
_edge_map[a].emplace(b, conn);
|
||||
_edge_map[b].emplace(a, conn);
|
||||
}
|
||||
|
||||
///
|
||||
@@ -443,20 +443,20 @@ public:
|
||||
constexpr void cut_edge(size_t a, size_t b) {
|
||||
|
||||
// Find the edge object
|
||||
const auto* it = _conn_map[a][b];
|
||||
const auto* it = _edge_map[a][b];
|
||||
if (not it) {
|
||||
return;
|
||||
}
|
||||
size_t c = *it;
|
||||
|
||||
// Check if undirected
|
||||
const auto* at = _conn_map[b][a];
|
||||
const auto* at = _edge_map[b][a];
|
||||
if (not at || *at != c) {
|
||||
_conn_pool.erase(c);
|
||||
_edge_pool.erase(c);
|
||||
}
|
||||
|
||||
// Erase the edge mapping
|
||||
_conn_map[a].erase(b);
|
||||
_edge_map[a].erase(b);
|
||||
}
|
||||
|
||||
///
|
||||
@@ -464,15 +464,15 @@ public:
|
||||
/// \param a The first vertex id
|
||||
/// \param b The second vertex id
|
||||
constexpr void cut_edge2(size_t a, size_t b) {
|
||||
const auto* ita = _conn_map[a][b];
|
||||
const auto* itb = _conn_map[a][b];
|
||||
const auto* ita = _edge_map[a][b];
|
||||
const auto* itb = _edge_map[a][b];
|
||||
if (not (ita || itb)) {
|
||||
return;
|
||||
}
|
||||
if (ita) _conn_pool.erase(*ita);
|
||||
if (itb) _conn_pool.erase(*itb);
|
||||
_conn_map[a].erase(b);
|
||||
_conn_map[b].erase(a);
|
||||
if (ita) _edge_pool.erase(*ita);
|
||||
if (itb) _edge_pool.erase(*itb);
|
||||
_edge_map[a].erase(b);
|
||||
_edge_map[b].erase(a);
|
||||
}
|
||||
|
||||
///
|
||||
@@ -491,8 +491,8 @@ public:
|
||||
/// \brief Clear the graph, destructing all vertices and edges.
|
||||
void clear() {
|
||||
_vertex_pool.clear();
|
||||
_conn_pool.clear();
|
||||
_conn_map.clear();
|
||||
_edge_pool.clear();
|
||||
_edge_map.clear();
|
||||
}
|
||||
|
||||
/// @}
|
||||
@@ -503,8 +503,8 @@ public:
|
||||
|
||||
private:
|
||||
vertex_pool_t _vertex_pool;
|
||||
edge_pool_t _conn_pool;
|
||||
edge_map_t _conn_map;
|
||||
edge_pool_t _edge_pool;
|
||||
edge_map_t _edge_map;
|
||||
|
||||
template<typename...ArgsT>
|
||||
size_t _insert(ArgsT&&...args) {
|
||||
|
||||
@@ -42,6 +42,22 @@ FENNEC_NO_INLINE uint64_t typeuuid() {
|
||||
return id = detail::_typeuuid<RootT>();
|
||||
}
|
||||
|
||||
template<typename RootT = void>
|
||||
struct typed {
|
||||
public:
|
||||
const uint64_t type;
|
||||
|
||||
template<typename TypeT>
|
||||
bool is_type() const {
|
||||
return type == typeuuid<TypeT, RootT>();
|
||||
}
|
||||
|
||||
template<typename TypeT>
|
||||
typed(TypeT*)
|
||||
: type(typeuuid<TypeT, RootT>()) {
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // FENNEC_LANG_TYPEUUID_H
|
||||
|
||||
@@ -55,7 +55,7 @@ public:
|
||||
/// \param str the cstring to convert
|
||||
path(const cstring& str)
|
||||
: _str(str) {
|
||||
while (not _str.empty() && _str[_str.size() - 1] == '/') {
|
||||
if (str.size() > 2 && str[str.size() - 1] == '/') {
|
||||
_str = _str.substring(0, str.size() - 1);
|
||||
}
|
||||
}
|
||||
@@ -64,8 +64,8 @@ public:
|
||||
/// \brief String Conversion Constructor
|
||||
/// \param str the string to convert
|
||||
path(const string& str)
|
||||
: _str(str) {
|
||||
while (_str[_str.size() - 1] == '/') {
|
||||
: _str(str) {
|
||||
if (str.size() > 2 && str[str.size() - 1] == '/') {
|
||||
_str = _str.substring(0, str.size() - 1);
|
||||
}
|
||||
}
|
||||
@@ -85,6 +85,16 @@ public:
|
||||
|
||||
// Assignment Operators ================================================================================================
|
||||
|
||||
///
|
||||
/// \brief C-String Assignment Operator
|
||||
/// \param str the cstring to assign
|
||||
/// \returns a reference to `this` after assigning `p`
|
||||
template<size_t n>
|
||||
path& operator=(const char (&str)[n]) {
|
||||
_str = str;
|
||||
return *this;
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief C-String Assignment Operator
|
||||
/// \param p the cstring to assign
|
||||
@@ -177,7 +187,7 @@ public:
|
||||
#else
|
||||
size_t start = _str.size() - 1;
|
||||
start = _str[start] == '/' ? start - 1 : start;
|
||||
return _str.substring(0, _str.rfind('/', start));
|
||||
return path(_str.substring(0, _str.rfind('/', start)));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
namespace fennec
|
||||
{
|
||||
|
||||
class display
|
||||
class display : public typed<display>
|
||||
{
|
||||
public:
|
||||
struct pixel_format {
|
||||
@@ -42,7 +42,7 @@ public:
|
||||
virtual bool connected() const = 0;
|
||||
virtual ~display();
|
||||
|
||||
virtual window* create_window() = 0;
|
||||
virtual window* create_window(window* parent) = 0;
|
||||
|
||||
const pixel_format& get_color_format() const {
|
||||
return _config.format;
|
||||
@@ -55,7 +55,6 @@ public:
|
||||
gfxcontext* get_context() { return _context; }
|
||||
|
||||
const string name;
|
||||
const uint64_t uuid;
|
||||
|
||||
protected:
|
||||
platform* _platform;
|
||||
@@ -63,9 +62,9 @@ protected:
|
||||
config _config;
|
||||
|
||||
template<typename DisplayT>
|
||||
explicit display(platform* platform, const cstring& name, DisplayT*)
|
||||
: name(name)
|
||||
, uuid(typeuuid<DisplayT>())
|
||||
explicit display(platform* platform, const cstring& name, DisplayT* type)
|
||||
: typed(type)
|
||||
, name(name)
|
||||
, _platform(platform)
|
||||
, _context(nullptr)
|
||||
, _config {
|
||||
|
||||
@@ -22,33 +22,39 @@
|
||||
#include <fennec/langproc/strings/string.h>
|
||||
#include <fennec/lang/typeuuid.h>
|
||||
#include <fennec/platform/interface/fwd.h>
|
||||
#include <fennec/platform/interface/window.h>
|
||||
|
||||
namespace fennec
|
||||
{
|
||||
|
||||
class gfxcontext {
|
||||
class gfxcontext : public typed<gfxcontext> {
|
||||
public:
|
||||
const string name;
|
||||
const uint64_t uuid;
|
||||
|
||||
virtual bool connected() = 0;
|
||||
virtual const cstring& get_name() = 0;
|
||||
virtual int32_t get_version_major() = 0;
|
||||
virtual int32_t get_version_minor() = 0;
|
||||
virtual int32_t get_context_version() = 0;
|
||||
virtual const cstring& get_context_name() = 0;
|
||||
virtual int32_t get_version() = 0;
|
||||
|
||||
virtual bool check_extension(const cstring& ext) = 0;
|
||||
virtual void make_current(gfxsurface* surface) = 0;
|
||||
|
||||
virtual gfxsurface* create_surface(window* window) = 0;
|
||||
|
||||
virtual ~gfxcontext() = default;
|
||||
|
||||
display* get_display() {
|
||||
return _display;
|
||||
}
|
||||
|
||||
protected:
|
||||
display* _display;
|
||||
|
||||
template<typename ContextT>
|
||||
gfxcontext(display* display, const cstring& name, ContextT*)
|
||||
: name(name)
|
||||
, uuid(typeuuid<ContextT>())
|
||||
gfxcontext(display* display, const cstring& name, ContextT* type)
|
||||
: typed(type)
|
||||
, name(name)
|
||||
, _display(display) {
|
||||
}
|
||||
};
|
||||
|
||||
76
include/fennec/platform/interface/gfxsurface.h
Normal file
76
include/fennec/platform/interface/gfxsurface.h
Normal file
@@ -0,0 +1,76 @@
|
||||
// =====================================================================================================================
|
||||
// fennec, a free and open source game engine
|
||||
// Copyright © 2025 Medusa Slockbower
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
// =====================================================================================================================
|
||||
|
||||
///
|
||||
/// \file gfxsurface.h
|
||||
/// \brief
|
||||
///
|
||||
///
|
||||
/// \details
|
||||
/// \author Medusa Slockbower
|
||||
///
|
||||
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||
///
|
||||
///
|
||||
|
||||
#ifndef FENNEC_PLATFORM_INTERFACE_GFXSURFACE_H
|
||||
#define FENNEC_PLATFORM_INTERFACE_GFXSURFACE_H
|
||||
|
||||
#include <fennec/lang/types.h>
|
||||
#include <fennec/lang/typeuuid.h>
|
||||
#include <fennec/platform/interface/fwd.h>
|
||||
#include <fennec/platform/interface/window.h>
|
||||
|
||||
namespace fennec
|
||||
{
|
||||
|
||||
class gfxsurface : public typed<gfxsurface> {
|
||||
public:
|
||||
virtual ~gfxsurface() = default;
|
||||
|
||||
virtual void resize(size_t width, size_t height) {
|
||||
_width = width;
|
||||
_height = height;
|
||||
}
|
||||
|
||||
gfxcontext* get_context() {
|
||||
return _context;
|
||||
}
|
||||
|
||||
window* get_window() {
|
||||
return _window;
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
gfxcontext* _context;
|
||||
window* _window;
|
||||
size_t _width, _height;
|
||||
|
||||
template<typename SurfaceT>
|
||||
gfxsurface(gfxcontext* ctx, window* window, SurfaceT* type)
|
||||
: typed(type)
|
||||
, _context(ctx)
|
||||
, _window(window)
|
||||
, _width(window->get_width()), _height(window->get_height()) {
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // FENNEC_PLATFORM_INTERFACE_GFXSURFACE_H
|
||||
@@ -59,13 +59,12 @@
|
||||
namespace fennec
|
||||
{
|
||||
|
||||
class platform {
|
||||
class platform : public typed<platform> {
|
||||
public:
|
||||
using shared_object = struct shared_object;
|
||||
using symbol = void*;
|
||||
|
||||
const string name;
|
||||
const uint64_t uuid;
|
||||
|
||||
virtual ~platform() = default;
|
||||
|
||||
@@ -81,9 +80,9 @@ public:
|
||||
|
||||
protected:
|
||||
template<typename PlatformT>
|
||||
explicit platform(const cstring& name, PlatformT*)
|
||||
: name(name)
|
||||
, uuid(typeuuid<PlatformT>()) {
|
||||
explicit platform(const cstring& name, PlatformT* type)
|
||||
: typed(type)
|
||||
, name(name) {
|
||||
auto& globals = _get_globals();
|
||||
assertf(globals.singleton == nullptr, "Conflicting Platform Definitions.");
|
||||
globals.singleton = this;
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <fennec/containers/optional.h>
|
||||
#include <fennec/langproc/strings/string.h>
|
||||
#include <fennec/platform/interface/fwd.h>
|
||||
#include <fennec/platform/linux/wayland/display.h>
|
||||
|
||||
namespace fennec
|
||||
{
|
||||
@@ -29,7 +30,7 @@ namespace fennec
|
||||
///
|
||||
/// \brief interface for handling windows
|
||||
/// \details the interface makes no guarantees about the bit-depth and is completely dependent on the implementation.
|
||||
class window {
|
||||
class window : public typed<window> {
|
||||
public:
|
||||
enum class fullscreen_mode {
|
||||
windowed = 0,
|
||||
@@ -53,6 +54,8 @@ public:
|
||||
fullscreen_mode fullscreen;
|
||||
};
|
||||
|
||||
virtual ~window() = default;
|
||||
|
||||
virtual bool running() = 0;
|
||||
virtual void configure(const config& config) = 0;
|
||||
virtual bool initialize(bool modal) = 0;
|
||||
@@ -63,7 +66,7 @@ public:
|
||||
|
||||
virtual bool set_width(size_t w) = 0;
|
||||
virtual bool set_height(size_t h) = 0;
|
||||
virtual bool set_size(size_t w, size_t h) = 0;
|
||||
virtual bool resize(size_t w, size_t h) = 0;
|
||||
|
||||
virtual bool set_fullscreen_mode(fullscreen_mode mode) = 0;
|
||||
|
||||
@@ -73,6 +76,8 @@ public:
|
||||
virtual bool grab_mouse(bool e) = 0;
|
||||
virtual bool block_screensaver(bool e) = 0;
|
||||
|
||||
virtual struct wl_surface* get_native_handle() = 0;
|
||||
|
||||
bool is_child() const {
|
||||
if (not _config) return false;
|
||||
return _config->flags & flags_child;
|
||||
@@ -91,9 +96,13 @@ public:
|
||||
return _display;
|
||||
}
|
||||
|
||||
const config& get_config() const {
|
||||
return *_config;
|
||||
}
|
||||
|
||||
|
||||
const string& get_title() const {
|
||||
static const string _null = { "null" };
|
||||
static const string _null{"null"};
|
||||
if (not _config) return _null;
|
||||
return _config->title;
|
||||
}
|
||||
@@ -137,13 +146,20 @@ public:
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual ~window() = default;
|
||||
window(display* display, window* parent);
|
||||
template<typename TypeT>
|
||||
window(display* display, window* parent, TypeT* type)
|
||||
: typed(type)
|
||||
, _display(display)
|
||||
, _parent(parent)
|
||||
, _surface(nullptr) {
|
||||
}
|
||||
|
||||
display* _display;
|
||||
window* _parent;
|
||||
optional<config> _config;
|
||||
gfxsurface* _context;
|
||||
gfxsurface* _surface;
|
||||
|
||||
private:
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
@@ -33,13 +33,28 @@ public:
|
||||
bool connected() const override;
|
||||
void* get_native_handle() override { return _handle; }
|
||||
|
||||
window* create_window() override;
|
||||
window* create_window(window* parent) override;
|
||||
|
||||
wl_registry* get_registry() { return _registry; }
|
||||
const wl_registry* get_registry() const { return _registry; }
|
||||
|
||||
wl_compositor* get_compositor() { return _compositor; }
|
||||
const wl_compositor* get_compositor() const { return _compositor; }
|
||||
|
||||
// xdg_wm_base* get_shell() { return _shell; }
|
||||
//const xdg_wm_base* get_shell() const { return _shell; }
|
||||
|
||||
wl_seat* get_seat() { return _seat; }
|
||||
const wl_seat* get_seat() const { return _seat; }
|
||||
|
||||
wl_shm* get_shm() { return _shm; }
|
||||
const wl_shm* get_shm() const { return _shm; }
|
||||
|
||||
private:
|
||||
wl_display* _handle;
|
||||
wl_registry* _registry;
|
||||
wl_compositor* _compositor;
|
||||
wl_shell* _shell;
|
||||
//xdg_wm_base* _shell;
|
||||
wl_seat* _seat;
|
||||
wl_shm* _shm;
|
||||
bool _fifo;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
3248
include/fennec/platform/linux/wayland/lib/protocols/wayland.xml
Normal file
3248
include/fennec/platform/linux/wayland/lib/protocols/wayland.xml
Normal file
File diff suppressed because it is too large
Load Diff
@@ -60,7 +60,7 @@
|
||||
FENNEC_LIB(WAYLAND);
|
||||
|
||||
FENNEC_SYMBOL(void, wl_proxy_marshal, struct wl_proxy*, uint32_t, ...);
|
||||
FENNEC_SYMBOL(struct wl_proxy*, wl_proxy_marshal_flags, struct wl_proxy *proxy, uint32_t opcode, const struct wl_interface *interface, uint32_t version, uint32_t flags, ...);
|
||||
FENNEC_SYMBOL(struct wl_proxy*, wl_proxy_marshal_flags, struct wl_proxy*, uint32_t, const struct wl_interface*, uint32_t, uint32_t, ...);
|
||||
FENNEC_SYMBOL(struct wl_proxy*, wl_proxy_create, struct wl_proxy*, const struct wl_interface*);
|
||||
FENNEC_SYMBOL(void, wl_proxy_destroy, struct wl_proxy*);
|
||||
FENNEC_SYMBOL(int, wl_proxy_add_listener, struct wl_proxy*, void (**)(void), void*);
|
||||
@@ -72,6 +72,11 @@ FENNEC_SYMBOL(const char*, wl_proxy_get_class, st
|
||||
FENNEC_SYMBOL(void, wl_proxy_set_queue, struct wl_proxy*, struct wl_event_queue*);
|
||||
FENNEC_SYMBOL(void*, wl_proxy_create_wrapper, void*);
|
||||
FENNEC_SYMBOL(void, wl_proxy_wrapper_destroy, void*);
|
||||
FENNEC_SYMBOL(struct wl_proxy*, wl_proxy_marshal_constructor, struct wl_proxy*, uint32_t, const struct wl_interface*, ...);
|
||||
FENNEC_SYMBOL(struct wl_proxy*, wl_proxy_marshal_constructor_versioned, struct wl_proxy*, uint32_t, const struct wl_interface*, uint32_t, ...);
|
||||
FENNEC_SYMBOL(void, wl_proxy_set_tag, struct wl_proxy*, const char* const*);
|
||||
FENNEC_SYMBOL(const char* const*, wl_proxy_get_tag, struct wl_proxy*);
|
||||
|
||||
FENNEC_SYMBOL(struct wl_display*, wl_display_connect, const char*);
|
||||
FENNEC_SYMBOL(struct wl_display*, wl_display_connect_to_fd, int);
|
||||
FENNEC_SYMBOL(void, wl_display_disconnect, struct wl_display*);
|
||||
@@ -88,6 +93,7 @@ FENNEC_SYMBOL(int, wl_display_get_error, st
|
||||
FENNEC_SYMBOL(int, wl_display_flush, struct wl_display*);
|
||||
FENNEC_SYMBOL(int, wl_display_roundtrip, struct wl_display*);
|
||||
FENNEC_SYMBOL(struct wl_event_queue*, wl_display_create_queue, struct wl_display*);
|
||||
|
||||
FENNEC_SYMBOL(void, wl_event_queue_destroy, struct wl_event_queue*);
|
||||
FENNEC_SYMBOL(void, wl_log_set_handler_client, wl_log_func_t);
|
||||
FENNEC_SYMBOL(void, wl_list_init, struct wl_list*);
|
||||
@@ -96,10 +102,6 @@ FENNEC_SYMBOL(void, wl_list_remove, st
|
||||
FENNEC_SYMBOL(int, wl_list_length, const struct wl_list*);
|
||||
FENNEC_SYMBOL(int, wl_list_empty, const struct wl_list*);
|
||||
FENNEC_SYMBOL(void, wl_list_insert_list, struct wl_list*, struct wl_list*);
|
||||
FENNEC_SYMBOL(struct wl_proxy*, wl_proxy_marshal_constructor, struct wl_proxy*, uint32_t opcode, const struct wl_interface*interface, ...);
|
||||
FENNEC_SYMBOL(struct wl_proxy*, wl_proxy_marshal_constructor_versioned, struct wl_proxy*proxy, uint32_t opcode, const struct wl_interface*interface, uint32_t version, ...);
|
||||
FENNEC_SYMBOL(void, wl_proxy_set_tag, struct wl_proxy*, const char* const*);
|
||||
FENNEC_SYMBOL(const char* const*, wl_proxy_get_tag, struct wl_proxy*);
|
||||
|
||||
FENNEC_GLOBAL(const struct wl_interface, wl_display_interface);
|
||||
FENNEC_GLOBAL(const struct wl_interface, wl_registry_interface);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,198 +0,0 @@
|
||||
// =====================================================================================================================
|
||||
// fennec, a free and open source game engine
|
||||
// Copyright © 2025 Medusa Slockbower
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
// =====================================================================================================================
|
||||
|
||||
#ifndef FENNEC_PLATFORM_LINUX_WAYLAND_LIB_WAYLAND_UTIL_H
|
||||
#define FENNEC_PLATFORM_LINUX_WAYLAND_LIB_WAYLAND_UTIL_H
|
||||
|
||||
/*
|
||||
* Copyright © 2008 Kristian Høgsberg
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial
|
||||
* portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#if defined(__GNUC__) && __GNUC__ >= 4
|
||||
#define WL_EXPORT __attribute__ ((visibility("default")))
|
||||
#else
|
||||
#define WL_EXPORT
|
||||
#endif
|
||||
|
||||
#if __STDC_VERSION__ >= 202311L
|
||||
#define WL_DEPRECATED [[deprecated]]
|
||||
#elif defined(__GNUC__) && __GNUC__ >= 4
|
||||
#define WL_DEPRECATED __attribute__ ((deprecated))
|
||||
#else
|
||||
#define WL_DEPRECATED
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) && __GNUC__ >= 4
|
||||
#define WL_PRINTF(x, y) __attribute__((__format__(__printf__, x, y)))
|
||||
#else
|
||||
#define WL_PRINTF(x, y)
|
||||
#endif
|
||||
|
||||
#if __STDC_VERSION__ >= 202311L
|
||||
#define WL_TYPEOF(expr) typeof(expr)
|
||||
#else
|
||||
#define WL_TYPEOF(expr) __typeof__(expr)
|
||||
#endif
|
||||
|
||||
struct wl_message {
|
||||
const char *name;
|
||||
const char *signature;
|
||||
const struct wl_interface **types;
|
||||
};
|
||||
|
||||
struct wl_interface {
|
||||
const char *name;
|
||||
int version;
|
||||
int method_count;
|
||||
const struct wl_message *methods;
|
||||
int event_count;
|
||||
const struct wl_message *events;
|
||||
};
|
||||
|
||||
struct wl_list {
|
||||
struct wl_list *prev;
|
||||
struct wl_list *next;
|
||||
};
|
||||
|
||||
#define wl_container_of(ptr, sample, member) \
|
||||
(WL_TYPEOF(sample))((char *)(ptr) - \
|
||||
offsetof(WL_TYPEOF(*sample), member))
|
||||
|
||||
#define wl_list_for_each(pos, head, member) \
|
||||
for (pos = wl_container_of((head)->next, pos, member); \
|
||||
&pos->member != (head); \
|
||||
pos = wl_container_of(pos->member.next, pos, member))
|
||||
|
||||
#define wl_list_for_each_safe(pos, tmp, head, member) \
|
||||
for (pos = wl_container_of((head)->next, pos, member), \
|
||||
tmp = wl_container_of((pos)->member.next, tmp, member); \
|
||||
&pos->member != (head); \
|
||||
pos = tmp, \
|
||||
tmp = wl_container_of(pos->member.next, tmp, member))
|
||||
|
||||
#define wl_list_for_each_reverse(pos, head, member) \
|
||||
for (pos = wl_container_of((head)->prev, pos, member); \
|
||||
&pos->member != (head); \
|
||||
pos = wl_container_of(pos->member.prev, pos, member))
|
||||
|
||||
#define wl_list_for_each_reverse_safe(pos, tmp, head, member) \
|
||||
for (pos = wl_container_of((head)->prev, pos, member), \
|
||||
tmp = wl_container_of((pos)->member.prev, tmp, member); \
|
||||
&pos->member != (head); \
|
||||
pos = tmp, \
|
||||
tmp = wl_container_of(pos->member.prev, tmp, member))
|
||||
|
||||
struct wl_array {
|
||||
size_t size;
|
||||
size_t alloc;
|
||||
void *data;
|
||||
};
|
||||
|
||||
void
|
||||
wl_array_init(struct wl_array *array);
|
||||
|
||||
void
|
||||
wl_array_release(struct wl_array *array);
|
||||
|
||||
void *
|
||||
wl_array_add(struct wl_array *array, size_t size);
|
||||
|
||||
int
|
||||
wl_array_copy(struct wl_array *array, struct wl_array *source);
|
||||
|
||||
#define wl_array_for_each(pos, array) \
|
||||
for (pos = (array)->data; \
|
||||
(array)->size != 0 && \
|
||||
(const char *) pos < ((const char *) (array)->data + (array)->size); \
|
||||
(pos)++)
|
||||
|
||||
typedef int32_t wl_fixed_t;
|
||||
|
||||
static inline double
|
||||
wl_fixed_to_double(wl_fixed_t f)
|
||||
{
|
||||
return f / 256.0;
|
||||
}
|
||||
|
||||
static inline wl_fixed_t
|
||||
wl_fixed_from_double(double d)
|
||||
{
|
||||
return (wl_fixed_t) (d * 256.0);
|
||||
}
|
||||
|
||||
static inline int
|
||||
wl_fixed_to_int(wl_fixed_t f)
|
||||
{
|
||||
return f / 256;
|
||||
}
|
||||
|
||||
static inline wl_fixed_t
|
||||
wl_fixed_from_int(int i)
|
||||
{
|
||||
return i * 256;
|
||||
}
|
||||
|
||||
union wl_argument {
|
||||
int32_t i;
|
||||
uint32_t u;
|
||||
wl_fixed_t f;
|
||||
const char *s;
|
||||
struct wl_object *o;
|
||||
uint32_t n;
|
||||
struct wl_array *a;
|
||||
int32_t h;
|
||||
};
|
||||
|
||||
typedef int (*wl_dispatcher_func_t)(const void *user_data, void *target,
|
||||
uint32_t opcode, const struct wl_message *msg,
|
||||
union wl_argument *args);
|
||||
|
||||
typedef void (*wl_log_func_t)(const char *fmt, va_list args) WL_PRINTF(1, 0);
|
||||
|
||||
enum wl_iterator_result {
|
||||
WL_ITERATOR_STOP,
|
||||
WL_ITERATOR_CONTINUE
|
||||
};
|
||||
|
||||
|
||||
#endif // FENNEC_PLATFORM_LINUX_WAYLAND_LIB_WAYLAND_UTIL_H
|
||||
98
include/fennec/platform/linux/wayland/lib/wayland.h
Normal file
98
include/fennec/platform/linux/wayland/lib/wayland.h
Normal file
@@ -0,0 +1,98 @@
|
||||
// =====================================================================================================================
|
||||
// fennec, a free and open source game engine
|
||||
// Copyright © 2025 Medusa Slockbower
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
// =====================================================================================================================
|
||||
|
||||
#ifndef FENNEC_PLATFORM_LINUX_WAYLAND_LIB_WAYLAND_CLIENT_H
|
||||
#define FENNEC_PLATFORM_LINUX_WAYLAND_LIB_WAYLAND_CLIENT_H
|
||||
|
||||
#define FENNEC_LIB(name) extern "C" bool FENNEC_HAS_LIB_##name;
|
||||
#define FENNEC_SYMBOL(ret, fn, ...) using WAYLAND_sym_##fn = ret(*)(__VA_ARGS__); \
|
||||
extern "C" WAYLAND_sym_##fn WAYLAND_##fn;
|
||||
#define FENNEC_GLOBAL(type, name) extern "C" type* WAYLAND_##name;
|
||||
#include <fennec/platform/linux/wayland/lib/sym.h>
|
||||
|
||||
#include <wayland-client-core.h>
|
||||
|
||||
#define wl_proxy_marshal WAYLAND_wl_proxy_marshal
|
||||
#define wl_proxy_marshal_flags WAYLAND_wl_proxy_marshal_flags
|
||||
#define wl_proxy_create WAYLAND_wl_proxy_create
|
||||
#define wl_proxy_destroy WAYLAND_wl_proxy_destroy
|
||||
#define wl_proxy_add_listener WAYLAND_wl_proxy_add_listener
|
||||
#define wl_proxy_set_user_data WAYLAND_wl_proxy_set_user_data
|
||||
#define wl_proxy_get_user_data WAYLAND_wl_proxy_get_user_data
|
||||
#define wl_proxy_get_version WAYLAND_wl_proxy_get_version
|
||||
#define wl_proxy_get_id WAYLAND_wl_proxy_get_id
|
||||
#define wl_proxy_get_class WAYLAND_wl_proxy_get_class
|
||||
#define wl_proxy_set_queue WAYLAND_wl_proxy_set_queue
|
||||
#define wl_proxy_create_wrapper WAYLAND_wl_proxy_create_wrapper
|
||||
#define wl_proxy_wrapper_destroy WAYLAND_wl_proxy_wrapper_destroy
|
||||
#define wl_proxy_marshal_constructor WAYLAND_wl_proxy_marshal_constructor
|
||||
#define wl_proxy_marshal_constructor_versioned WAYLAND_wl_proxy_marshal_constructor_versioned
|
||||
#define wl_proxy_set_tag WAYLAND_wl_proxy_set_tag
|
||||
#define wl_proxy_get_tag WAYLAND_wl_proxy_get_tag
|
||||
|
||||
#define wl_event_queue_destroy WAYLAND_wl_event_queue_destroy
|
||||
#define wl_log_set_handler_client WAYLAND_wl_log_set_handler_client
|
||||
#define wl_list_init WAYLAND_wl_list_init
|
||||
#define wl_list_insert WAYLAND_wl_list_insert
|
||||
#define wl_list_remove WAYLAND_wl_list_remove
|
||||
#define wl_list_length WAYLAND_wl_list_length
|
||||
#define wl_list_empty WAYLAND_wl_list_empty
|
||||
#define wl_list_insert_list WAYLAND_wl_list_insert_list
|
||||
|
||||
#define wl_display_connect WAYLAND_wl_display_connect
|
||||
#define wl_display_connect_to_fd WAYLAND_wl_display_connect_to_fd
|
||||
#define wl_display_reconnect WAYLAND_wl_display_reconnect
|
||||
#define wl_display_disconnect WAYLAND_wl_display_disconnect
|
||||
#define wl_display_get_fd WAYLAND_wl_display_get_fd
|
||||
#define wl_display_dispatch WAYLAND_wl_display_dispatch
|
||||
#define wl_display_dispatch_queue WAYLAND_wl_display_dispatch_queue
|
||||
#define wl_display_dispatch_queue_pending WAYLAND_wl_display_dispatch_queue_pending
|
||||
#define wl_display_dispatch_pending WAYLAND_wl_display_dispatch_pending
|
||||
#define wl_display_prepare_read WAYLAND_wl_display_prepare_read
|
||||
#define wl_display_prepare_read_queue WAYLAND_wl_display_prepare_read_queue
|
||||
#define wl_display_read_events WAYLAND_wl_display_read_events
|
||||
#define wl_display_cancel_read WAYLAND_wl_display_cancel_read
|
||||
#define wl_display_get_error WAYLAND_wl_display_get_error
|
||||
#define wl_display_flush WAYLAND_wl_display_flush
|
||||
#define wl_display_roundtrip WAYLAND_wl_display_roundtrip
|
||||
#define wl_display_create_queue WAYLAND_wl_display_create_queue
|
||||
|
||||
#define wl_seat_interface *WAYLAND_wl_seat_interface
|
||||
#define wl_surface_interface *WAYLAND_wl_surface_interface
|
||||
#define wl_shm_pool_interface *WAYLAND_wl_shm_pool_interface
|
||||
#define wl_buffer_interface *WAYLAND_wl_buffer_interface
|
||||
#define wl_registry_interface *WAYLAND_wl_registry_interface
|
||||
#define wl_region_interface *WAYLAND_wl_region_interface
|
||||
#define wl_pointer_interface *WAYLAND_wl_pointer_interface
|
||||
#define wl_keyboard_interface *WAYLAND_wl_keyboard_interface
|
||||
#define wl_compositor_interface *WAYLAND_wl_compositor_interface
|
||||
#define wl_output_interface *WAYLAND_wl_output_interface
|
||||
#define wl_shm_interface *WAYLAND_wl_shm_interface
|
||||
#define wl_data_device_interface *WAYLAND_wl_data_device_interface
|
||||
#define wl_data_offer_interface *WAYLAND_wl_data_offer_interface
|
||||
#define wl_data_source_interface *WAYLAND_wl_data_source_interface
|
||||
#define wl_data_device_manager_interface *WAYLAND_wl_data_device_manager_interface
|
||||
|
||||
#define wl_egl_window_create WAYLAND_wl_egl_window_create
|
||||
#define wl_egl_window_destroy WAYLAND_wl_egl_window_destroy
|
||||
#define wl_egl_window_resize WAYLAND_wl_egl_window_resize
|
||||
#define wl_egl_window_get_attached_size WAYLAND_wl_egl_window_get_attached_size
|
||||
|
||||
#include <fennec/platform/linux/wayland/lib/headers/wayland-client-protocols.h>
|
||||
|
||||
#endif // FENNEC_PLATFORM_LINUX_WAYLAND_LIB_WAYLAND_CLIENT_H
|
||||
83
include/fennec/platform/linux/wayland/window.h
Normal file
83
include/fennec/platform/linux/wayland/window.h
Normal file
@@ -0,0 +1,83 @@
|
||||
// =====================================================================================================================
|
||||
// fennec, a free and open source game engine
|
||||
// Copyright © 2025 Medusa Slockbower
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
// =====================================================================================================================
|
||||
|
||||
///
|
||||
/// \file window.h
|
||||
/// \brief
|
||||
///
|
||||
///
|
||||
/// \details
|
||||
/// \author Medusa Slockbower
|
||||
///
|
||||
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||
///
|
||||
///
|
||||
|
||||
#ifndef FENNEC_PLATFORM_LINUX_WAYLAND_WINDOW_H
|
||||
#define FENNEC_PLATFORM_LINUX_WAYLAND_WINDOW_H
|
||||
|
||||
#include <fennec/platform/interface/window.h>
|
||||
#include <fennec/platform/linux/wayland/display.h>
|
||||
|
||||
namespace fennec
|
||||
{
|
||||
|
||||
class wayland_window : public window {
|
||||
public:
|
||||
bool running() override;
|
||||
|
||||
void configure(const config& config) override;
|
||||
|
||||
bool initialize(bool modal) override;
|
||||
|
||||
bool shutdown() override;
|
||||
|
||||
bool set_title(const cstring& title) override;
|
||||
bool set_title(const string& title) override;
|
||||
|
||||
bool set_width(size_t w) override;
|
||||
bool set_height(size_t h) override;
|
||||
bool resize(size_t w, size_t h) override;
|
||||
bool set_resizable(bool e) override;
|
||||
bool set_fullscreen_mode(fullscreen_mode mode) override;
|
||||
|
||||
bool grab_keyboard(bool e) override;
|
||||
bool grab_mouse(bool e) override;
|
||||
|
||||
bool block_screensaver(bool e) override;
|
||||
|
||||
wayland_window(wayland_display* display, wayland_window* parent);
|
||||
~wayland_window() override;
|
||||
|
||||
struct wl_surface* get_native_handle() override {
|
||||
return _handle;
|
||||
}
|
||||
|
||||
private:
|
||||
wl_surface* _handle;
|
||||
wl_shell_surface* _shell;
|
||||
size_t _nfs_width, _nfs_height;
|
||||
|
||||
static void listen_ping(void*, wl_shell_surface*, uint32_t);
|
||||
static void listen_configure(void*, wl_shell_surface*, uint32_t, int32_t, int32_t);
|
||||
static void listen_popup_done(void*, wl_shell_surface*);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // FENNEC_PLATFORM_LINUX_WAYLAND_WINDOW_H
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
#include <EGL/egl.h>
|
||||
#include <fennec/platform/interface/gfxcontext.h>
|
||||
#include <fennec/platform/opengl/egl/fwd.h>
|
||||
|
||||
namespace fennec
|
||||
{
|
||||
@@ -34,12 +35,26 @@ public:
|
||||
bool connected() override;
|
||||
int32_t get_version_major() override { return _eglvmajor; }
|
||||
int32_t get_version_minor() override { return _eglvminor; }
|
||||
int32_t get_context_version() override { return _eglctype; }
|
||||
const cstring& get_context_name() override;
|
||||
int32_t get_version() override { return _eglctype; }
|
||||
const cstring& get_name() override;
|
||||
bool check_extension(const cstring& ext) override;
|
||||
|
||||
gfxsurface* create_surface(window* window) override;
|
||||
|
||||
void make_current(gfxsurface* surface) override;
|
||||
|
||||
EGLDisplay get_egl_display() {
|
||||
return _egldisplay;
|
||||
}
|
||||
|
||||
EGLDisplay get_egl_context() {
|
||||
return _eglcontext;
|
||||
}
|
||||
|
||||
EGLDisplay get_egl_config() {
|
||||
return _eglconfig;
|
||||
}
|
||||
|
||||
private:
|
||||
EGLDisplay _egldisplay;
|
||||
EGLContext _eglcontext;
|
||||
|
||||
@@ -16,7 +16,27 @@
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
// =====================================================================================================================
|
||||
|
||||
#ifndef FENNEC_CONCURRENCY_ATOMIC_H
|
||||
#define FENNEC_CONCURRENCY_ATOMIC_H
|
||||
///
|
||||
/// \file fwd.h
|
||||
/// \brief
|
||||
///
|
||||
///
|
||||
/// \details
|
||||
/// \author Medusa Slockbower
|
||||
///
|
||||
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||
///
|
||||
///
|
||||
|
||||
#endif // FENNEC_CONCURRENCY_ATOMIC_H
|
||||
#ifndef FENNEC_PLATFORM_OPENGL_EGL_FWD_H
|
||||
#define FENNEC_PLATFORM_OPENGL_EGL_FWD_H
|
||||
|
||||
namespace fennec
|
||||
{
|
||||
|
||||
class eglcontext;
|
||||
class eglsurface;
|
||||
|
||||
}
|
||||
|
||||
#endif // FENNEC_PLATFORM_OPENGL_EGL_FWD_H
|
||||
@@ -16,7 +16,45 @@
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
// =====================================================================================================================
|
||||
|
||||
#ifndef FENNEC_CONCURRENCY_MUTEX_H
|
||||
#define FENNEC_CONCURRENCY_MUTEX_H
|
||||
///
|
||||
/// \file surface.h
|
||||
/// \brief
|
||||
///
|
||||
///
|
||||
/// \details
|
||||
/// \author Medusa Slockbower
|
||||
///
|
||||
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||
///
|
||||
///
|
||||
|
||||
#endif // FENNEC_CONCURRENCY_MUTEX_H
|
||||
#ifndef FENNEC_PLATFORM_OPENGL_EGL_SURFACE_H
|
||||
#define FENNEC_PLATFORM_OPENGL_EGL_SURFACE_H
|
||||
|
||||
#include <fennec/platform/interface/gfxsurface.h>
|
||||
#include <fennec/platform/linux/wayland/window.h>
|
||||
#include <fennec/platform/opengl/egl/context.h>
|
||||
|
||||
namespace fennec
|
||||
{
|
||||
|
||||
class eglsurface : public gfxsurface {
|
||||
public:
|
||||
~eglsurface() override;
|
||||
|
||||
void resize(size_t width, size_t height) override;
|
||||
|
||||
eglsurface(eglcontext* context, window* window);
|
||||
|
||||
EGLSurface get_egl_surface() {
|
||||
return _surface;
|
||||
}
|
||||
|
||||
private:
|
||||
void* _handle;
|
||||
EGLSurface _surface;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // FENNEC_PLATFORM_OPENGL_EGL_SURFACE_H
|
||||
@@ -23,8 +23,8 @@ Links:
|
||||
|
||||
### Structures (`gfx2d`)
|
||||
|
||||
For the 2d rendering framework, Materials need to be rendered independently because we have
|
||||
no size constraints for images. This disallows us from using a meta-shader like in
|
||||
For the 2d rendering framework, Materials need to be rendered independently because we have
|
||||
no size constraints for images. This disallows us from using a meta-shader like in
|
||||
the 3d rendering framework.
|
||||
|
||||
```c++
|
||||
@@ -59,6 +59,6 @@ struct Object
|
||||
- Adjust Buffer Size using the counts
|
||||
- Insert using another atomic buffer
|
||||
|
||||
- Translucent objects will be sorted. We can cheat by using a z-index instead of a z-coordinate.
|
||||
This will allow us to sort objects as they are created. We can still bulk render each z-index,
|
||||
- Translucent objects will be sorted. We can cheat by using a z-index instead of a z-coordinate.
|
||||
This will allow us to sort objects as they are created. We can still bulk render each z-index,
|
||||
with meshes and objects being grouped by material.
|
||||
@@ -15,16 +15,16 @@
|
||||
|
||||
## Introduction
|
||||
|
||||
  This system handles the rendering of 3D meshes, materials, lights, and post-processing
|
||||
  This system handles the rendering of 3D meshes, materials, lights, and post-processing
|
||||
effects.
|
||||
**DirectX will never have official support.**
|
||||
If you would like to make a fork, have at it, but know that I will hold a deep disdain for you.
|
||||
|
||||
The graphics pipeline will have a buffer with a list of objects and their rendering data.
|
||||
The graphics pipeline will have a buffer with a list of objects and their rendering data.
|
||||
This will be referred to as the Object Buffer. There will be two, for both the Deferred and Forward Passes.
|
||||
|
||||
The buffers will be optimized by scene prediction.
|
||||
This involves tracking the meshes and textures directly and indirectly used by a scene.
|
||||
The buffers will be optimized by scene prediction.
|
||||
This involves tracking the meshes and textures directly and indirectly used by a scene.
|
||||
A callback function in the graphics system for scene loading can do this.
|
||||
|
||||
|
||||
@@ -66,8 +66,8 @@ Objects are identified with a manually provided type and ID. Object types includ
|
||||
|
||||
A user should never have to specify these and should be automatically generated by the respective components.
|
||||
|
||||
Textures for 3D rendering are stored in various buffers with sizes of powers of 2. Ratios of `1:1`
|
||||
and `2:1` are allowed. The `2:1` ratio is specifically for spherical and cylindrical projection. UVs
|
||||
Textures for 3D rendering are stored in various buffers with sizes of powers of 2. Ratios of `1:1`
|
||||
and `2:1` are allowed. The `2:1` ratio is specifically for spherical and cylindrical projection. UVs
|
||||
may be transformed to use a `2:1` as if it were `1:2`.
|
||||
Cubemaps and 3D textures may only be `1:1`.
|
||||
|
||||
|
||||
@@ -14,10 +14,10 @@
|
||||
|
||||
## Introduction
|
||||
|
||||
  This system will handle newtonian physics for 3D rigid and soft-bodies. This should include
|
||||
articulated skeletal systems, particle physics, and soft-body physics. The following soft-body systems
|
||||
will be supported with the associated implementation; elastics with finite element simulation, cloth
|
||||
physics with position-based dynamics, oceans with iWave, 3D fluid dynamics with smoothed-particle
|
||||
  This system will handle newtonian physics for 3D rigid and soft-bodies. This should include
|
||||
articulated skeletal systems, particle physics, and soft-body physics. The following soft-body systems
|
||||
will be supported with the associated implementation; elastics with finite element simulation, cloth
|
||||
physics with position-based dynamics, oceans with iWave, 3D fluid dynamics with smoothed-particle
|
||||
hydrodynamics, 2D surface fluid dynamics with force-based dynamics.
|
||||
|
||||
|
||||
|
||||
@@ -8,10 +8,10 @@
|
||||
|
||||
## Introduction
|
||||
|
||||
  This system implements pathing and decision systems for general-purpose traditional
|
||||
artifical intelligence algorithms. This library will not support Machine-Learning Artificial
|
||||
Intelligence (ML/AI). This artificial intelligence method only differs in static generation
|
||||
between 2D and 3D. The solvers are dimension independent since they work on a graph.
|
||||
  This system implements pathing and decision systems for general-purpose traditional
|
||||
artifical intelligence algorithms. This library will not support Machine-Learning Artificial
|
||||
Intelligence (ML/AI). This artificial intelligence method only differs in static generation
|
||||
between 2D and 3D. The solvers are dimension independent since they work on a graph.
|
||||
|
||||
|
||||
## General Process
|
||||
@@ -25,5 +25,5 @@ between 2D and 3D. The solvers are dimension independent since they work on a gr
|
||||
* update paths using dijkstra's algorithm
|
||||
* apply rigid-body forces with constraints
|
||||
|
||||
The update loop for artificial intelligence should only update every `n` ticks. Where
|
||||
The update loop for artificial intelligence should only update every `n` ticks. Where
|
||||
`n <= k`, with `k` being the tick rate of the physics engine.
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
|
||||
## Introduction
|
||||
|
||||
  This library contains headers and classes that implement common data
|
||||
structures. The contents include the Containers Library of the C++ Standard
|
||||
  This library contains headers and classes that implement common data
|
||||
structures. The contents include the Containers Library of the C++ Standard
|
||||
Library and Template Library.
|
||||
|
||||
|
||||
@@ -29,29 +29,29 @@ Library and Template Library.
|
||||
| Symbol | Implemented | Passed |
|
||||
|:-------------------------------------|:-----------:|:------:|
|
||||
| map (`std::unordered_map`) | ✅ | ✅ |
|
||||
| map_sequence (`std::map`) | ⛔ | ⛔ |
|
||||
| multiset (`std::unordered_multiset`) | ⛔ | ⛔ |
|
||||
| multisequence (`std::multiset`) | ⛔ | ⛔ |
|
||||
| multimap (`std::unordered_multimap`) | ⛔ | ⛔ |
|
||||
| multimap_sequence (`std::multimap`) | ⛔ | ⛔ |
|
||||
| map_sequence (`std::map`) | ⛔ | ⛔ |
|
||||
| multiset (`std::unordered_multiset`) | ⛔ | ⛔ |
|
||||
| multisequence (`std::multiset`) | ⛔ | ⛔ |
|
||||
| multimap (`std::unordered_multimap`) | ⛔ | ⛔ |
|
||||
| multimap_sequence (`std::multimap`) | ⛔ | ⛔ |
|
||||
| pair | ✅ | ✅ |
|
||||
| tuple | 🚧 | 🚧 |
|
||||
| optional | ✅ | ✅ |
|
||||
| variant | ⛔ | ⛔ |
|
||||
| any | ⛔ | ⛔ |
|
||||
| bitset | ⛔ | ⛔ |
|
||||
| variant | ⛔ | ⛔ |
|
||||
| any | ⛔ | ⛔ |
|
||||
| bitset | ⛔ | ⛔ |
|
||||
| array | ✅ | ✅ |
|
||||
| dynarray (`std::vector`) | 🚧 | 🚧 |
|
||||
| deque | ⛔ | ⛔ |
|
||||
| deque | ⛔ | ⛔ |
|
||||
| list | ✅ | ✅ |
|
||||
| set (`std::unordered_set`) | ✅ | ✅ |
|
||||
| sequence (`std::set`) | ⛔ | ⛔ |
|
||||
| sequence (`std::set`) | ⛔ | ⛔ |
|
||||
|
||||
|
||||
### fennec
|
||||
|
||||
| Symbol | Implemented | Passed |
|
||||
|:------------|:-----------:|:------:|
|
||||
| graph | 🚧 | 🚧 |
|
||||
| object_pool | 🚧 | 🚧 |
|
||||
| graph | 🚧 | 🚧 |
|
||||
| object_pool | 🚧 | 🚧 |
|
||||
| rd_tree | ✅ | ✅ |
|
||||
|
||||
@@ -15,41 +15,49 @@
|
||||
|
||||
## Introduction
|
||||
|
||||
  These files serve as general planning documentation for engine structure, systems,
|
||||
  These files serve as general planning documentation for engine structure, systems,
|
||||
pipelines, and implementation.
|
||||
|
||||
|
||||
  Implementations of core engine systems should strive to be `O(1)` in
|
||||
implementations, both in terms of runtime and memory performance. This is obviously
|
||||
not a realistic goal, so rather than the goal requiring the entire engine to be `O(1)`,
|
||||
we should more specifically look at achieving `O(1)` performance on hot paths.
|
||||
I distinctly use 'strive' and 'goal' as different concepts, where designs should
|
||||
*strive* to accommodate function implementations for `O(1)`, however the specifics
|
||||
of the implementation might not always be able to achieve that, so the end *goal* is
|
||||
  Implementations of core engine systems should strive to be `O(1)` in
|
||||
implementations, both in terms of runtime and memory performance. This is obviously
|
||||
not a realistic goal, so rather than the goal requiring the entire engine to be `O(1)`,
|
||||
we should more specifically look at achieving `O(1)` performance on hot paths.
|
||||
I distinctly use 'strive' and 'goal' as different concepts, where designs should
|
||||
*strive* to accommodate function implementations for `O(1)`, however the specifics
|
||||
of the implementation might not always be able to achieve that, so the end *goal* is
|
||||
that hot paths should be `O(1)`.
|
||||
|
||||
  Functions should be highly verbose and any bugprone or erroneous behaviour should
|
||||
  Functions should be highly verbose and any bugprone or erroneous behaviour should
|
||||
throw assertions. **DO NOT USE EXCEPTIONS**.
|
||||
|
||||
  System implementations should be independent of architecture or platforms. i.e.
|
||||
the code of the graphics system should not care if OpenGL or Vulkan is used and should
|
||||
  System implementations should be independent of architecture or platforms. i.e.
|
||||
the code of the graphics system should not care if OpenGL or Vulkan is used and should
|
||||
not use any direct calls to OpenGL or Vulkan.
|
||||
|
||||
  The engine should not care about the types of objects loaded from a so/dll. In
|
||||
fact, most of the code should be type independent. Any shared information among a
|
||||
collection of objects should be held either implicitly or explicitly in the super-class.
|
||||
It will be the responsibility of the linked code to initialize and cleanup the objects
|
||||
  The engine should not care about the types of objects loaded from a so/dll. In
|
||||
fact, most of the code should be type independent. Any shared information among a
|
||||
collection of objects should be held either implicitly or explicitly in the super-class.
|
||||
It will be the responsibility of the linked code to initialize and cleanup the objects
|
||||
related to it. This principle should extend to the submodules of the engine.
|
||||
|
||||
  It is also best to avoid objects having behaviour that is not defined by the system
|
||||
they are in. There are some exceptions in extensions or mods, which should be given
|
||||
configurability and programmability within those systems and their stages. This can
|
||||
  It is also best to avoid objects having behaviour that is not defined by the system
|
||||
they are in. There are some exceptions in extensions or mods, which should be given
|
||||
configurability and programmability within those systems and their stages. This can
|
||||
be achieved using events at different stages of those engines that are on-demand.
|
||||
|
||||
|
||||
## External Libraries
|
||||
|
||||
* `cpptrace`
|
||||
* Walking the stack and retrieving information about the code is *very* platform
|
||||
dependent, and it makes little sense spending days writing a library that will
|
||||
be less effective.
|
||||
|
||||
|
||||
## Definitions
|
||||
|
||||
  Many subpages of these documents will contain tables that use symbols to
|
||||
  Many subpages of these documents will contain tables that use symbols to
|
||||
denote implementation and testing progress. The symbols are defined below.
|
||||
|
||||
| Symbol | Meaning | Notes |
|
||||
@@ -62,4 +70,7 @@ denote implementation and testing progress. The symbols are defined below.
|
||||
|
||||
## Libraries
|
||||
- [C++ Language Library](./CPP_LANGUAGE.md#c-language-library-lang)
|
||||
- [Platform Support Library](./PLATFORM_SUPPORT.md#platform--api-support)
|
||||
- [Platform Support Library](./PLATFORM_SUPPORT.md#platform-support-library-platform)
|
||||
- [Memory Library](./MEMORY.md#memory-library-memory)
|
||||
- [Containers Library](./CONTAINERS.md#containers-library-containers)
|
||||
- [Language Processing Library](./LANGUAGE_PROCESSING.md#language-processing-library-langproc)
|
||||
@@ -26,8 +26,8 @@
|
||||
|
||||
## Introduction
|
||||
|
||||
  This library contains headers and classes related to the C++ language. The
|
||||
contents of this library include the Language Support, Diagnostics, and
|
||||
  This library contains headers and classes related to the C++ language. The
|
||||
contents of this library include the Language Support, Diagnostics, and
|
||||
Metaprogramming libraries of the C++ Standard Library and Template Library.
|
||||
|
||||
See:
|
||||
@@ -59,22 +59,22 @@ See:
|
||||
| is_null_pointer | ✅ | ✅ |
|
||||
| is_integral | ✅ | ✅ |
|
||||
| is_floating_point | ✅ | ✅ |
|
||||
| is_array | ✅ | ❓ |
|
||||
| is_array | ✅ | 🚧 |
|
||||
| is_enum | ⛔ | ⛔ |
|
||||
| is_union | ⛔ | ⛔ |
|
||||
| is_class | ✅ | ✅ |
|
||||
| is_function | ⛔ | ⛔ |
|
||||
| is_pointer | ✅ | ✅ |
|
||||
| is_lvalue_reference | ✅ | ✅ |
|
||||
| is_rvalue_reference | ✔ | ✔ |
|
||||
| is_rvalue_reference | ✅ | ✅ |
|
||||
| is_member_object_pointer | ⛔ | ⛔ |
|
||||
| is_member_function_pointer | ⛔ | ⛔ |
|
||||
|
||||
### Composite Types
|
||||
| Symbol | Implemented | Passed |
|
||||
|:------------------|:-----------:|:------:|
|
||||
| is_fundamental | ✔ | ✔ |
|
||||
| is_arithmetic | ✔ | ✔ |
|
||||
| is_fundamental | ✅ | ✅ |
|
||||
| is_arithmetic | ✅ | ✅ |
|
||||
| is_scalar | ⛔ | ⛔ |
|
||||
| is_object | ⛔ | ⛔ |
|
||||
| is_compound | ⛔ | ⛔ |
|
||||
@@ -84,9 +84,9 @@ See:
|
||||
### Type Properties
|
||||
| Symbol | Implemented | Passed |
|
||||
|:----------------------------------|:-----------:|:------:|
|
||||
| is_const | ✔ | ✔ |
|
||||
| is_volatile | ✔ | ✔ |
|
||||
| is_trivially_copyable | ✔ | ✔ |
|
||||
| is_const | ✅ | ✅ |
|
||||
| is_volatile | ✅ | ✅ |
|
||||
| is_trivially_copyable | ✅ | ✅ |
|
||||
| is_standard_layout | ⛔ | ⛔ |
|
||||
| has_unique_object_representations | ⛔ | ⛔ |
|
||||
| is_empty | ⛔ | ⛔ |
|
||||
@@ -95,8 +95,8 @@ See:
|
||||
| is_final | ⛔ | ⛔ |
|
||||
| is_aggregate | ⛔ | ⛔ |
|
||||
| is_implicit_lifetime | ⛔ | ⛔ |
|
||||
| is_signed | ✔ | ✔ |
|
||||
| is_unsigned | ✔ | ✔ |
|
||||
| is_signed | ✅ | ✅ |
|
||||
| is_unsigned | ✅ | ✅ |
|
||||
| is_bounded_array | ⛔ | ⛔ |
|
||||
| is_unbounded_array | ⛔ | ⛔ |
|
||||
| is_scoped_enum | ⛔ | ⛔ |
|
||||
@@ -104,16 +104,16 @@ See:
|
||||
### Supported Operations
|
||||
| Symbol | Implemented | Passed |
|
||||
|:------------------------------------|:-----------:|:------:|
|
||||
| is_constructible | ✔ | ✔ |
|
||||
| is_trivially_constructible | ✔ | ✔ |
|
||||
| is_constructible | ✅ | ✅ |
|
||||
| is_trivially_constructible | ✅ | ✅ |
|
||||
| is_nothrow_constructible | ⛔ | ⛔ |
|
||||
| is_default_constructible | ✔ | ✔ |
|
||||
| is_default_constructible | ✅ | ✅ |
|
||||
| is_trivially_default_constructible | ⛔ | ⛔ |
|
||||
| is_nothrow_default_constructible | ⛔ | ⛔ |
|
||||
| is_copy_constructible | ✔ | ✔ |
|
||||
| is_copy_constructible | ✅ | ✅ |
|
||||
| is_trivially_copy_constructible | ⛔ | ⛔ |
|
||||
| is_nothrow_copy_constructible | ⛔ | ⛔ |
|
||||
| is_move_constructible | ✔ | ✔ |
|
||||
| is_move_constructible | ✅ | ✅ |
|
||||
| is_trivially_move_constructible | ⛔ | ⛔ |
|
||||
| is_nothrow_move_constructible | ⛔ | ⛔ |
|
||||
| is_destructible | ⛔ | ⛔ |
|
||||
@@ -137,10 +137,10 @@ See:
|
||||
### Type Relationships
|
||||
| Symbol | Implemented | Passed |
|
||||
|:------------------------------------|:-----------:|:------:|
|
||||
| is_same | ✔ | ✔ |
|
||||
| is_same | ✅ | ✅ |
|
||||
| is_base_of | ❌ | ❌ |
|
||||
| is_virtual_base_of | ❌ | ❌ |
|
||||
| is_convertible | ✔ | ✔ |
|
||||
| is_convertible | ✅ | ✅ |
|
||||
| is_nothrow_convertible | ❌ | ❌ |
|
||||
| is_layout_compatible | ❌ | ❌ |
|
||||
| is_pointer_interconvertible_base_of | ❌ | ❌ |
|
||||
@@ -152,19 +152,19 @@ See:
|
||||
### Type Transformations
|
||||
| Symbol | Implemented | Passed |
|
||||
|:---------------------|:-----------:|:------:|
|
||||
| add_const | ✔ | ✔ |
|
||||
| add_volatile | ✔ | ✔ |
|
||||
| add_cv | ✔ | ✔ |
|
||||
| remove_const | ✔ | ✔ |
|
||||
| remove_volatile | ✔ | ✔ |
|
||||
| remove_cv | ✔ | ✔ |
|
||||
| add_lvalue_reference | ✔ | ✔ |
|
||||
| add_rvalue_reference | ✔ | ✔ |
|
||||
| remove_reference | ✔ | ✔ |
|
||||
| add_pointer | ✔ | ✔ |
|
||||
| remove_pointer | ✔ | ✔ |
|
||||
| make_signed | ✔ | ✔ |
|
||||
| make_unsigned | ✔ | ✔ |
|
||||
| add_const | ✅ | ✅ |
|
||||
| add_volatile | ✅ | ✅ |
|
||||
| add_cv | ✅ | ✅ |
|
||||
| remove_const | ✅ | ✅ |
|
||||
| remove_volatile | ✅ | ✅ |
|
||||
| remove_cv | ✅ | ✅ |
|
||||
| add_lvalue_reference | ✅ | ✅ |
|
||||
| add_rvalue_reference | ✅ | ✅ |
|
||||
| remove_reference | ✅ | ✅ |
|
||||
| add_pointer | ✅ | ✅ |
|
||||
| remove_pointer | ✅ | ✅ |
|
||||
| make_signed | ✅ | ✅ |
|
||||
| make_unsigned | ✅ | ✅ |
|
||||
| remove_extent | ❌ | ❌ |
|
||||
| remove_all_extents | ❌ | ❌ |
|
||||
|
||||
@@ -174,17 +174,17 @@ See:
|
||||
| aligned_storage | ❌ | ❌ |
|
||||
| aligned_union | ❌ | ❌ |
|
||||
| aligned_union | ❌ | ❌ |
|
||||
| decay | 🚧 | 🚧 |
|
||||
| remove_cvref | ✔ | ✔ |
|
||||
| enable_if | ✔ | ✔ |
|
||||
| conditional | ✔ | ✔ |
|
||||
| decay | 🚧 | 🚧 |
|
||||
| remove_cvref | ✅ | ✅ |
|
||||
| enable_if | ✅ | ✅ |
|
||||
| conditional | ✅ | ✅ |
|
||||
| common_type | ❌ | ❌ |
|
||||
| common_reference | ❌ | ❌ |
|
||||
| basic_common_reference | ❌ | ❌ |
|
||||
| underlying_type | ❌ | ❌ |
|
||||
| result_of | ❌ | ❌ |
|
||||
| invoke_result | ❌ | ❌ |
|
||||
| void_t | ✔ | ✔ |
|
||||
| void_t | ✅ | ✅ |
|
||||
|
||||
### Logical Operations
|
||||
| Symbol | Implemented | Passed |
|
||||
@@ -196,9 +196,9 @@ See:
|
||||
### Sequences
|
||||
| Symbol | Implemented | Passed |
|
||||
|:-------------------------------------------------|:-----------:|:------:|
|
||||
| const_sequence | ✔ | ✔ |
|
||||
| const_integer_sequence (`std::integer_sequence`) | ✔ | ✔ |
|
||||
| make_integer_sequence | ✔ | ✔ |
|
||||
| const_index_sequence (`std::index_sequence`) | ✔ | ✔ |
|
||||
| make_index_sequence | ✔ | ✔ |
|
||||
| concat_sequence | ✔ | ✔ |
|
||||
| const_sequence | ✅ | ✅ |
|
||||
| const_integer_sequence (`std::integer_sequence`) | ✅ | ✅ |
|
||||
| make_integer_sequence | ✅ | ✅ |
|
||||
| const_index_sequence (`std::index_sequence`) | ✅ | ✅ |
|
||||
| make_index_sequence | ✅ | ✅ |
|
||||
| concat_sequence | ✅ | ✅ |
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
## Introduction
|
||||
|
||||
  This file outlines the core engine structure and all necessary systems for
|
||||
  This file outlines the core engine structure and all necessary systems for
|
||||
the engine to run.
|
||||
|
||||
|
||||
@@ -35,70 +35,70 @@ This section outlines core systems to the engine and brief overviews.
|
||||
|
||||
### Events
|
||||
|
||||
  fennec will be largely event based, the system should be able to handle multiple
|
||||
event types without having any type-specific code. There will be a few categories of events,
|
||||
predominantly on-demand and delayed events. On-demand events are fired immediately, which is
|
||||
useful for events related to graphics and audio. Delayed events are fired at the next tick or
|
||||
after a certain period of time, this is useful for physics events which can't be handled
|
||||
immediately without potentially harming the state of the physics engine. Events should be
|
||||
  fennec will be largely event based, the system should be able to handle multiple
|
||||
event types without having any type-specific code. There will be a few categories of events,
|
||||
predominantly on-demand and delayed events. On-demand events are fired immediately, which is
|
||||
useful for events related to graphics and audio. Delayed events are fired at the next tick or
|
||||
after a certain period of time, this is useful for physics events which can't be handled
|
||||
immediately without potentially harming the state of the physics engine. Events should be
|
||||
optionally able to be handled with multithreading.
|
||||
|
||||
|
||||
### Scene
|
||||
|
||||
  The core structure of the engine and its levels will be a scene hierarchy. The hierarchy
|
||||
will be implemented using a rooted-directed tree (rdtree, not to be confused with rbtree).
|
||||
Each element in the tree will be a node with a name and some very basic flags. Component
|
||||
dependent behaviour *must* be handled in systems to avoid the overhead of an object-oriented
|
||||
scene hierarchy. This is predominantly caused by the recursive nature of parsing an object-
|
||||
  The core structure of the engine and its levels will be a scene hierarchy. The hierarchy
|
||||
will be implemented using a rooted-directed tree (rdtree, not to be confused with rbtree).
|
||||
Each element in the tree will be a node with a name and some very basic flags. Component
|
||||
dependent behaviour *must* be handled in systems to avoid the overhead of an object-oriented
|
||||
scene hierarchy. This is predominantly caused by the recursive nature of parsing an object-
|
||||
oriented scene hierarchy where each node records its children and updates them accordingly.
|
||||
|
||||
|
||||
### Scripts
|
||||
|
||||
  Scripts won't be handled the same way scripts are in other engines, they will be translated
|
||||
as a system which will be data-oriented. This is to reduce the overhead of the object-oriented
|
||||
  Scripts won't be handled the same way scripts are in other engines, they will be translated
|
||||
as a system which will be data-oriented. This is to reduce the overhead of the object-oriented
|
||||
approach in C++ while maintaining the appearance of being object-oriented.
|
||||
|
||||
|
||||
### AI
|
||||
|
||||
  AI will be a fairly multi-parted system as we need to handle different use-cases.
|
||||
The first use case is characters that can "walk" and "jump" on surfaces. The second use-case
|
||||
is characters that "fly" in some manner. The static path generation will be the only difference
|
||||
  AI will be a fairly multi-parted system as we need to handle different use-cases.
|
||||
The first use case is characters that can "walk" and "jump" on surfaces. The second use-case
|
||||
is characters that "fly" in some manner. The static path generation will be the only difference
|
||||
between 2D and 3D.
|
||||
|
||||
|
||||
### Physics
|
||||
|
||||
  Physics, like other systems, will be separated into 2D and 3D specific implementations.
|
||||
This system should be able to handle both Newtonian Rigid-Bodies and Soft-Bodies. The 2D
|
||||
and 3D systems should be able to co-exist but not interact. This is for such cases where one
|
||||
  Physics, like other systems, will be separated into 2D and 3D specific implementations.
|
||||
This system should be able to handle both Newtonian Rigid-Bodies and Soft-Bodies. The 2D
|
||||
and 3D systems should be able to co-exist but not interact. This is for such cases where one
|
||||
might decide to have a minigame with physics enabled in a 2D environment.
|
||||
|
||||
|
||||
### Graphics
|
||||
|
||||
  Graphics, like other systems, will be separated into 2D and 3D specific implementations.
|
||||
Graphics will exist on a separate thread that handles "frames" vs "ticks," see definitions below
|
||||
for more information. From an abstract, the graphics system should be able to handle static models,
|
||||
  Graphics, like other systems, will be separated into 2D and 3D specific implementations.
|
||||
Graphics will exist on a separate thread that handles "frames" vs "ticks," see definitions below
|
||||
for more information. From an abstract, the graphics system should be able to handle static models,
|
||||
dynamic models, skeletons, materials, lights, lighting models, and post-processing effects.
|
||||
|
||||
|
||||
### Audio
|
||||
|
||||
  Audio may actually be implemented generically since the principles of spatial audio apply
|
||||
identically in both 2D and 3D. The only thing that may change for 2D is which axis is "up" and which
|
||||
axis is "forwards," for example side-scrollers vs top-down. However, this does not mandate specific
|
||||
implementations and rather just aliases which axis is "up." The X-axis can always be "left" and "right"
|
||||
while the Y axis may be interpreted as "up" or "forwards." Audio also won't be handled in the same
|
||||
  Audio may actually be implemented generically since the principles of spatial audio apply
|
||||
identically in both 2D and 3D. The only thing that may change for 2D is which axis is "up" and which
|
||||
axis is "forwards," for example side-scrollers vs top-down. However, this does not mandate specific
|
||||
implementations and rather just aliases which axis is "up." The X-axis can always be "left" and "right"
|
||||
while the Y axis may be interpreted as "up" or "forwards." Audio also won't be handled in the same
|
||||
manner as other systems which have explicit ticks and frames.
|
||||
|
||||
|
||||
|
||||
## Core Game Loop
|
||||
|
||||
  The core game loop is divided into Ticks and Frames. Ticks represent updates in the engine
|
||||
  The core game loop is divided into Ticks and Frames. Ticks represent updates in the engine
|
||||
state while Frames represent the generation of the visual output of the engine.
|
||||
|
||||
### Tick
|
||||
|
||||
@@ -17,20 +17,20 @@
|
||||
|
||||
## Introduction
|
||||
|
||||
  This library contains implementations of headers and classes related to processing
|
||||
languages. This includes; ascii/utf8/utf16 string processing, file formats, machine language,
|
||||
  This library contains implementations of headers and classes related to processing
|
||||
languages. This includes; ascii/utf8/utf16 string processing, file formats, machine language,
|
||||
and programming languages.
|
||||
|
||||
  fennec should be able to process documentation in files, the main ways it will support
|
||||
  fennec should be able to process documentation in files, the main ways it will support
|
||||
this is through Doxygen and LaTeX. Consider including binaries with releases.
|
||||
|
||||
|
||||
## String Analysis (`langproc/strings`)
|
||||
|
||||
  fennec reimplements the C++ Strings Library as a submodule of this library. This
|
||||
is because C++ `std::string` has a lot of overhead. I would say that `std::string`
|
||||
is a Jeep, while `fennec::string` is an F2 Car, if that analogy makes any sense. i.e.
|
||||
`std::string` offers a lot of use cases, but is slower, while an F2 Car is barebones and
|
||||
  fennec reimplements the C++ Strings Library as a submodule of this library. This
|
||||
is because C++ `std::string` has a lot of overhead. I would say that `std::string`
|
||||
is a Jeep, while `fennec::string` is an F2 Car, if that analogy makes any sense. i.e.
|
||||
`std::string` offers a lot of use cases, but is slower, while an F2 Car is barebones and
|
||||
highly performant on the right surface.
|
||||
|
||||
### Implementation
|
||||
@@ -46,7 +46,7 @@ highly performant on the right surface.
|
||||
|
||||
## File System (`filesystem`)
|
||||
|
||||
  fennec *does not* reimplement the C++ I/O Library. What it does do
|
||||
  fennec *does not* reimplement the C++ I/O Library. What it does do
|
||||
is create C++ classes that handle file streams, directory streams, and file paths.
|
||||
|
||||
### Implementation
|
||||
@@ -86,7 +86,7 @@ certain specification. Here are some concepts that will need to be implemented a
|
||||
|
||||
### Writing
|
||||
|
||||
  The writers will be responsible for writing data as a specific format. I.E. converting
|
||||
  The writers will be responsible for writing data as a specific format. I.E. converting
|
||||
data values (e.g. floats, ints, etc.) to a readable language (e.g. ascii/utf8/utf16).
|
||||
|
||||
- Writer
|
||||
@@ -96,7 +96,7 @@ data values (e.g. floats, ints, etc.) to a readable language (e.g. ascii/utf8/ut
|
||||
|
||||
## Formats (`langproc/formats`)
|
||||
|
||||
  This submodule will contain classes for processing a variety of file formats.
|
||||
  This submodule will contain classes for processing a variety of file formats.
|
||||
|
||||
### Serialization
|
||||
|
||||
@@ -166,8 +166,8 @@ data values (e.g. floats, ints, etc.) to a readable language (e.g. ascii/utf8/ut
|
||||
|
||||
#### 3D Model Formats
|
||||
|
||||
  unfortunately, most formats are esoteric due to copyright/trademark/etc.
|
||||
I will be using assimp for the time being, below is a list of formats supported
|
||||
  unfortunately, most formats are esoteric due to copyright/trademark/etc.
|
||||
I will be using assimp for the time being, below is a list of formats supported
|
||||
by assimp.
|
||||
|
||||
| Symbol | Implemented | Passed |
|
||||
|
||||
@@ -14,9 +14,9 @@
|
||||
|
||||
## Introduction
|
||||
|
||||
  This library contains headers and classes related to memory allocation and
|
||||
management in C++. The contents include the Memory Management Library of
|
||||
the C++ Standard Library and Template Library. This pulls some functions from the
|
||||
  This library contains headers and classes related to memory allocation and
|
||||
management in C++. The contents include the Memory Management Library of
|
||||
the C++ Standard Library and Template Library. This pulls some functions from the
|
||||
C stdlib and either wraps them or aliases them.
|
||||
|
||||
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
|
||||
## Introduction
|
||||
|
||||
  The platform support library will include headers, functions, and classes related
|
||||
to supporting various platforms. Platforms may be defined as any Hardware, OS, or
|
||||
  The platform support library will include headers, functions, and classes related
|
||||
to supporting various platforms. Platforms may be defined as any Hardware, OS, or
|
||||
Drivers that must be initialized for the engine context.
|
||||
|
||||
|
||||
@@ -48,14 +48,14 @@ Platform Support will be implemented in the following order:
|
||||
- Vulkan
|
||||
- Metal
|
||||
|
||||
  Linux Wayland will be implemented first. Once setup, the core engine will be
|
||||
implemented and tested on top of Wayland. Once the engine is in a stable state,
|
||||
  Linux Wayland will be implemented first. Once setup, the core engine will be
|
||||
implemented and tested on top of Wayland. Once the engine is in a stable state,
|
||||
then support for other platforms will be resumed.
|
||||
|
||||
|
||||
## Consoles
|
||||
|
||||
  Most consoles will never get official platform support due to NDAs which conflict
|
||||
with the principles of this engine. fennec will avoid using proprietary libraries except
|
||||
when strictly necessary, such as support for Windows and MacOS. fennec will interact
|
||||
  Most consoles will never get official platform support due to NDAs which conflict
|
||||
with the principles of this engine. fennec will avoid using proprietary libraries except
|
||||
when strictly necessary, such as support for Windows and MacOS. fennec will interact
|
||||
with any drivers required for the listed operating systems above, even if proprietary.
|
||||
|
||||
@@ -138,8 +138,8 @@ file& file::operator=(file&& file) noexcept {
|
||||
_error = file._error;
|
||||
|
||||
file._handle = nullptr;
|
||||
file._path = "";
|
||||
file._error = nullptr;
|
||||
file._path = "";
|
||||
file._error = nullptr;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ path path::current() {
|
||||
path path::current() {
|
||||
char cstr[PATH_MAX];
|
||||
if (getcwd(cstr, sizeof(cstr)) == nullptr) {
|
||||
return string("");
|
||||
return path("");
|
||||
}
|
||||
return path(cstring(cstr, strlen(cstr) + 1));
|
||||
}
|
||||
|
||||
@@ -18,9 +18,11 @@
|
||||
|
||||
#include <fennec/platform/linux/wayland/display.h>
|
||||
#include <fennec/platform/linux/wayland/lib/loader.h>
|
||||
#include <fennec/platform/linux/wayland/lib/wayland-client.h>
|
||||
#include <fennec/platform/linux/wayland/lib/wayland.h>
|
||||
|
||||
#include <fennec/lang/startup.h>
|
||||
#include <fennec/platform/linux/wayland/window.h>
|
||||
#include <fennec/platform/linux/wayland/lib/headers/wayland-client-protocols.h>
|
||||
|
||||
namespace fennec
|
||||
{
|
||||
@@ -42,7 +44,6 @@ wayland_display::wayland_display(platform* platform)
|
||||
, _handle(nullptr)
|
||||
, _registry(nullptr)
|
||||
, _compositor(nullptr)
|
||||
, _shell(nullptr)
|
||||
, _seat(nullptr)
|
||||
, _shm(nullptr)
|
||||
, _fifo(false) {
|
||||
@@ -89,14 +90,13 @@ bool wayland_display::connected() const {
|
||||
return _handle != nullptr;
|
||||
}
|
||||
|
||||
window* wayland_display::create_window() {
|
||||
return nullptr;
|
||||
window* wayland_display::create_window(window* parent) {
|
||||
return new wayland_window(this, static_cast<wayland_window*>(parent));
|
||||
}
|
||||
|
||||
void wayland_display::cleanup() {
|
||||
|
||||
// Cleanup members
|
||||
if (_shell) wl_shell_destroy(_shell);
|
||||
if (_compositor) wl_compositor_destroy(_compositor);
|
||||
if (_registry) wl_registry_destroy(_registry);
|
||||
if (_handle) {
|
||||
@@ -104,7 +104,6 @@ void wayland_display::cleanup() {
|
||||
wl_display_disconnect(_handle);
|
||||
}
|
||||
|
||||
_shell = nullptr;
|
||||
_compositor = nullptr;
|
||||
_registry = nullptr;
|
||||
_handle = nullptr;
|
||||
@@ -121,11 +120,9 @@ void wayland_display::listen_global(void* data, wl_registry* registry, uint32_t
|
||||
const cstring interface = cstring(itfc, strlen(itfc) + 1);
|
||||
|
||||
if (interface == "wl_compositor") {
|
||||
device->_compositor = static_cast<wl_compositor*>(wl_registry_bind(registry, name, wl_compositor_interface, version));
|
||||
} else if (interface == "wl_shell") {
|
||||
device->_shell = static_cast<wl_shell*>(wl_registry_bind(registry, name, wl_shell_interface, version));
|
||||
device->_compositor = static_cast<wl_compositor*>(wl_registry_bind(registry, name, &wl_compositor_interface, version));
|
||||
} else if (interface == "wl_seat") {
|
||||
device->_seat = static_cast<wl_seat*>(wl_registry_bind(registry, name, wl_seat_interface, version));
|
||||
device->_seat = static_cast<wl_seat*>(wl_registry_bind(registry, name, &wl_seat_interface, version));
|
||||
wl_seat_add_listener(device->_seat, &seat_listener, device);
|
||||
} else if (interface == "wp_fifo_manager_v1") {
|
||||
device->_fifo = true;
|
||||
|
||||
@@ -16,13 +16,13 @@
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
// =====================================================================================================================
|
||||
|
||||
#include <fennec/platform/linux/wayland/lib/wayland-client.h>
|
||||
#include <fennec/platform/linux/wayland/lib/headers/wayland-client-protocols.h>
|
||||
#include <fennec/platform/linux/wayland/lib/loader.h>
|
||||
|
||||
#define FENNEC_LIB(name) bool FENNEC_HAS_LIB_##name;
|
||||
#define FENNEC_SYMBOL(ret, fn, ...) using sym_##fn = ret(*)(__VA_ARGS__); \
|
||||
sym_##fn fn;
|
||||
#define FENNEC_GLOBAL(type, name) type* name;
|
||||
#define FENNEC_SYMBOL(ret, fn, ...) using WAYLAND_sym_##fn = ret(*)(__VA_ARGS__); \
|
||||
WAYLAND_sym_##fn WAYLAND_##fn;
|
||||
#define FENNEC_GLOBAL(type, name) type* WAYLAND_##name;
|
||||
#include <fennec/platform/linux/wayland/lib/sym.h>
|
||||
|
||||
namespace fennec
|
||||
@@ -57,10 +57,10 @@ bool load_symbols(platform* platform) {
|
||||
return false; \
|
||||
} \
|
||||
current_lib = &_FENNEC_LIB_##lib;
|
||||
#define FENNEC_SYMBOL(ret, fn, ...) fn = (sym_##fn)(platform->find_symbol(current_lib->obj, #fn)); \
|
||||
assertf(fn != nullptr, "Failed to find symbol: " #fn);
|
||||
#define FENNEC_GLOBAL(type, name) name = (type*)(platform->find_symbol(current_lib->obj, #name)); \
|
||||
assertf(name != nullptr, "Failed to find global: " #name);
|
||||
#define FENNEC_SYMBOL(ret, fn, ...) WAYLAND_##fn = (WAYLAND_sym_##fn)(platform->find_symbol(current_lib->obj, #fn)); \
|
||||
assertf(WAYLAND_##fn != nullptr, "Failed to find symbol: " #fn);
|
||||
#define FENNEC_GLOBAL(type, name) WAYLAND_##name = (type*)(platform->find_symbol(current_lib->obj, #name)); \
|
||||
assertf(WAYLAND_##name != nullptr, "Failed to find global: " #name);
|
||||
#include <fennec/platform/linux/wayland/lib/sym.h>
|
||||
|
||||
|
||||
@@ -74,9 +74,9 @@ void unload_symbols(platform* platform) {
|
||||
}
|
||||
|
||||
#define FENNEC_LIB(lib) platform->unload_object(_FENNEC_LIB_##lib.obj); \
|
||||
_FENNEC_LIB_##lib.obj = nullptr;
|
||||
#define FENNEC_SYMBOL(ret, fn, ...) fn = nullptr;
|
||||
#define FENNEC_GLOBAL(type, name) name = nullptr;
|
||||
_FENNEC_LIB_##lib.obj = nullptr;
|
||||
#define FENNEC_SYMBOL(ret, fn, ...) WAYLAND_##fn = nullptr;
|
||||
#define FENNEC_GLOBAL(type, name) WAYLAND_##name = nullptr;
|
||||
#include <fennec/platform/linux/wayland/lib/sym.h>
|
||||
}
|
||||
|
||||
|
||||
139
source/platform/linux/wayland/window.cpp
Normal file
139
source/platform/linux/wayland/window.cpp
Normal file
@@ -0,0 +1,139 @@
|
||||
// =====================================================================================================================
|
||||
// fennec, a free and open source game engine
|
||||
// Copyright © 2025 Medusa Slockbower
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
// =====================================================================================================================
|
||||
|
||||
#include <fennec/platform/interface/gfxcontext.h>
|
||||
#include <fennec/platform/interface/gfxsurface.h>
|
||||
|
||||
#include <fennec/platform/linux/wayland/window.h>
|
||||
#include <fennec/platform/linux/wayland/lib/wayland.h>
|
||||
|
||||
namespace fennec
|
||||
{
|
||||
|
||||
bool wayland_window::running() {
|
||||
return _surface != nullptr;
|
||||
}
|
||||
|
||||
void wayland_window::configure(const config& config) {
|
||||
_config = config;
|
||||
}
|
||||
|
||||
bool wayland_window::initialize(bool) {
|
||||
|
||||
wayland_display* display = static_cast<wayland_display*>(_display);
|
||||
|
||||
_handle = wl_compositor_create_surface(display->get_compositor());
|
||||
|
||||
_surface = display->get_context()->create_surface(this);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool wayland_window::shutdown() {
|
||||
delete _surface;
|
||||
wl_surface_destroy(_handle);
|
||||
_display = nullptr;
|
||||
_surface = nullptr;
|
||||
_shell = nullptr;
|
||||
_handle = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool wayland_window::set_title(const cstring& title) {
|
||||
if (not _config) {
|
||||
return true;
|
||||
}
|
||||
_config->title = title;
|
||||
wl_shell_surface_set_title(_shell, _config->title.cstr());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool wayland_window::set_title(const string& title) {
|
||||
if (not _config) {
|
||||
return true;
|
||||
}
|
||||
_config->title = title;
|
||||
wl_shell_surface_set_title(_shell, _config->title.cstr());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool wayland_window::set_width(size_t w) {
|
||||
if (not _config) {
|
||||
return true;
|
||||
}
|
||||
_config->width = w;
|
||||
_surface->resize(_config->width, _config->height);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool wayland_window::set_height(size_t h) {
|
||||
if (not _config) {
|
||||
return true;
|
||||
}
|
||||
_config->height = h;
|
||||
_surface->resize(_config->width, _config->height);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool wayland_window::resize(size_t w, size_t h) {
|
||||
if (not _config) {
|
||||
return true;
|
||||
}
|
||||
_config->width = w;
|
||||
_config->height = h;
|
||||
_surface->resize(_config->width, _config->height);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool wayland_window::set_resizable(bool) {
|
||||
return false; // TODO
|
||||
}
|
||||
|
||||
bool wayland_window::set_fullscreen_mode(fullscreen_mode) {
|
||||
return false; // TODO
|
||||
}
|
||||
|
||||
bool wayland_window::grab_keyboard(bool) {
|
||||
return false; // TODO
|
||||
}
|
||||
|
||||
bool wayland_window::grab_mouse(bool) {
|
||||
return false; // TODO
|
||||
}
|
||||
|
||||
bool wayland_window::block_screensaver(bool) {
|
||||
return false; // TODO
|
||||
}
|
||||
|
||||
wayland_window::wayland_window(wayland_display* display, wayland_window* parent)
|
||||
: window(display, parent, this)
|
||||
, _handle()
|
||||
, _shell()
|
||||
, _nfs_width(0), _nfs_height(0) {
|
||||
}
|
||||
|
||||
wayland_window::~wayland_window() {
|
||||
wayland_window::shutdown();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -21,6 +21,7 @@
|
||||
#include <fennec/platform/interface/display.h>
|
||||
#include <fennec/platform/interface/platform.h>
|
||||
#include <fennec/platform/opengl/egl/context.h>
|
||||
#include <fennec/platform/opengl/egl/surface.h>
|
||||
|
||||
#include <GL/gl.h>
|
||||
|
||||
@@ -40,7 +41,10 @@ STATIC_CONSTRUCTOR(_egl_init) {
|
||||
}
|
||||
|
||||
eglcontext::eglcontext(display* display)
|
||||
: gfxcontext(display, "EGL", this) {
|
||||
: gfxcontext(display, "EGL", this)
|
||||
, _egldisplay(nullptr), _eglcontext(nullptr)
|
||||
, _eglconfig(), _eglvmajor(0), _eglvminor(0)
|
||||
, _eglctype(0), _extensions(nullptr) {
|
||||
|
||||
// Get the display format
|
||||
const display::pixel_format& fmt = _display->get_color_format();
|
||||
@@ -121,7 +125,7 @@ bool eglcontext::connected() {
|
||||
return _eglcontext != nullptr;
|
||||
}
|
||||
|
||||
const cstring& eglcontext::get_context_name() {
|
||||
const cstring& eglcontext::get_name() {
|
||||
static constexpr cstring opengl = "OpenGL";
|
||||
static constexpr cstring gles = "GLES";
|
||||
static constexpr cstring openvg = "OpenVG"; // this should never be used
|
||||
@@ -137,8 +141,13 @@ bool eglcontext::check_extension(const cstring& ext) {
|
||||
return _extensions.find(ext) != _extensions.size();
|
||||
}
|
||||
|
||||
void eglcontext::make_current(gfxsurface*) {
|
||||
gfxsurface* eglcontext::create_surface(window* window) {
|
||||
return new eglsurface(this, window);
|
||||
}
|
||||
|
||||
void eglcontext::make_current(gfxsurface* surface) {
|
||||
eglsurface* eglsurface = static_cast<fennec::eglsurface*>(surface);
|
||||
eglMakeCurrent(_egldisplay, eglsurface->get_egl_surface(), eglsurface->get_egl_surface(), _eglcontext);
|
||||
}
|
||||
|
||||
void eglcontext::cleanup() {
|
||||
|
||||
66
source/platform/opengl/egl/surface.cpp
Normal file
66
source/platform/opengl/egl/surface.cpp
Normal file
@@ -0,0 +1,66 @@
|
||||
// =====================================================================================================================
|
||||
// fennec, a free and open source game engine
|
||||
// Copyright © 2025 Medusa Slockbower
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
// =====================================================================================================================
|
||||
|
||||
#include <fennec/platform/opengl/egl/surface.h>
|
||||
#include <fennec/platform/linux/wayland/lib/wayland.h>
|
||||
|
||||
namespace fennec
|
||||
{
|
||||
|
||||
eglsurface::~eglsurface() {
|
||||
if (_window->is_type<wayland_window>()) {
|
||||
wl_egl_window_destroy(static_cast<wl_egl_window*>(_handle));
|
||||
}
|
||||
}
|
||||
|
||||
void eglsurface::resize(size_t width, size_t height) {
|
||||
gfxsurface::resize(width, height);
|
||||
if (_window->is_type<wayland_window>()) {
|
||||
wl_egl_window_resize(static_cast<wl_egl_window*>(_handle), width, height, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
eglsurface::eglsurface(eglcontext* context, window* window)
|
||||
: gfxsurface(context, window, this)
|
||||
, _handle(nullptr)
|
||||
, _surface(nullptr) {
|
||||
|
||||
const window::config& config = window->get_config();
|
||||
if (window->is_type<wayland_window>()) {
|
||||
_handle = wl_egl_window_create(window->get_native_handle(), config.width, config.height);
|
||||
}
|
||||
|
||||
assert(
|
||||
_handle != nullptr,
|
||||
"Failed to create egl window!"
|
||||
);
|
||||
|
||||
eglCreateWindowSurface(
|
||||
context->get_egl_display(),
|
||||
context->get_egl_config(),
|
||||
reinterpret_cast<EGLNativeWindowType>(_handle),
|
||||
nullptr
|
||||
);
|
||||
|
||||
assert(
|
||||
EGL_TRUE == eglMakeCurrent(context->get_egl_display(), _surface, _surface, context->get_egl_context()),
|
||||
"Failed to create egl window!"
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -34,13 +34,33 @@ inline void fennec_test_platform() {
|
||||
platform* instance = platform::instance();
|
||||
instance->initialize();
|
||||
|
||||
fennec_test_run(instance->get_display() != nullptr, true);
|
||||
fennec_test_run(instance->get_display()->get_context() != nullptr, true);
|
||||
display* display = instance->get_display();
|
||||
|
||||
std::cout << instance->get_display()->get_context()->get_context_name() << " ";
|
||||
std::cout << instance->get_display()->get_context()->get_version_major() << ".";
|
||||
std::cout << instance->get_display()->get_context()->get_version_minor() << std::endl;
|
||||
fennec_test_run(display != nullptr, true);
|
||||
fennec_test_run(display->get_context() != nullptr, true);
|
||||
|
||||
gfxcontext* gfxcontext = display->get_context();
|
||||
|
||||
std::cout << gfxcontext->get_name() << " ";
|
||||
std::cout << gfxcontext->get_version_major() << ".";
|
||||
std::cout << gfxcontext->get_version_minor() << std::endl;
|
||||
|
||||
window::config winconfig = {
|
||||
string{"fennec_test_platform"},
|
||||
window::flags_none,
|
||||
1280, 720,
|
||||
window::fullscreen_mode::windowed
|
||||
};
|
||||
window* window = display->create_window(nullptr);
|
||||
|
||||
fennec_test_run(window != nullptr, true);
|
||||
|
||||
window->configure(winconfig);
|
||||
window->initialize(false);
|
||||
|
||||
fennec_test_run(window->running(), true);
|
||||
|
||||
delete window;
|
||||
instance->shutdown();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user