Compare commits
6 commits
main
...
fix/clang-
Author | SHA1 | Date | |
---|---|---|---|
1c8d4abed4 | |||
93faae4553 | |||
664a267640 | |||
f0e09cab86 | |||
b58e022389 | |||
978291bb59 |
263 changed files with 2877 additions and 8461 deletions
155
.drone.yml
155
.drone.yml
|
@ -1,140 +1,57 @@
|
||||||
---
|
|
||||||
kind: pipeline
|
|
||||||
type: exec
|
|
||||||
name: amd64 — msvc
|
|
||||||
trigger:
|
|
||||||
branch:
|
|
||||||
- main
|
|
||||||
platform:
|
|
||||||
os: windows
|
|
||||||
arch: amd64
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: unit tests
|
|
||||||
shell: powershell
|
|
||||||
commands:
|
|
||||||
- ./tools/ci/amd64/msvc/unit_tests.ps1
|
|
||||||
|
|
||||||
---
|
|
||||||
kind: pipeline
|
kind: pipeline
|
||||||
type: docker
|
type: docker
|
||||||
name: amd64 — gcc
|
name: clang format
|
||||||
|
clone:
|
||||||
|
recursive: true
|
||||||
|
submodule_update_remote: true
|
||||||
|
|
||||||
trigger:
|
trigger:
|
||||||
branch:
|
branch:
|
||||||
- main
|
- main
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: unit tests
|
|
||||||
image: amd64_gcc_unit_tests:latest
|
|
||||||
pull: if-not-exists
|
|
||||||
commands:
|
|
||||||
- ./tools/ci/amd64/gcc/unit_tests.sh
|
|
||||||
|
|
||||||
- name: valgrind
|
|
||||||
image: amd64_gcc_valgrind:latest
|
|
||||||
pull: if-not-exists
|
|
||||||
commands:
|
|
||||||
- ./tools/ci/amd64/gcc/valgrind.sh
|
|
||||||
|
|
||||||
---
|
|
||||||
kind: pipeline
|
|
||||||
type: docker
|
|
||||||
name: amd64 — clang
|
|
||||||
trigger:
|
|
||||||
branch:
|
|
||||||
- main
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: code coverage
|
|
||||||
image: amd64_clang_coverage:latest
|
|
||||||
pull: if-not-exists
|
|
||||||
environment:
|
|
||||||
CODECOV_TOKEN:
|
|
||||||
from_secret: CODECOV_TOKEN
|
|
||||||
commands:
|
|
||||||
- ./tools/ci/amd64/clang/coverage.sh
|
|
||||||
|
|
||||||
- name: leak sanitizer
|
|
||||||
image: amd64_clang_lsan:latest
|
|
||||||
pull: if-not-exists
|
|
||||||
commands:
|
|
||||||
- ./tools/ci/amd64/clang/lsan.sh
|
|
||||||
|
|
||||||
- name: memory sanitizer
|
|
||||||
image: amd64_clang_msan:latest
|
|
||||||
pull: if-not-exists
|
|
||||||
commands:
|
|
||||||
- ./tools/ci/amd64/clang/msan.sh
|
|
||||||
|
|
||||||
---
|
|
||||||
kind: pipeline
|
|
||||||
type: docker
|
|
||||||
name: static analysis
|
|
||||||
trigger:
|
|
||||||
branch:
|
|
||||||
- main
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: clang tidy
|
|
||||||
image: clang_tidy:latest
|
|
||||||
pull: if-not-exists
|
|
||||||
privileged: true
|
|
||||||
commands:
|
|
||||||
- ./tools/ci/static_analysis/clang_tidy.sh
|
|
||||||
|
|
||||||
- name: clang format
|
- name: clang format
|
||||||
image: clang_format:latest
|
image: clang_format:latest
|
||||||
pull: if-not-exists
|
pull: if-not-exists
|
||||||
commands:
|
commands:
|
||||||
- ./tools/ci/static_analysis/clang_format.sh
|
- |
|
||||||
|
set -e
|
||||||
|
clang-format --version
|
||||||
|
HAS_ISSUES=0
|
||||||
|
|
||||||
|
for file in $(find ./modules -name '*.?pp'); do
|
||||||
|
echo "Checking format for $file"
|
||||||
|
if ! clang-format --dry-run --Werror "$file"; then
|
||||||
|
echo "❌ Formatting issue detected in $file"
|
||||||
|
HAS_ISSUES=1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ "$HAS_ISSUES" -eq 0 ]; then
|
||||||
|
echo "✅ All files are properly formatted! Well done! ^~^"
|
||||||
|
else
|
||||||
|
echo "❌ Senpai! There was some formatting issues :c"
|
||||||
|
fi
|
||||||
|
|
||||||
|
exit $HAS_ISSUES
|
||||||
---
|
---
|
||||||
|
|
||||||
kind: pipeline
|
kind: pipeline
|
||||||
type: docker
|
type: docker
|
||||||
name: documentation — development
|
name: static analysis
|
||||||
node:
|
clone:
|
||||||
environment: ryali
|
recursive: true
|
||||||
|
submodule_update_remote: true
|
||||||
|
|
||||||
trigger:
|
trigger:
|
||||||
branch:
|
branch:
|
||||||
- main
|
- main
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: build and deploy
|
- name: static_analysis
|
||||||
image: documentation:latest
|
image: static_analysis:latest
|
||||||
pull: if-not-exists
|
pull: if-not-exists
|
||||||
|
privileged: true
|
||||||
commands:
|
commands:
|
||||||
- pwd
|
- git submodule update --init --recursive
|
||||||
- cd docs
|
- conan build . -s build_type=Release -o enable_static_analysis=True --build=missing
|
||||||
- mkdir generated
|
|
||||||
- touch generated/changelogs.rst
|
|
||||||
- touch generated/api.rst
|
|
||||||
- sphinx-build -M html . .
|
|
||||||
|
|
||||||
- rm -rf /light_docs_dev/*
|
|
||||||
- mv ./html/* /light_docs_dev/
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
kind: pipeline
|
|
||||||
type: docker
|
|
||||||
name: documentation — production
|
|
||||||
node:
|
|
||||||
environment: ryali
|
|
||||||
trigger:
|
|
||||||
event:
|
|
||||||
- tag
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: build and deploy
|
|
||||||
image: documentation:latest
|
|
||||||
pull: if-not-exists
|
|
||||||
commands:
|
|
||||||
- pwd
|
|
||||||
- cd docs
|
|
||||||
- mkdir generated
|
|
||||||
- touch generated/changelogs.rst
|
|
||||||
- touch generated/api.rst
|
|
||||||
- sphinx-build -M html . .
|
|
||||||
|
|
||||||
- rm -rf /light_docs/*
|
|
||||||
- mv ./html/* /light_docs/
|
|
||||||
|
|
36
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
36
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
---
|
||||||
|
name: Bug report
|
||||||
|
about: Create a report to help us improve
|
||||||
|
title: "[BUG]: "
|
||||||
|
labels: ''
|
||||||
|
assignees: Light3039
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Describe the bug**
|
||||||
|
A clear and concise description of what the bug is.
|
||||||
|
|
||||||
|
**Expected behavior**
|
||||||
|
A clear and concise description of what you expected to happen.
|
||||||
|
|
||||||
|
**To Reproduce**
|
||||||
|
Steps to reproduce the behavior:
|
||||||
|
1. Make projects "..."
|
||||||
|
2. Build projects "..."
|
||||||
|
3. Run project (Mirror/Sandbox) "..."
|
||||||
|
4. Do "..."
|
||||||
|
5. See bug "..."
|
||||||
|
|
||||||
|
**System (you can omit any of the fields except OS and Console's debug output):**
|
||||||
|
- OS: [e.g. Manjaro Linux v21.1.0]
|
||||||
|
- GPU: [e.g. NVIDIA GeForce GTX 1050 Ti Mobile]
|
||||||
|
- CPU: [e.g. Intel i7-7700HQ (8) @ 3.800GHz]
|
||||||
|
|
||||||
|
- Console's debug output (omit if bug occurs before running the program):
|
||||||
|
|
||||||
|
**Screenshots**
|
||||||
|
If applicable, add screenshots to help explain your problem.
|
||||||
|
If possible add screen shot of console's debug output and neofetch.
|
||||||
|
|
||||||
|
**Additional context**
|
||||||
|
Add any other context about the problem here.
|
4
.gitmodules
vendored
4
.gitmodules
vendored
|
@ -0,0 +1,4 @@
|
||||||
|
[submodule "external/imgui"]
|
||||||
|
path = external/imgui
|
||||||
|
url = https://github.com/ocornut/imgui
|
||||||
|
branch = docking
|
|
@ -1,43 +1,30 @@
|
||||||
cmake_minimum_required(VERSION 3.14)
|
cmake_minimum_required(VERSION 3.14)
|
||||||
project(Light)
|
project(Light)
|
||||||
set(CMAKE_CXX_STANDARD 23)
|
set(CMAKE_CXX_STANDARD 23)
|
||||||
set(CMAKE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/tools/cmake)
|
|
||||||
|
|
||||||
include(CheckCXXSourceCompiles)
|
include(${CMAKE_CURRENT_SOURCE_DIR}/tools/cmake/macros.cmake)
|
||||||
include(${CMAKE_DIR}/functions.cmake)
|
|
||||||
include(${CMAKE_DIR}/definitions.cmake)
|
|
||||||
include(${CMAKE_DIR}/dependencies.cmake)
|
|
||||||
|
|
||||||
add_option(ENABLE_UNIT_TESTS "Enables the building of the unit test modules")
|
add_option(ENABLE_STATIC_ANALYSIS "Enables clang-tidy static analysis")
|
||||||
add_option(ENABLE_FUZZ_TESTS "Enables the building of the fuzz test modules")
|
|
||||||
|
|
||||||
add_option(ENABLE_STATIC_ANALYSIS "Makes clang-tidy checks mandatory for compilation")
|
|
||||||
if (ENABLE_STATIC_ANALYSIS)
|
if (ENABLE_STATIC_ANALYSIS)
|
||||||
set(CMAKE_CXX_CLANG_TIDY "clang-tidy;--warnings-as-errors=*;--allow-no-checks")
|
set(CMAKE_CXX_CLANG_TIDY "clang-tidy;--warnings-as-errors=*;--allow-no-checks")
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
add_option(ENABLE_LLVM_COVERAGE "Enables the code coverage instrumentation for clang")
|
if(WIN32)
|
||||||
if(ENABLE_LLVM_COVERAGE)
|
add_compile_definitions(LIGHT_PLATFORM_WINDOWS)
|
||||||
if (NOT "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
elseif(UNIX)
|
||||||
message(FATAL_ERROR "ENABLE_LLVM_COVERAGE only supports the clang compiler")
|
add_compile_definitions(LIGHT_PLATFORM_LINUX)
|
||||||
endif ()
|
endif()
|
||||||
|
|
||||||
# Check for libc++
|
find_package(glfw3 REQUIRED)
|
||||||
check_cxx_source_compiles("
|
find_package(glm REQUIRED)
|
||||||
#include <string>
|
find_package(spdlog REQUIRED)
|
||||||
#ifdef _LIBCPP_VERSION
|
find_package(stb REQUIRED)
|
||||||
int main() { return 0; }
|
find_package(yaml-cpp REQUIRED)
|
||||||
#else
|
find_package(EnTT REQUIRED)
|
||||||
#error Not using libc++
|
find_package(opengl_system REQUIRED)
|
||||||
#endif
|
find_package(nlohmann_json REQUIRED)
|
||||||
" USING_LIBCXX)
|
find_package(lz4 REQUIRED)
|
||||||
if(NOT USING_LIBCXX)
|
|
||||||
message(FATAL_ERROR "ENABLE_LLVM_COVERAGE requires libc++, please compile with -stdlib=libc++")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
add_compile_options(-fprofile-instr-generate -fcoverage-mapping)
|
add_subdirectory(./modules)
|
||||||
add_link_options(-fprofile-instr-generate -fcoverage-mapping)
|
add_subdirectory(./external)
|
||||||
endif ()
|
|
||||||
|
|
||||||
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/modules)
|
|
||||||
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/external/glad)
|
|
||||||
|
|
|
@ -1,6 +1,2 @@
|
||||||
# Light
|
# Light
|
||||||
See docs.light7734.com for a comprehensive project documentation
|
See docs.light7734.com for a comprehensive project documentation
|
||||||
|
|
||||||
<!---FUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUCK
|
|
||||||
MEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE
|
|
||||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA!!!!!!!!-->
|
|
||||||
|
|
23
conanfile.py
23
conanfile.py
|
@ -11,29 +11,26 @@ class LightRecipe(ConanFile):
|
||||||
generators = "CMakeDeps"
|
generators = "CMakeDeps"
|
||||||
|
|
||||||
options = {
|
options = {
|
||||||
"enable_unit_tests": [True, False],
|
|
||||||
"enable_fuzz_tests": [True, False],
|
|
||||||
"enable_llvm_coverage": [True, False],
|
|
||||||
"enable_static_analysis": [True, False],
|
"enable_static_analysis": [True, False],
|
||||||
"use_mold": [True, False],
|
|
||||||
"export_compile_commands": [True, False],
|
"export_compile_commands": [True, False],
|
||||||
}
|
}
|
||||||
|
|
||||||
default_options = {
|
default_options = {
|
||||||
"enable_unit_tests": True,
|
|
||||||
"enable_fuzz_tests": False,
|
|
||||||
"enable_llvm_coverage": False,
|
|
||||||
"enable_static_analysis": False,
|
|
||||||
"use_mold": False,
|
|
||||||
"export_compile_commands": True,
|
"export_compile_commands": True,
|
||||||
|
"enable_static_analysis": False,
|
||||||
}
|
}
|
||||||
|
|
||||||
def requirements(self):
|
def requirements(self):
|
||||||
self.requires("imgui/1.92.0-docking")
|
self.requires("gtest/1.16.0")
|
||||||
self.requires("entt/3.15.0")
|
self.requires("entt/3.15.0")
|
||||||
self.requires("glfw/3.4")
|
self.requires("glfw/3.4")
|
||||||
|
self.requires("glm/1.0.1")
|
||||||
|
self.requires("spdlog/1.15.3")
|
||||||
|
self.requires("spirv-cross/1.4.313.0")
|
||||||
self.requires("stb/cci.20240531")
|
self.requires("stb/cci.20240531")
|
||||||
|
self.requires("volk/1.3.296.0")
|
||||||
self.requires("yaml-cpp/0.8.0")
|
self.requires("yaml-cpp/0.8.0")
|
||||||
|
self.requires("nlohmann_json/3.12.0")
|
||||||
self.requires("lz4/1.10.0")
|
self.requires("lz4/1.10.0")
|
||||||
|
|
||||||
def layout(self):
|
def layout(self):
|
||||||
|
@ -44,13 +41,7 @@ class LightRecipe(ConanFile):
|
||||||
|
|
||||||
tc.variables["CMAKE_BUILD_TYPE"] = self.settings.build_type
|
tc.variables["CMAKE_BUILD_TYPE"] = self.settings.build_type
|
||||||
|
|
||||||
if self.options.use_mold:
|
|
||||||
tc.cache_variables["CMAKE_LINKER_TYPE"] = "MOLD"
|
|
||||||
|
|
||||||
tc.cache_variables["CMAKE_EXPORT_COMPILE_COMMANDS"] = self.options.export_compile_commands
|
tc.cache_variables["CMAKE_EXPORT_COMPILE_COMMANDS"] = self.options.export_compile_commands
|
||||||
tc.cache_variables["ENABLE_UNIT_TESTS"] = self.options.enable_unit_tests
|
|
||||||
tc.cache_variables["ENABLE_FUZZ_TESTS"] = self.options.enable_fuzz_tests
|
|
||||||
tc.cache_variables["ENABLE_LLVM_COVERAGE"] = self.options.enable_llvm_coverage
|
|
||||||
tc.cache_variables["ENABLE_STATIC_ANALYSIS"] = self.options.enable_static_analysis
|
tc.cache_variables["ENABLE_STATIC_ANALYSIS"] = self.options.enable_static_analysis
|
||||||
|
|
||||||
repo = git.Repo(search_parent_directories=True)
|
repo = git.Repo(search_parent_directories=True)
|
||||||
|
|
3
docs/.gitignore
vendored
3
docs/.gitignore
vendored
|
@ -1,3 +0,0 @@
|
||||||
_build/
|
|
||||||
generated/
|
|
||||||
|
|
|
@ -1,72 +1,62 @@
|
||||||
Asset Management
|
Asset Management
|
||||||
===================================================================================================
|
===================================================================================================
|
||||||
|
Layout
|
||||||
On Disk (file) Layout
|
|
||||||
---------------------------------------------------------------------------------------------------
|
---------------------------------------------------------------------------------------------------
|
||||||
|
{version} | 4 bytes, ie. uint32_t
|
||||||
.. code-block:: md
|
{general metadata} | sizeof(AssetMetadata)
|
||||||
|
{specialized metadata} | sizeof(XXXAssetMetadata), eg. TextureAssetMetadata
|
||||||
{version} | 4 bytes, ie. uint32_t
|
{n} | 4 bytes, ie. uint32_t
|
||||||
{general metadata} | sizeof(AssetMetadata)
|
{blob_0...n metadata} | n * sizeof(BlobMetadata)
|
||||||
{specialized metadata} | sizeof(XXXAssetMetadata), eg. TextureAssetMetadata
|
{blob_0...n data} | variable size based on actual data
|
||||||
{n} | 4 bytes, ie. uint32_t
|
{end marker} | 8 byte, ie size_t for marking the END
|
||||||
{blob_0...n metadata} | n * sizeof(BlobMetadata)
|
|
||||||
{blob_0...n data} | variable size based on actual data
|
|
||||||
{end marker} | 8 byte, ie size_t for marking the END
|
|
||||||
|
|
||||||
Sections
|
Sections
|
||||||
---------------------------------------------------------------------------------------------------
|
---------------------------------------------------------------------------------------------------
|
||||||
|
version -> The version of the asset for forward compatibility
|
||||||
.. code-block:: md
|
general metadata -> Common asset metadata such as file-path, asset-type, creator, etc.
|
||||||
|
specialized metadata -> Metadata specific to the asset, eg. texture dimensions for Textures.
|
||||||
version -> The version of the asset for forward compatibility
|
n -> The number of blobs.
|
||||||
general metadata -> Common asset metadata such as file-path, asset-type, creator, etc.
|
blob_0...n metadata -> Metadata specifying how the actual data is packed, required for unpacking.
|
||||||
specialized metadata -> Metadata specific to the asset, eg. texture dimensions for Textures.
|
blob_0...n data -> The actual data, packed and compressed to be reacdy for direct engine consumption.
|
||||||
n -> The number of blobs.
|
|
||||||
blob_0...n metadata -> Metadata specifying how the actual data is packed, required for unpacking.
|
|
||||||
blob_0...n data -> The actual data, packed and compressed to be reacdy for direct engine consumption.
|
|
||||||
|
|
||||||
Loading
|
Loading
|
||||||
---------------------------------------------------------------------------------------------------
|
---------------------------------------------------------------------------------------------------
|
||||||
Loading pre-baked asset files (like .png files) for baking:
|
Each `Loader` has ONE OR MORE supported input file types (detected via the file extension): eg. StbLoader -> Can read in .jpg, .png, .bmp, etc.... files
|
||||||
|
|
||||||
|
Each `Loader` has ONLY ONE supported output asset type:
|
||||||
Each **Loader** has ONE OR MORE supported input file types (detected via the file extension): eg. StbLoader -> Can read in .jpg, .png, .bmp, etc.... files
|
|
||||||
|
|
||||||
Each **Loader** has ONLY ONE supported output asset type:
|
|
||||||
eg. StbLoader -> outputs TextureAsset
|
eg. StbLoader -> outputs TextureAsset
|
||||||
|
|
||||||
Multiple **Loader**\s MAY have as output the same asset type:
|
Multiple `Loader`s MAY have as output the same asset type:
|
||||||
eg. StbLoader -> outputs TextureAsset
|
eg. StbLoader -> outputs TextureAsset
|
||||||
eg. SomeOtherImgLoader -> outputs TextureAsset
|
eg. SomeOtherImgLoader -> outputs TextureAsset
|
||||||
|
|
||||||
Multiple **Loader**\s SHOULD NOT have as input same extension types
|
Multiple `Loader`s SHOULD NOT have as input same extension types
|
||||||
eg. .jpg, .png -> if supported, should only be supported by 1 **Loader** class
|
eg. .jpg, .png -> if supported, should only be supported by 1 `Loader` class
|
||||||
|
|
||||||
Each **Loader** SHOULD read and turn the data from a file (eg. .png for textures) into something
|
Each `Loader` SHOULD read and turn the data from a file (eg. .png for textures) into something
|
||||||
understandable by a **Packer** (not the engine itself).
|
understandable by a `Packer` (not the engine itself).
|
||||||
|
|
||||||
A **Loader** SHOULD NOT be responsible for packing the parsed file data into asset data,
|
A `Loader` SHOULD NOT be responsible for packing the parsed file data into asset data,
|
||||||
as that implies direct understanding of the layout required by the engine.
|
as that implies direct understanding of the layout required by the engine.
|
||||||
|
|
||||||
And if that layout changes, ALL **Loader**s should change accordingly;
|
And if that layout changes, ALL `Loader`s should change accordingly;
|
||||||
which makes a class that's responsible for reading files dependant on the engine's (potentially frequent) internal changes.
|
which makes a class that's responsible for reading files dependant on the engine's (potentially frequent) internal changes.
|
||||||
The logic is to reduce many-to-one dependency into a one-to-one dependency by redirecting the packing process to **Packer** classes
|
The logic is to reduce many-to-one dependency into a one-to-one dependency by redirecting the packing process to `Packer` classes
|
||||||
|
|
||||||
Packing
|
Packing
|
||||||
---------------------------------------------------------------------------------------------------
|
---------------------------------------------------------------------------------------------------
|
||||||
Each **Packer** is responsible for packing ONLY ONE asset type:
|
Each `Packer` is responsible for packing ONLY ONE asset type:
|
||||||
eg. TexturePacker for packing texture assets from parsed image files.
|
eg. TexturePacker for packing texture assets from parsed image files.
|
||||||
eg. ModelPacker for packing model assets from parsed model files.
|
eg. ModelPacker for packing model assets from parsed model files.
|
||||||
|
|
||||||
Each **Packer** will output ONE OR MORE blobs of data,
|
Each `Packer` will output ONE OR MORE blobs of data,
|
||||||
and for EACH blob of data, it'll write a BlobMetadata, AFTER the specialized metadata (eg. TextureAssetMetadata)
|
and for EACH blob of data, it'll write a BlobMetadata, AFTER the specialized metadata (eg. TextureAssetMetadata)
|
||||||
|
|
||||||
A **Packer** will make use of the **Compressor** classes to compress the data,
|
A `Packer` will make use of the `Compressor` classes to compress the data,
|
||||||
and lay it out in a way that is suitable for the engine's consumption.
|
and lay it out in a way that is suitable for the engine's consumption.
|
||||||
|
|
||||||
Unpacking
|
Unpacking
|
||||||
---------------------------------------------------------------------------------------------------
|
---------------------------------------------------------------------------------------------------
|
||||||
A **Parser** is responsible for parsing ONLY ONE asset type:
|
A `Parser` is responsible for parsing ONLY ONE asset type:
|
||||||
eg. TextureParser for parsing texture assets for direct engine consumption.
|
eg. TextureParser for parsing texture assets for direct engine consumption.
|
||||||
eg. ModelParser for parsing model assets for direct engine consumption.
|
eg. ModelParser for parsing model assets for direct engine consumption.
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
.. architecture/resources
|
|
||||||
|
|
||||||
Resource Management
|
Resource Management
|
||||||
|
|
||||||
===================================================================================================
|
===================================================================================================
|
||||||
|
|
||||||
|
|
27
docs/conf.py
27
docs/conf.py
|
@ -1,27 +0,0 @@
|
||||||
# Configuration file for the Sphinx documentation builder.
|
|
||||||
#
|
|
||||||
# For the full list of built-in configuration values, see the documentation:
|
|
||||||
# https://www.sphinx-doc.org/en/master/usage/configuration.html
|
|
||||||
|
|
||||||
# -- Project information -----------------------------------------------------
|
|
||||||
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
|
|
||||||
|
|
||||||
project = 'light'
|
|
||||||
copyright = '2025, light7734'
|
|
||||||
author = 'light7734'
|
|
||||||
|
|
||||||
# -- General configuration ---------------------------------------------------
|
|
||||||
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
|
|
||||||
|
|
||||||
extensions = []
|
|
||||||
|
|
||||||
templates_path = ['_templates']
|
|
||||||
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# -- Options for HTML output -------------------------------------------------
|
|
||||||
# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output
|
|
||||||
|
|
||||||
html_theme = 'sphinx_rtd_theme'
|
|
||||||
html_static_path = ['_static']
|
|
|
@ -1,68 +0,0 @@
|
||||||
from git import Repo
|
|
||||||
import re
|
|
||||||
|
|
||||||
repo = Repo(search_parent_directories=True)
|
|
||||||
assert not repo.bare
|
|
||||||
|
|
||||||
file_path = "generated/changelog.rst"
|
|
||||||
|
|
||||||
messages = []
|
|
||||||
short_shas = []
|
|
||||||
hex_shas = []
|
|
||||||
logs = []
|
|
||||||
|
|
||||||
remote_url = "https://git.light7734.com/light7734/light/commit"
|
|
||||||
def format_log(commit_type, message, major, minor, patch, short_sha, hex_sha):
|
|
||||||
href = f"{remote_url}/{hex_sha}"
|
|
||||||
version = f"{major}.{minor}.{patch}-kitten+{short_sha}";
|
|
||||||
link = f"`{version} <{remote_url}/{hex_sha}>`__"
|
|
||||||
return f"| **{message}** ({link})"
|
|
||||||
|
|
||||||
for commit in repo.iter_commits():
|
|
||||||
messages.append(commit.summary)
|
|
||||||
short_shas.append(repo.git.rev_parse(commit.hexsha, short=5))
|
|
||||||
hex_shas.append(commit.hexsha)
|
|
||||||
|
|
||||||
ver_major = 0
|
|
||||||
ver_minor = 0
|
|
||||||
ver_patch = 0
|
|
||||||
|
|
||||||
idx = len(messages)
|
|
||||||
for message in reversed(messages):
|
|
||||||
idx = idx - 1;
|
|
||||||
|
|
||||||
commit_type = re.match("^(feat|fix|refactor|perf|build|asset|test|chore|ci|docs)", message)
|
|
||||||
if not commit_type:
|
|
||||||
continue
|
|
||||||
|
|
||||||
match commit_type.group(0):
|
|
||||||
case "feat":
|
|
||||||
ver_minor = ver_minor + 1
|
|
||||||
ver_patch = 0
|
|
||||||
|
|
||||||
case "fix":
|
|
||||||
ver_patch = ver_patch + 1
|
|
||||||
|
|
||||||
case "refactor":
|
|
||||||
ver_patch = ver_patch + 1
|
|
||||||
|
|
||||||
case "perf":
|
|
||||||
ver_patch = ver_patch + 1
|
|
||||||
|
|
||||||
case "build":
|
|
||||||
ver_patch = ver_patch + 1
|
|
||||||
|
|
||||||
case "asset":
|
|
||||||
ver_patch = ver_patch + 1
|
|
||||||
|
|
||||||
logs.append(format_log(commit_type, message, ver_major, ver_minor, ver_patch, short_shas[idx], hex_shas[idx]))
|
|
||||||
|
|
||||||
with open(file_path, "w") as f:
|
|
||||||
f.write(".. changelogs\n\n\n")
|
|
||||||
f.write("Changelogs\n")
|
|
||||||
f.write("==================================================\n\n")
|
|
||||||
|
|
||||||
f.write("KITTEN\n")
|
|
||||||
f.write("--------------------------------------------------\n\n")
|
|
||||||
for log in reversed(logs):
|
|
||||||
f.write(log + '\n')
|
|
|
@ -1,10 +0,0 @@
|
||||||
.. guidelines/conventions
|
|
||||||
|
|
||||||
Coding Conventions
|
|
||||||
===================================================================================================
|
|
||||||
Any line of code added to the engine, must abide by following conventions.
|
|
||||||
They may seem arbitrary, and sometimes they are. But to achieve **consistency**, which is not an arbitrary goal, is to
|
|
||||||
follow these guidelines.
|
|
||||||
|
|
||||||
AAA
|
|
||||||
--------------------
|
|
|
@ -1,147 +0,0 @@
|
||||||
.. guidelines/development
|
|
||||||
|
|
||||||
Development
|
|
||||||
===================================================================================================
|
|
||||||
As a solo-project, I am not only the **developer**, but also the **manager**.
|
|
||||||
Therefore there is a need, if this project is to succeed, to have a development plan.
|
|
||||||
|
|
||||||
Such a plan should:
|
|
||||||
|
|
||||||
- Define a way to **distribute work** (across time, since there's only 1 developer).
|
|
||||||
- Define what is a **unit of work** (cycles).
|
|
||||||
- Provide a way to **track productivity**, which helps projecting the future and **detecting patterns** early on.
|
|
||||||
- Provide a **pipeline** for the work to go through and **minimize ambiguity**.
|
|
||||||
|
|
||||||
These are the **management** aspects of the project, which help the development goals to be more **pragmatic**
|
|
||||||
---by pulling my mind out of its **engineering dreamland**, and make it focus on the **broader picture**.
|
|
||||||
|
|
||||||
Cycle
|
|
||||||
---------------------------------------------------------------------------------------------------
|
|
||||||
A cycle is one **step** in development, one cycle = one ticket, and it consists of 4 stages:
|
|
||||||
|
|
||||||
1 - Make it known
|
|
||||||
- Write the commit message.
|
|
||||||
- This limits the **scope of changes** and gives you a very specific **goal** to work towards.
|
|
||||||
- If something outside of this scope really bothers you, fix and stash for a future cycle.
|
|
||||||
- Make a ticket if stash-fix is implausible ---**DO NOT** write **todo** comments.
|
|
||||||
- The message should follow the project's **commit message specifications**.
|
|
||||||
|
|
||||||
- Make a ticket.
|
|
||||||
- Version control (git) is a **development-tool**, not a **management-tool**.
|
|
||||||
- Provide a very brief description ---This may be used in the commit message's body.
|
|
||||||
|
|
||||||
2 - Make it work
|
|
||||||
- Write high-level tests that confirms the cycle's requirements are met.
|
|
||||||
- That is, specify requirements in a programming language instead of English.
|
|
||||||
- You're done when all the tests pass.
|
|
||||||
- Preferably write the tests first, but it's okay to start with the interface.
|
|
||||||
- Tests may not be necessary depending on the requirements and commit type.
|
|
||||||
|
|
||||||
- "Make it work" doesn't mean liberally producing shit code, you should:
|
|
||||||
- Follow project's **conventions**.
|
|
||||||
- Follow **best practices** and **proven swe principles**.
|
|
||||||
- Enable **warnings as errors**.
|
|
||||||
- Enable **static analysis**.
|
|
||||||
- Don't break any pre-existing-tests.
|
|
||||||
- Have the over-all picture in mind.
|
|
||||||
|
|
||||||
3 - Make it right
|
|
||||||
- Test driven refactoring
|
|
||||||
- Now you have a better picture of how things relate and work.
|
|
||||||
- Switch to a TDD-style development to do the refactoring while following swe best-practices and proven-principles.
|
|
||||||
|
|
||||||
4 - Make it fast
|
|
||||||
- This is an engine, at the end of the day, **performance** is king.
|
|
||||||
- Get a performance and/or memory profile and try to alleviate the bottlenecks.
|
|
||||||
- Avoid premature optimizations, be certain what you change has performance benefits.
|
|
||||||
|
|
||||||
|
|
||||||
Sprint
|
|
||||||
---------------------------------------------------------------------------------------------------
|
|
||||||
A sprint is the collection of all the finished cycles in one week.
|
|
||||||
It's meant to provide insight on development speed and help projecting the future.
|
|
||||||
|
|
||||||
|
|
||||||
Commit Message Specification
|
|
||||||
---------------------------------------------------------------------------------------------------
|
|
||||||
The project follows the `Conventional Commits Specification <https://www.conventionalcommits.org/en/v1.0.0-beta.4>`_.
|
|
||||||
|
|
||||||
.. code-block:: md
|
|
||||||
|
|
||||||
<type>[optional scope]: <description>
|
|
||||||
|
|
||||||
[optional body]
|
|
||||||
|
|
||||||
[optional footer]
|
|
||||||
|
|
||||||
With the following commit types:
|
|
||||||
|
|
||||||
- feat
|
|
||||||
- For adding a new feature.
|
|
||||||
- Causes a **minor** bump in version.
|
|
||||||
|
|
||||||
- fix
|
|
||||||
- For changes that fix one or more bug.
|
|
||||||
- Causes a **patch** bump in version.
|
|
||||||
|
|
||||||
- refactor
|
|
||||||
- For non feat/fix changes that improve the implementation and/or the interface.
|
|
||||||
- Causes a **patch** bump in version.
|
|
||||||
|
|
||||||
- perf
|
|
||||||
- For changes that (hopefully) improve the performance.
|
|
||||||
- Causes a **patch** bump in version.
|
|
||||||
|
|
||||||
- build
|
|
||||||
- For changes that affect the build system or external dependencies.
|
|
||||||
- Causes a **patch** bump in version.
|
|
||||||
|
|
||||||
- asset
|
|
||||||
- For changes to the files under the ``/data`` directory.
|
|
||||||
- Causes a **patch** bump in version.
|
|
||||||
|
|
||||||
- test
|
|
||||||
- For adding missing tests or correcting the existing tests.
|
|
||||||
- Does not affect the version.
|
|
||||||
|
|
||||||
- chore
|
|
||||||
- For releases, .gitignore changes, deleting unused files, etc.
|
|
||||||
- Does not affect the version.
|
|
||||||
|
|
||||||
- ci
|
|
||||||
- For changes to our CI configuration files and scripts, including files under ``/tools/ci``.
|
|
||||||
- Does not affect the version.
|
|
||||||
|
|
||||||
- docs
|
|
||||||
- For changes to the documentations.
|
|
||||||
- Does not affect the version.
|
|
||||||
|
|
||||||
Semantic Versioning
|
|
||||||
---------------------------------------------------------------------------------------------------
|
|
||||||
Coupled with conventional commit style messages, we can automajically version the project following
|
|
||||||
the **Semantic Versioning 2.0.0** specifications.
|
|
||||||
|
|
||||||
The full version identifier consits of a version core (major.minor.patch) + label + hexsha of the commit.
|
|
||||||
Using the following format:
|
|
||||||
|
|
||||||
|
|
||||||
.. code-block:: md
|
|
||||||
|
|
||||||
<major>.<minor>.<patch>-<label>+<short_hexsha>
|
|
||||||
|
|
||||||
eg.
|
|
||||||
0.8.1-kitten+ea898
|
|
||||||
0.5.0-kitten+01d85
|
|
||||||
1.5.0-akasha+7de53
|
|
||||||
|
|
||||||
kitten refers to all pre-release (1.0.0) versions
|
|
||||||
|
|
||||||
|
|
||||||
The shortened hexsha of a commit is obtained by:
|
|
||||||
``git rev-parse --short=5 <commit_hexsha>``
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
.. guidelines/philosophy
|
|
||||||
|
|
||||||
Philosophy
|
|
||||||
===================================================================================================
|
|
||||||
|
|
||||||
| **A theory or attitude that acts as a guiding principle for behaviour.**
|
|
||||||
| --- Oxford Languages
|
|
|
@ -1,32 +0,0 @@
|
||||||
.. light documentation
|
|
||||||
|
|
||||||
.. toctree::
|
|
||||||
:maxdepth: 2
|
|
||||||
:caption: Light Engine
|
|
||||||
|
|
||||||
light/showcase.rst
|
|
||||||
light/features.rst
|
|
||||||
|
|
||||||
.. toctree::
|
|
||||||
:maxdepth: 2
|
|
||||||
:caption: Software Architecture
|
|
||||||
|
|
||||||
architecture/assets.rst
|
|
||||||
architecture/resource.rst
|
|
||||||
|
|
||||||
.. toctree::
|
|
||||||
:maxdepth: 2
|
|
||||||
:caption: Development Guidelines
|
|
||||||
|
|
||||||
guidelines/philosophy.rst
|
|
||||||
guidelines/development.rst
|
|
||||||
guidelines/conventions.rst
|
|
||||||
|
|
||||||
.. toctree::
|
|
||||||
:maxdepth: 2
|
|
||||||
:caption: Generated Docs
|
|
||||||
|
|
||||||
generated/api.rst
|
|
||||||
generated/changelog.rst
|
|
||||||
|
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
.. light/features
|
|
||||||
|
|
||||||
Features
|
|
||||||
===================================================================================================
|
|
|
@ -1,4 +0,0 @@
|
||||||
.. light/demos
|
|
||||||
|
|
||||||
Showcase
|
|
||||||
===================================================================================================
|
|
|
@ -1,35 +0,0 @@
|
||||||
@ECHO OFF
|
|
||||||
|
|
||||||
pushd %~dp0
|
|
||||||
|
|
||||||
REM Command file for Sphinx documentation
|
|
||||||
|
|
||||||
if "%SPHINXBUILD%" == "" (
|
|
||||||
set SPHINXBUILD=sphinx-build
|
|
||||||
)
|
|
||||||
set SOURCEDIR=.
|
|
||||||
set BUILDDIR=_build
|
|
||||||
|
|
||||||
%SPHINXBUILD% >NUL 2>NUL
|
|
||||||
if errorlevel 9009 (
|
|
||||||
echo.
|
|
||||||
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
|
|
||||||
echo.installed, then set the SPHINXBUILD environment variable to point
|
|
||||||
echo.to the full path of the 'sphinx-build' executable. Alternatively you
|
|
||||||
echo.may add the Sphinx directory to PATH.
|
|
||||||
echo.
|
|
||||||
echo.If you don't have Sphinx installed, grab it from
|
|
||||||
echo.https://www.sphinx-doc.org/
|
|
||||||
exit /b 1
|
|
||||||
)
|
|
||||||
|
|
||||||
if "%1" == "" goto help
|
|
||||||
|
|
||||||
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
|
|
||||||
goto end
|
|
||||||
|
|
||||||
:help
|
|
||||||
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
|
|
||||||
|
|
||||||
:end
|
|
||||||
popd
|
|
58
external/CMakeLists.txt
vendored
Normal file
58
external/CMakeLists.txt
vendored
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
# GLAD #
|
||||||
|
add_subdirectory(./glad)
|
||||||
|
|
||||||
|
set(MIRROR_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../modules/mirror/)
|
||||||
|
set(DEPENDENCIES_DIR ${CMAKE_CURRENT_SOURCE_DIR}/)
|
||||||
|
|
||||||
|
if (CMAKE_COMPILER_IS_GNUCC)
|
||||||
|
add_compile_options(-w)
|
||||||
|
endif()
|
||||||
|
if(MSVC)
|
||||||
|
add_compile_options(/MP)
|
||||||
|
add_compile_options(/W0)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
file(GLOB IMGUI_FILES true ABSOLUTE
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/imgui/imgui.cpp
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/imgui/imgui_tables.cpp
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/imgui/imgui_widgets.cpp
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/imgui/imgui_draw.cpp
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/imgui/imgui_demo.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
set(BACKENDS_DIR ${CMAKE_CURRENT_SOURCE_DIR}/imgui/backends/)
|
||||||
|
|
||||||
|
|
||||||
|
file(GLOB IMGUI_BACKEND_FILES true ABSOLUTE
|
||||||
|
${BACKENDS_DIR}imgui_impl_opengl3.cpp
|
||||||
|
${BACKENDS_DIR}imgui_impl_glfw.cpp
|
||||||
|
# ${BACKENDS_DIR}imgui_impl_vulkan.cpp ${BACKENDS_DIR}imgui_impl_vulkan.h
|
||||||
|
)
|
||||||
|
|
||||||
|
if(WIN32)
|
||||||
|
file(GLOB IMGUI_WINDOWS_BACKEND_FILES true ABSOLUTE ${CMAKE_CURRENT_SOURCE_DIR}/backends/
|
||||||
|
${BACKENDS_DIR}imgui_impl_dx11.cpp
|
||||||
|
${BACKENDS_DIR}imgui_impl_win32.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
list(APPEND IMGUI_BACKEND_FILES ${IMGUI_WINDOWS_BACKEND_FILES})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_compile_definitions(IMGUI_IMPL_OPENGL_LOADER_GLAD)
|
||||||
|
include_directories(${DEPENDENCIES_DIR}GLFW/include)
|
||||||
|
include_directories(${DEPENDENCIES_DIR}glm/)
|
||||||
|
|
||||||
|
add_library(imgui STATIC ${IMGUI_FILES} ${IMGUI_BACKEND_FILES})
|
||||||
|
|
||||||
|
target_include_directories(imgui PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/imgui)
|
||||||
|
target_link_libraries(
|
||||||
|
imgui
|
||||||
|
PUBLIC glad
|
||||||
|
PUBLIC opengl::opengl
|
||||||
|
PUBLIC glm::glm
|
||||||
|
PUBLIC glfw
|
||||||
|
)
|
||||||
|
|
||||||
|
# Copy imconfig.h over
|
||||||
|
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/configurations/imgui/imconfig.h
|
||||||
|
DESTINATION ${CMAKE_CURRENT_SOURCE_DIR}/imgui/)
|
131
external/configurations/imgui/imconfig.h
vendored
Normal file
131
external/configurations/imgui/imconfig.h
vendored
Normal file
|
@ -0,0 +1,131 @@
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// COMPILE-TIME OPTIONS FOR DEAR IMGUI
|
||||||
|
// Runtime options (clipboard callbacks, enabling various features, etc.) can generally be set via the ImGuiIO structure.
|
||||||
|
// You can use ImGui::SetAllocatorFunctions() before calling ImGui::CreateContext() to rewire memory allocation functions.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// A) You may edit imconfig.h (and not overwrite it when updating Dear ImGui, or maintain a patch/rebased branch with your modifications to it)
|
||||||
|
// B) or '#define IMGUI_USER_CONFIG "my_imgui_config.h"' in your project and then add directives in your own file without touching this template.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// You need to make sure that configuration settings are defined consistently _everywhere_ Dear ImGui is used, which include the imgui*.cpp
|
||||||
|
// files but also _any_ of your code that uses Dear ImGui. This is because some compile-time options have an affect on data structures.
|
||||||
|
// Defining those options in imconfig.h will ensure every compilation unit gets to see the same data structure layouts.
|
||||||
|
// Call IMGUI_CHECKVERSION() from your .cpp files to verify that the data structures your files are using are matching the ones imgui.cpp is using.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
//---- Define assertion handler. Defaults to calling assert().
|
||||||
|
// If your macro uses multiple statements, make sure is enclosed in a 'do { .. } while (0)' block so it can be used as a single statement.
|
||||||
|
//#define IM_ASSERT(_EXPR) MyAssert(_EXPR)
|
||||||
|
//#define IM_ASSERT(_EXPR) ((void)(_EXPR)) // Disable asserts
|
||||||
|
|
||||||
|
//---- Define attributes of all API symbols declarations, e.g. for DLL under Windows
|
||||||
|
// Using Dear ImGui via a shared library is not recommended, because of function call overhead and because we don't guarantee backward nor forward ABI compatibility.
|
||||||
|
// DLL users: heaps and globals are not shared across DLL boundaries! You will need to call SetCurrentContext() + SetAllocatorFunctions()
|
||||||
|
// for each static/DLL boundary you are calling from. Read "Context and Memory Allocators" section of imgui.cpp for more details.
|
||||||
|
//#define IMGUI_API __declspec( dllexport )
|
||||||
|
//#define IMGUI_API __declspec( dllimport )
|
||||||
|
|
||||||
|
//---- Don't define obsolete functions/enums/behaviors. Consider enabling from time to time after updating to avoid using soon-to-be obsolete function/names.
|
||||||
|
//#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||||
|
//#define IMGUI_DISABLE_OBSOLETE_KEYIO // 1.87: disable legacy io.KeyMap[]+io.KeysDown[] in favor io.AddKeyEvent(). This will be folded into IMGUI_DISABLE_OBSOLETE_FUNCTIONS in a few versions.
|
||||||
|
|
||||||
|
//---- Disable all of Dear ImGui or don't implement standard windows.
|
||||||
|
// It is very strongly recommended to NOT disable the demo windows during development. Please read comments in imgui_demo.cpp.
|
||||||
|
//#define IMGUI_DISABLE // Disable everything: all headers and source files will be empty.
|
||||||
|
//#define IMGUI_DISABLE_DEMO_WINDOWS // Disable demo windows: ShowDemoWindow()/ShowStyleEditor() will be empty. Not recommended.
|
||||||
|
//#define IMGUI_DISABLE_METRICS_WINDOW // Disable metrics/debugger and other debug tools: ShowMetricsWindow() and ShowStackToolWindow() will be empty.
|
||||||
|
|
||||||
|
//---- Don't implement some functions to reduce linkage requirements.
|
||||||
|
//#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS // [Win32] Don't implement default clipboard handler. Won't use and link with OpenClipboard/GetClipboardData/CloseClipboard etc. (user32.lib/.a, kernel32.lib/.a)
|
||||||
|
//#define IMGUI_ENABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] [Default with Visual Studio] Implement default IME handler (require imm32.lib/.a, auto-link for Visual Studio, -limm32 on command-line for MinGW)
|
||||||
|
//#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] [Default with non-Visual Studio compilers] Don't implement default IME handler (won't require imm32.lib/.a)
|
||||||
|
//#define IMGUI_DISABLE_WIN32_FUNCTIONS // [Win32] Won't use and link with any Win32 function (clipboard, ime).
|
||||||
|
//#define IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS // [OSX] Implement default OSX clipboard handler (need to link with '-framework ApplicationServices', this is why this is not the default).
|
||||||
|
//#define IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS // Don't implement ImFormatString/ImFormatStringV so you can implement them yourself (e.g. if you don't want to link with vsnprintf)
|
||||||
|
//#define IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS // Don't implement ImFabs/ImSqrt/ImPow/ImFmod/ImCos/ImSin/ImAcos/ImAtan2 so you can implement them yourself.
|
||||||
|
//#define IMGUI_DISABLE_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle at all (replace them with dummies)
|
||||||
|
//#define IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle so you can implement them yourself if you don't want to link with fopen/fclose/fread/fwrite. This will also disable the LogToTTY() function.
|
||||||
|
//#define IMGUI_DISABLE_DEFAULT_ALLOCATORS // Don't implement default allocators calling malloc()/free() to avoid linking with them. You will need to call ImGui::SetAllocatorFunctions().
|
||||||
|
//#define IMGUI_DISABLE_SSE // Disable use of SSE intrinsics even if available
|
||||||
|
|
||||||
|
//---- Include imgui_user.h at the end of imgui.h as a convenience
|
||||||
|
//#define IMGUI_INCLUDE_IMGUI_USER_H
|
||||||
|
|
||||||
|
//---- Pack colors to BGRA8 instead of RGBA8 (to avoid converting from one to another)
|
||||||
|
//#define IMGUI_USE_BGRA_PACKED_COLOR
|
||||||
|
|
||||||
|
//---- Use 32-bit for ImWchar (default is 16-bit) to support unicode planes 1-16. (e.g. point beyond 0xFFFF like emoticons, dingbats, symbols, shapes, ancient languages, etc...)
|
||||||
|
//#define IMGUI_USE_WCHAR32
|
||||||
|
|
||||||
|
//---- Avoid multiple STB libraries implementations, or redefine path/filenames to prioritize another version
|
||||||
|
// By default the embedded implementations are declared static and not available outside of Dear ImGui sources files.
|
||||||
|
//#define IMGUI_STB_TRUETYPE_FILENAME "my_folder/stb_truetype.h"
|
||||||
|
//#define IMGUI_STB_RECT_PACK_FILENAME "my_folder/stb_rect_pack.h"
|
||||||
|
//#define IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION
|
||||||
|
//#define IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION
|
||||||
|
|
||||||
|
//---- Use stb_printf's faster implementation of vsnprintf instead of the one from libc (unless IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS is defined)
|
||||||
|
// Requires 'stb_sprintf.h' to be available in the include path. Compatibility checks of arguments and formats done by clang and GCC will be disabled in order to support the extra formats provided by STB sprintf.
|
||||||
|
// #define IMGUI_USE_STB_SPRINTF
|
||||||
|
|
||||||
|
//---- Use FreeType to build and rasterize the font atlas (instead of stb_truetype which is embedded by default in Dear ImGui)
|
||||||
|
// Requires FreeType headers to be available in the include path. Requires program to be compiled with 'misc/freetype/imgui_freetype.cpp' (in this repository) + the FreeType library (not provided).
|
||||||
|
// On Windows you may use vcpkg with 'vcpkg install freetype --triplet=x64-windows' + 'vcpkg integrate install'.
|
||||||
|
//#define IMGUI_ENABLE_FREETYPE
|
||||||
|
|
||||||
|
//---- Use stb_truetype to build and rasterize the font atlas (default)
|
||||||
|
// The only purpose of this define is if you want force compilation of the stb_truetype backend ALONG with the FreeType backend.
|
||||||
|
//#define IMGUI_ENABLE_STB_TRUETYPE
|
||||||
|
|
||||||
|
//---- Define constructor and implicit cast operators to convert back<>forth between your math types and ImVec2/ImVec4.
|
||||||
|
// This will be inlined as part of ImVec2 and ImVec4 class declarations.
|
||||||
|
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
|
#define IM_VEC2_CLASS_EXTRA \
|
||||||
|
bool operator==(glm::vec2 rhs) { return x == rhs.x && y == rhs.y; } \
|
||||||
|
bool operator!=(glm::vec2 rhs) { return (*this) == rhs; } \
|
||||||
|
bool operator==(ImVec2 rhs) { return x == rhs.x && y == rhs.y; } \
|
||||||
|
bool operator!=(ImVec2 rhs) { return (*this) == rhs; }
|
||||||
|
|
||||||
|
|
||||||
|
#define IM_VEC4_CLASS_EXTRA \
|
||||||
|
bool operator==(glm::vec4 rhs) { return x == rhs.x && y == rhs.y && z == rhs.z && w == rhs.w; } \
|
||||||
|
bool operator!=(glm::vec4 rhs) { return (*this) == rhs; } \
|
||||||
|
bool operator==(ImVec4 rhs) { return x == rhs.x && y == rhs.y && z == rhs.z && w == rhs.w; } \
|
||||||
|
bool operator!=(ImVec4 rhs) { return (*this) == rhs; }
|
||||||
|
|
||||||
|
|
||||||
|
//---- Use 32-bit vertex indices (default is 16-bit) is one way to allow large meshes with more than 64K vertices.
|
||||||
|
// Your renderer backend will need to support it (most example renderer backends support both 16/32-bit indices).
|
||||||
|
// Another way to allow large meshes while keeping 16-bit indices is to handle ImDrawCmd::VtxOffset in your renderer.
|
||||||
|
// Read about ImGuiBackendFlags_RendererHasVtxOffset for details.
|
||||||
|
//#define ImDrawIdx unsigned int
|
||||||
|
|
||||||
|
//---- Override ImDrawCallback signature (will need to modify renderer backends accordingly)
|
||||||
|
//struct ImDrawList;
|
||||||
|
//struct ImDrawCmd;
|
||||||
|
//typedef void (*MyImDrawCallback)(const ImDrawList* draw_list, const ImDrawCmd* cmd, void* my_renderer_user_data);
|
||||||
|
//#define ImDrawCallback MyImDrawCallback
|
||||||
|
|
||||||
|
//---- Debug Tools: Macro to break in Debugger
|
||||||
|
// (use 'Metrics->Tools->Item Picker' to pick widgets with the mouse and break into them for easy debugging.)
|
||||||
|
//#define IM_DEBUG_BREAK IM_ASSERT(0)
|
||||||
|
//#define IM_DEBUG_BREAK __debugbreak()
|
||||||
|
|
||||||
|
//---- Debug Tools: Have the Item Picker break in the ItemAdd() function instead of ItemHoverable(),
|
||||||
|
// (which comes earlier in the code, will catch a few extra items, allow picking items other than Hovered one.)
|
||||||
|
// This adds a small runtime cost which is why it is not enabled by default.
|
||||||
|
//#define IMGUI_DEBUG_TOOL_ITEM_PICKER_EX
|
||||||
|
|
||||||
|
//---- Debug Tools: Enable slower asserts
|
||||||
|
//#define IMGUI_DEBUG_PARANOID
|
||||||
|
|
||||||
|
//---- Tip: You can add extra functions within the ImGui:: namespace, here or in your own headers files.
|
||||||
|
/*
|
||||||
|
namespace ImGui
|
||||||
|
{
|
||||||
|
void MyFunction(const char* name, const MyMatrix44& v);
|
||||||
|
}
|
||||||
|
*/
|
1
external/imgui
vendored
Submodule
1
external/imgui
vendored
Submodule
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit 250333d895b1067533533dcfab137512745b9689
|
|
@ -3,22 +3,22 @@ add_subdirectory(./base)
|
||||||
add_subdirectory(./time)
|
add_subdirectory(./time)
|
||||||
add_subdirectory(./logger)
|
add_subdirectory(./logger)
|
||||||
add_subdirectory(./debug)
|
add_subdirectory(./debug)
|
||||||
add_subdirectory(./math)
|
|
||||||
#
|
|
||||||
add_subdirectory(./asset_baker)
|
add_subdirectory(./asset_baker)
|
||||||
add_subdirectory(./asset_parser)
|
add_subdirectory(./asset_parser)
|
||||||
# add_subdirectory(./asset_manager)
|
add_subdirectory(./asset_manager)
|
||||||
#
|
|
||||||
add_subdirectory(./camera)
|
add_subdirectory(./camera)
|
||||||
# add_subdirectory(./input)
|
add_subdirectory(./input)
|
||||||
# add_subdirectory(./ui)
|
add_subdirectory(./ui)
|
||||||
#
|
|
||||||
add_subdirectory(./surface)
|
add_subdirectory(./window)
|
||||||
# add_subdirectory(./renderer)
|
add_subdirectory(./renderer)
|
||||||
add_subdirectory(./ecs)
|
add_subdirectory(./ecs)
|
||||||
#
|
|
||||||
add_subdirectory(./app)
|
add_subdirectory(./app)
|
||||||
|
|
||||||
# apps
|
# apps
|
||||||
add_subdirectory(./mirror)
|
add_subdirectory(./mirror)
|
||||||
|
|
||||||
add_subdirectory(test)
|
add_subdirectory(test)
|
||||||
|
|
|
@ -1,2 +1,21 @@
|
||||||
add_library_module(app application.cpp)
|
add_library_module(app
|
||||||
target_link_libraries(app PRIVATE lt_debug)
|
application.cpp
|
||||||
|
layer.cpp
|
||||||
|
layer_stack.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(app
|
||||||
|
PUBLIC
|
||||||
|
renderer
|
||||||
|
logger
|
||||||
|
ui
|
||||||
|
asset_parser
|
||||||
|
asset_manager
|
||||||
|
lt_debug
|
||||||
|
ecs
|
||||||
|
window
|
||||||
|
glad
|
||||||
|
time
|
||||||
|
opengl::opengl
|
||||||
|
EnTT::EnTT
|
||||||
|
)
|
||||||
|
|
77
modules/app/include/app/application.hpp
Normal file
77
modules/app/include/app/application.hpp
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <time/timer.hpp>
|
||||||
|
|
||||||
|
namespace lt {
|
||||||
|
|
||||||
|
class Renderer;
|
||||||
|
class Window;
|
||||||
|
class Event;
|
||||||
|
class GraphicsContext;
|
||||||
|
class UserInterface;
|
||||||
|
class LayerStack;
|
||||||
|
|
||||||
|
extern Scope<class Application> create_application();
|
||||||
|
|
||||||
|
class Application
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Application(const Application &) = delete;
|
||||||
|
|
||||||
|
Application(Application &&) = delete;
|
||||||
|
|
||||||
|
auto operator=(const Application &) -> Application & = delete;
|
||||||
|
|
||||||
|
auto operator=(Application &&) -> Application & = delete;
|
||||||
|
|
||||||
|
virtual ~Application();
|
||||||
|
|
||||||
|
[[nodiscard]] auto sanity_check() const -> bool;
|
||||||
|
|
||||||
|
void game_loop();
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_window() -> Window &
|
||||||
|
{
|
||||||
|
return *m_window;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_layer_stack() -> LayerStack &
|
||||||
|
{
|
||||||
|
return *m_layer_stack;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void quit();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Application();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void update_layers();
|
||||||
|
|
||||||
|
void render_layers();
|
||||||
|
|
||||||
|
void render_user_interface();
|
||||||
|
|
||||||
|
void poll_events();
|
||||||
|
|
||||||
|
void on_event(const Event &event);
|
||||||
|
|
||||||
|
void log_debug_data() const;
|
||||||
|
|
||||||
|
Timer m_timer;
|
||||||
|
|
||||||
|
Scope<Window> m_window;
|
||||||
|
|
||||||
|
Scope<UserInterface> m_user_interface;
|
||||||
|
|
||||||
|
Scope<GraphicsContext> m_graphics_context;
|
||||||
|
|
||||||
|
Scope<Renderer> m_renderer;
|
||||||
|
|
||||||
|
Scope<LayerStack> m_layer_stack;
|
||||||
|
|
||||||
|
static Application *s_instance;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace lt
|
|
@ -2,21 +2,21 @@
|
||||||
|
|
||||||
#include <app/application.hpp>
|
#include <app/application.hpp>
|
||||||
|
|
||||||
auto main(int argc, char *argv[]) -> int32_t
|
int main(int argc, char *argv[]) // NOLINT
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
std::ignore = argc;
|
std::ignore = argc;
|
||||||
std::ignore = argv;
|
std::ignore = argv;
|
||||||
|
|
||||||
auto application = lt::Scope<lt::app::Application> {};
|
auto application = lt::Scope<lt::Application> {};
|
||||||
|
|
||||||
application = lt::app::create_application();
|
application = lt::create_application();
|
||||||
if (!application)
|
|
||||||
{
|
lt::ensure(application, "Failed to create application");
|
||||||
throw std::runtime_error { "Failed to create application\n" };
|
lt::ensure(application->sanity_check(), "Failed to verify the sanity of the application");
|
||||||
}
|
|
||||||
|
|
||||||
application->game_loop();
|
application->game_loop();
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
catch (const std::exception &exp)
|
catch (const std::exception &exp)
|
116
modules/app/include/app/layer.hpp
Normal file
116
modules/app/include/app/layer.hpp
Normal file
|
@ -0,0 +1,116 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace lt {
|
||||||
|
|
||||||
|
class Event;
|
||||||
|
|
||||||
|
class MouseMovedEvent;
|
||||||
|
class ButtonPressedEvent;
|
||||||
|
class ButtonReleasedEvent;
|
||||||
|
class WheelScrolledEvent;
|
||||||
|
class KeyPressedEvent;
|
||||||
|
class KeyRepeatEvent;
|
||||||
|
class KeyReleasedEvent;
|
||||||
|
class SetCharEvent;
|
||||||
|
class WindowClosedEvent;
|
||||||
|
class WindowResizedEvent;
|
||||||
|
class WindowMovedEvent;
|
||||||
|
class WindowLostFocusEvent;
|
||||||
|
class WindowGainFocusEvent;
|
||||||
|
|
||||||
|
class Layer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Layer(std::string name);
|
||||||
|
|
||||||
|
virtual ~Layer() = default;
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_name() const -> const std::string &
|
||||||
|
{
|
||||||
|
return m_layer_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void on_update(float deltaTime)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void on_user_interface_update()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void on_render()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
auto on_event(const Event &event) -> bool;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::string m_layer_name;
|
||||||
|
|
||||||
|
virtual auto on_mouse_moved(const MouseMovedEvent & /*event*/) -> bool
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual auto on_button_pressed(const ButtonPressedEvent & /*event*/) -> bool
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual auto on_button_released(const ButtonReleasedEvent & /*event*/) -> bool
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual auto on_wheel_scrolled(const WheelScrolledEvent & /*event*/) -> bool
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual auto on_key_pressed(const KeyPressedEvent & /*event*/) -> bool
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual auto on_key_repeat(const KeyRepeatEvent & /*event*/) -> bool
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual auto on_key_released(const KeyReleasedEvent & /*event*/) -> bool
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual auto on_set_char(const SetCharEvent & /*event*/) -> bool
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual auto on_window_closed(const WindowClosedEvent & /*event*/) -> bool
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual auto on_window_resized(const WindowResizedEvent & /*event*/) -> bool
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual auto on_window_moved(const WindowMovedEvent & /*event*/) -> bool
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual auto on_window_lost_focus(const WindowLostFocusEvent & /*event*/) -> bool
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual auto on_window_gain_focus(const WindowGainFocusEvent & /*event*/) -> bool
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace lt
|
50
modules/app/include/app/layer_stack.hpp
Normal file
50
modules/app/include/app/layer_stack.hpp
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace lt {
|
||||||
|
|
||||||
|
class Layer;
|
||||||
|
class Event;
|
||||||
|
|
||||||
|
class LayerStack
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
template<typename Layer_T, typename... Args>
|
||||||
|
void emplace_layer(Args &&...args)
|
||||||
|
{
|
||||||
|
attach_layer(create_ref<Layer_T>(std::forward<Args>(args)...));
|
||||||
|
}
|
||||||
|
|
||||||
|
void attach_layer(Ref<Layer> layer);
|
||||||
|
|
||||||
|
void detach_layer(const Ref<Layer> &layer);
|
||||||
|
|
||||||
|
[[nodiscard]] auto is_empty() const -> bool
|
||||||
|
{
|
||||||
|
return m_layers.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto begin() -> std::vector<Ref<Layer>>::iterator
|
||||||
|
{
|
||||||
|
return m_layers.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto end() -> std::vector<Ref<Layer>>::iterator
|
||||||
|
{
|
||||||
|
return m_layers.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto rbegin() -> std::vector<Ref<Layer>>::reverse_iterator
|
||||||
|
{
|
||||||
|
return m_layers.rbegin();
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto rend() -> std::vector<Ref<Layer>>::reverse_iterator
|
||||||
|
{
|
||||||
|
return m_layers.rend();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<Ref<Layer>> m_layers;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace lt
|
|
@ -1,48 +0,0 @@
|
||||||
#include <app/application.hpp>
|
|
||||||
#include <app/system.hpp>
|
|
||||||
|
|
||||||
namespace lt::app {
|
|
||||||
|
|
||||||
void Application::game_loop()
|
|
||||||
{
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
for (auto &system : m_systems)
|
|
||||||
{
|
|
||||||
if (system->tick())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto &system : m_systems_to_be_registered)
|
|
||||||
{
|
|
||||||
m_systems.emplace_back(system)->on_register();
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto &system : m_systems_to_be_unregistered)
|
|
||||||
{
|
|
||||||
m_systems.erase(
|
|
||||||
std::remove(m_systems.begin(), m_systems.end(), system),
|
|
||||||
m_systems.end()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_systems.empty())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Application::register_system(Ref<app::ISystem> system)
|
|
||||||
{
|
|
||||||
m_systems.emplace_back(std::move(system));
|
|
||||||
}
|
|
||||||
|
|
||||||
void Application::unregister_system(Ref<app::ISystem> system)
|
|
||||||
{
|
|
||||||
m_systems_to_be_unregistered.emplace_back(std::move(system));
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace lt::app
|
|
|
@ -1,44 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
namespace lt::app {
|
|
||||||
|
|
||||||
class ISystem;
|
|
||||||
|
|
||||||
extern Scope<class Application> create_application();
|
|
||||||
|
|
||||||
/** The main application class.
|
|
||||||
* Think of this like an aggregate of systems, you register systems through this interface.
|
|
||||||
* Then they'll tick every "application frame".
|
|
||||||
*/
|
|
||||||
class Application
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Application(const Application &) = delete;
|
|
||||||
|
|
||||||
Application(Application &&) = delete;
|
|
||||||
|
|
||||||
auto operator=(const Application &) -> Application & = delete;
|
|
||||||
|
|
||||||
auto operator=(Application &&) -> Application & = delete;
|
|
||||||
|
|
||||||
virtual ~Application() = default;
|
|
||||||
|
|
||||||
void game_loop();
|
|
||||||
|
|
||||||
void register_system(Ref<app::ISystem> system);
|
|
||||||
|
|
||||||
void unregister_system(Ref<app::ISystem> system);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
Application() = default;
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::vector<Ref<app::ISystem>> m_systems;
|
|
||||||
|
|
||||||
std::vector<Ref<app::ISystem>> m_systems_to_be_unregistered;
|
|
||||||
|
|
||||||
std::vector<Ref<app::ISystem>> m_systems_to_be_registered;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace lt::app
|
|
|
@ -1,27 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
namespace lt::app {
|
|
||||||
|
|
||||||
class ISystem
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ISystem() = default;
|
|
||||||
|
|
||||||
virtual ~ISystem() = default;
|
|
||||||
|
|
||||||
ISystem(ISystem &&) = default;
|
|
||||||
|
|
||||||
ISystem(const ISystem &) = delete;
|
|
||||||
|
|
||||||
auto operator=(ISystem &&) -> ISystem & = default;
|
|
||||||
|
|
||||||
auto operator=(const ISystem &) -> ISystem & = delete;
|
|
||||||
|
|
||||||
virtual void on_register() = 0;
|
|
||||||
|
|
||||||
virtual void on_unregister() = 0;
|
|
||||||
|
|
||||||
virtual auto tick() -> bool = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace lt::app
|
|
203
modules/app/src/application.cpp
Normal file
203
modules/app/src/application.cpp
Normal file
|
@ -0,0 +1,203 @@
|
||||||
|
#include <app/application.hpp>
|
||||||
|
#include <app/layer.hpp>
|
||||||
|
#include <app/layer_stack.hpp>
|
||||||
|
#include <asset_manager/asset_manager.hpp>
|
||||||
|
#include <debug/assertions.hpp>
|
||||||
|
#include <input/events/event.hpp>
|
||||||
|
#include <input/events/keyboard.hpp>
|
||||||
|
#include <input/events/window.hpp>
|
||||||
|
#include <input/input.hpp>
|
||||||
|
#include <ranges>
|
||||||
|
#include <renderer/blender.hpp>
|
||||||
|
#include <renderer/graphics_context.hpp>
|
||||||
|
#include <renderer/render_command.hpp>
|
||||||
|
#include <renderer/renderer.hpp>
|
||||||
|
#include <ui/ui.hpp>
|
||||||
|
#include <window/linux/window.hpp>
|
||||||
|
|
||||||
|
namespace lt {
|
||||||
|
|
||||||
|
Application *Application::s_instance = nullptr;
|
||||||
|
|
||||||
|
Application::Application(): m_window(nullptr)
|
||||||
|
{
|
||||||
|
ensure(!s_instance, "Application constructed twice");
|
||||||
|
s_instance = this;
|
||||||
|
|
||||||
|
m_window = Window::create([this](auto &&PH1) { on_event(std::forward<decltype(PH1)>(PH1)); });
|
||||||
|
|
||||||
|
// create graphics context
|
||||||
|
m_graphics_context = GraphicsContext::create(
|
||||||
|
GraphicsAPI::OpenGL,
|
||||||
|
(GLFWwindow *)m_window->get_handle()
|
||||||
|
);
|
||||||
|
|
||||||
|
AssetManager::load_shader(
|
||||||
|
"LT_ENGINE_RESOURCES_TEXTURE_SHADER",
|
||||||
|
"data/assets/shaders/texture/vs.asset",
|
||||||
|
"data/assets/shaders/texture/ps.asset"
|
||||||
|
);
|
||||||
|
|
||||||
|
AssetManager::load_shader(
|
||||||
|
"LT_ENGINE_RESOURCES_TINTED_TEXTURE_SHADER",
|
||||||
|
"data/assets/shaders/tinted_texture/vs.asset",
|
||||||
|
"data/assets/shaders/tinted_texture/ps.asset"
|
||||||
|
);
|
||||||
|
|
||||||
|
AssetManager::load_shader(
|
||||||
|
"LT_ENGINE_RESOURCES_QUAD_SHADER",
|
||||||
|
"data/assets/shaders/quads/vs.asset",
|
||||||
|
"data/assets/shaders/quads/ps.asset"
|
||||||
|
);
|
||||||
|
|
||||||
|
m_renderer = Renderer::create(
|
||||||
|
(GLFWwindow *)m_window->get_handle(),
|
||||||
|
lt::GraphicsContext::get_shared_context(),
|
||||||
|
Renderer::CreateInfo {
|
||||||
|
.quad_renderer_shader = AssetManager::get_shader("LT_ENGINE_RESOURCES_QUAD_SHADER"),
|
||||||
|
.texture_renderer_shader = AssetManager::get_shader(
|
||||||
|
"LT_ENGINE_RESOURCES_TEXTURE_SHADER"
|
||||||
|
),
|
||||||
|
.tinted_texture_renderer_shader = AssetManager::get_shader(
|
||||||
|
"LT_ENGINE_RESOURCES_TINTED_"
|
||||||
|
"TEXTURE_SHADER"
|
||||||
|
),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
ensure(m_graphics_context, "lWindow::lWindow: failed to create 'GraphicsContext'");
|
||||||
|
|
||||||
|
m_user_interface = UserInterface::create(
|
||||||
|
(GLFWwindow *)m_window->get_handle(),
|
||||||
|
lt::GraphicsContext::get_shared_context()
|
||||||
|
);
|
||||||
|
|
||||||
|
m_layer_stack = create_scope<LayerStack>();
|
||||||
|
}
|
||||||
|
|
||||||
|
Application::~Application()
|
||||||
|
{
|
||||||
|
/** This is required to make forward-declarations possible:
|
||||||
|
* https://stackoverflow.com/questions/34072862/why-is-error-invalid-application-of-sizeof-to-an-incomplete-type-using-uniqu
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
void Application::game_loop()
|
||||||
|
{
|
||||||
|
m_window->set_visibility(true);
|
||||||
|
|
||||||
|
while (!m_window->is_closed())
|
||||||
|
{
|
||||||
|
update_layers();
|
||||||
|
render_layers();
|
||||||
|
render_user_interface();
|
||||||
|
poll_events();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Application::quit()
|
||||||
|
{
|
||||||
|
s_instance->m_window->close();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Application::update_layers()
|
||||||
|
{
|
||||||
|
for (auto &it : *m_layer_stack)
|
||||||
|
{
|
||||||
|
// narrowing double -> float
|
||||||
|
it->on_update(static_cast<float>(m_timer.elapsed_time().count()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(Light): each layer should have their own "delta time"
|
||||||
|
m_timer.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Application::render_layers()
|
||||||
|
{
|
||||||
|
m_renderer->begin_frame();
|
||||||
|
|
||||||
|
for (auto &it : *m_layer_stack)
|
||||||
|
{
|
||||||
|
it->on_render();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_renderer->end_frame();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Application::render_user_interface()
|
||||||
|
{
|
||||||
|
m_user_interface->begin();
|
||||||
|
|
||||||
|
for (auto &it : *m_layer_stack)
|
||||||
|
{
|
||||||
|
it->on_user_interface_update();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_user_interface->end();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Application::poll_events()
|
||||||
|
{
|
||||||
|
m_window->poll_events();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Application::on_event(const Event &event)
|
||||||
|
{
|
||||||
|
// window
|
||||||
|
if (event.has_category(WindowEventCategory))
|
||||||
|
{
|
||||||
|
m_window->on_event(event);
|
||||||
|
|
||||||
|
if (event.get_event_type() == EventType::WindowResized)
|
||||||
|
{
|
||||||
|
m_renderer->on_window_resize(dynamic_cast<const WindowResizedEvent &>(event));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// input
|
||||||
|
if (event.has_category(InputEventCategory))
|
||||||
|
{
|
||||||
|
Input::instance().on_event(event);
|
||||||
|
|
||||||
|
if (!Input::instance().is_receiving_game_events())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto &it : std::ranges::reverse_view(*m_layer_stack))
|
||||||
|
{
|
||||||
|
if (it->on_event(event))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto Application::sanity_check() const -> bool
|
||||||
|
{
|
||||||
|
log_inf("Checking application sanity...");
|
||||||
|
ensure(s_instance, "Application not constructed!?");
|
||||||
|
ensure(m_window, "Window is not initialized");
|
||||||
|
ensure(m_user_interface, "User interface is not initialized");
|
||||||
|
ensure(m_graphics_context, "Graphics context is not initialized");
|
||||||
|
ensure(m_renderer, "Renderer is not initialized");
|
||||||
|
ensure(m_layer_stack, "Layer_stack is not initialized");
|
||||||
|
ensure(!m_layer_stack->is_empty(), "Layer_stack is empty");
|
||||||
|
|
||||||
|
log_inf("Logging application state...");
|
||||||
|
this->log_debug_data();
|
||||||
|
m_graphics_context->log_debug_data();
|
||||||
|
m_user_interface->log_debug_data();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Application::log_debug_data() const
|
||||||
|
{
|
||||||
|
log_inf("Platform::");
|
||||||
|
log_inf(" Platform name: {}", constants::platform_name);
|
||||||
|
log_inf(" Platform identifier: {}", std::to_underlying(constants::platform));
|
||||||
|
log_inf(" CWD: {}", std::filesystem::current_path().generic_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace lt
|
47
modules/app/src/layer.cpp
Normal file
47
modules/app/src/layer.cpp
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
#include <app/layer.hpp>
|
||||||
|
#include <input/events/char.hpp>
|
||||||
|
#include <input/events/event.hpp>
|
||||||
|
#include <input/events/keyboard.hpp>
|
||||||
|
#include <input/events/mouse.hpp>
|
||||||
|
#include <input/events/window.hpp>
|
||||||
|
|
||||||
|
namespace lt {
|
||||||
|
|
||||||
|
Layer::Layer(std::string name): m_layer_name(std::move(name))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Layer::on_event(const Event &event) -> bool
|
||||||
|
{
|
||||||
|
switch (event.get_event_type())
|
||||||
|
{
|
||||||
|
case EventType::MouseMoved: return on_mouse_moved(dynamic_cast<const MouseMovedEvent &>(event));
|
||||||
|
case EventType::ButtonPressed:
|
||||||
|
return on_button_pressed(dynamic_cast<const ButtonPressedEvent &>(event));
|
||||||
|
case EventType::ButtonReleased:
|
||||||
|
return on_button_released(dynamic_cast<const ButtonReleasedEvent &>(event));
|
||||||
|
case EventType::WheelScrolled:
|
||||||
|
return on_wheel_scrolled(dynamic_cast<const WheelScrolledEvent &>(event));
|
||||||
|
|
||||||
|
case EventType::KeyPressed: return on_key_pressed(dynamic_cast<const KeyPressedEvent &>(event));
|
||||||
|
case EventType::KeyRepeated: return on_key_repeat(dynamic_cast<const KeyRepeatEvent &>(event));
|
||||||
|
case EventType::KeyReleased:
|
||||||
|
return on_key_released(dynamic_cast<const KeyReleasedEvent &>(event));
|
||||||
|
case EventType::SetChar: return on_set_char(dynamic_cast<const SetCharEvent &>(event));
|
||||||
|
|
||||||
|
case EventType::WindowClosed:
|
||||||
|
return on_window_closed(dynamic_cast<const WindowClosedEvent &>(event));
|
||||||
|
case EventType::WindowResized:
|
||||||
|
return on_window_resized(dynamic_cast<const WindowResizedEvent &>(event));
|
||||||
|
case EventType::WindowMoved:
|
||||||
|
return on_window_moved(dynamic_cast<const WindowMovedEvent &>(event));
|
||||||
|
case EventType::WindowLostFocus:
|
||||||
|
return on_window_lost_focus(dynamic_cast<const WindowLostFocusEvent &>(event));
|
||||||
|
case EventType::WindowGainFocus:
|
||||||
|
return on_window_gain_focus(dynamic_cast<const WindowGainFocusEvent &>(event));
|
||||||
|
|
||||||
|
default: ensure(false, "Invalid event: {}", event.get_info_lt_log());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace lt
|
18
modules/app/src/layer_stack.cpp
Normal file
18
modules/app/src/layer_stack.cpp
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
#include <app/layer.hpp>
|
||||||
|
#include <app/layer_stack.hpp>
|
||||||
|
|
||||||
|
namespace lt {
|
||||||
|
|
||||||
|
void LayerStack::attach_layer(Ref<Layer> layer)
|
||||||
|
{
|
||||||
|
log_trc("Attaching layer [{}]", layer->get_name());
|
||||||
|
m_layers.emplace_back(std::move(layer));
|
||||||
|
}
|
||||||
|
|
||||||
|
void LayerStack::detach_layer(const Ref<Layer> &layer)
|
||||||
|
{
|
||||||
|
log_trc("Detaching layer [{}]", layer->get_name());
|
||||||
|
m_layers.erase(std::find(m_layers.begin(), m_layers.end(), layer));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace lt
|
|
@ -1,5 +1,5 @@
|
||||||
add_executable_module(
|
add_executable_module(
|
||||||
asset_baker entrypoint/baker.cpp
|
asset_baker baker.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(
|
target_link_libraries(
|
||||||
|
|
|
@ -131,8 +131,7 @@ public:
|
||||||
return "TextLoader";
|
return "TextLoader";
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] auto load(const std::filesystem::path &file_path) const
|
[[nodiscard]] auto load(const std::filesystem::path& file_path) const -> Assets::TextAsset::PackageData
|
||||||
-> Assets::TextAsset::PackageData
|
|
||||||
{
|
{
|
||||||
auto stream = std::ifstream { file_path, std::ios::binary };
|
auto stream = std::ifstream { file_path, std::ios::binary };
|
||||||
if (!stream.good())
|
if (!stream.good())
|
|
@ -5,5 +5,5 @@ add_library_module(asset_manager
|
||||||
target_link_libraries(
|
target_link_libraries(
|
||||||
asset_manager
|
asset_manager
|
||||||
PUBLIC asset_parser
|
PUBLIC asset_parser
|
||||||
PRIVATE logger
|
PRIVATE renderer
|
||||||
)
|
)
|
||||||
|
|
|
@ -6,6 +6,7 @@ add_library_module(asset_parser
|
||||||
|
|
||||||
target_link_libraries(
|
target_link_libraries(
|
||||||
asset_parser
|
asset_parser
|
||||||
PRIVATE LZ4::lz4_static
|
PUBLIC LZ4::lz4_static
|
||||||
PRIVATE logger
|
PUBLIC nlohmann_json::nlohmann_json
|
||||||
|
PUBLIC logger
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <asset_parser/compressors/compressors.hpp>
|
|
||||||
#include <asset_parser/parser.hpp>
|
#include <asset_parser/parser.hpp>
|
||||||
|
#include <compressors/compressors.hpp>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <fstream>
|
#include <fstream>
|
|
@ -1,7 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <asset_parser/compressors/compressors.hpp>
|
|
||||||
#include <asset_parser/parser.hpp>
|
#include <asset_parser/parser.hpp>
|
||||||
|
#include <compressors/compressors.hpp>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <fstream>
|
#include <fstream>
|
|
@ -1,6 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <asset_parser/compressors/compressors.hpp>
|
#include <compressors/compressors.hpp>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <fstream>
|
#include <fstream>
|
|
@ -1,5 +1,6 @@
|
||||||
#include <asset_parser/assets/text.hpp>
|
#include <asset_parser/assets/text.hpp>
|
||||||
#include <lz4.h>
|
#include <lz4.h>
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
namespace Assets {
|
namespace Assets {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include <asset_parser/assets/texture.hpp>
|
#include <asset_parser/assets/texture.hpp>
|
||||||
#include <lz4.h>
|
#include <lz4.h>
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
namespace Assets {
|
namespace Assets {
|
||||||
|
|
|
@ -1,2 +1,3 @@
|
||||||
add_library_module(base)
|
add_library_module(base)
|
||||||
target_precompile_headers(base INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/private/pch.hpp)
|
|
||||||
|
target_precompile_headers(base INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/src/pch.hpp)
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
add_library_module(camera camera.cpp scene.cpp)
|
add_library_module(camera camera.cpp scene.cpp)
|
||||||
|
|
||||||
target_link_libraries(camera PUBLIC math)
|
target_link_libraries(camera PUBLIC glm::glm)
|
||||||
|
|
34
modules/camera/include/camera/camera.hpp
Normal file
34
modules/camera/include/camera/camera.hpp
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
|
namespace lt {
|
||||||
|
|
||||||
|
class Camera
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Camera() = default;
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_projection() const -> const glm::mat4 &
|
||||||
|
{
|
||||||
|
return m_projection;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_background_color() const -> const glm::vec4 &
|
||||||
|
{
|
||||||
|
return m_background_color;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_background_color(const glm::vec4 &color)
|
||||||
|
{
|
||||||
|
m_background_color = color;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
glm::mat4 m_projection {};
|
||||||
|
|
||||||
|
private:
|
||||||
|
glm::vec4 m_background_color = glm::vec4(1.0f, 0.0f, 0.0f, 1.0f);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace lt
|
|
@ -1,6 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <camera/scene.hpp>
|
#include <camera/scene.hpp>
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
namespace lt {
|
namespace lt {
|
||||||
|
|
|
@ -1,35 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <math/mat4.hpp>
|
|
||||||
#include <math/vec4.hpp>
|
|
||||||
|
|
||||||
namespace lt {
|
|
||||||
|
|
||||||
class Camera
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Camera() = default;
|
|
||||||
|
|
||||||
[[nodiscard]] auto get_projection() const -> const math::mat4 &
|
|
||||||
{
|
|
||||||
return m_projection;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] auto get_background_color() const -> const math::vec4 &
|
|
||||||
{
|
|
||||||
return m_background_color;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_background_color(const math::vec4 &color)
|
|
||||||
{
|
|
||||||
m_background_color = color;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
math::mat4 m_projection;
|
|
||||||
|
|
||||||
private:
|
|
||||||
math::vec4 m_background_color = math::vec4(1.0f, 0.0f, 0.0f, 1.0f);
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace lt
|
|
|
@ -1,12 +1,11 @@
|
||||||
#include <camera/scene.hpp>
|
#include <camera/scene.hpp>
|
||||||
#include <math/algebra.hpp>
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
#include <math/trig.hpp>
|
|
||||||
|
|
||||||
namespace lt {
|
namespace lt {
|
||||||
|
|
||||||
SceneCamera::SceneCamera()
|
SceneCamera::SceneCamera()
|
||||||
: m_orthographic_specification { .size = 1000.0f, .near_plane = -1.0f, .far_plane = 10000.0f }
|
: m_orthographic_specification { .size = 1000.0f, .near_plane = -1.0f, .far_plane = 10000.0f }
|
||||||
, m_perspective_specification { .vertical_fov = math::radians(45.0f),
|
, m_perspective_specification { .vertical_fov = glm::radians(45.0f),
|
||||||
.near_plane = 0.01f,
|
.near_plane = 0.01f,
|
||||||
.far_plane = 10000.0f }
|
.far_plane = 10000.0f }
|
||||||
, m_aspect_ratio(16.0f / 9.0f)
|
, m_aspect_ratio(16.0f / 9.0f)
|
||||||
|
@ -65,19 +64,26 @@ void SceneCamera::set_perspective_near_plane(float near_plane)
|
||||||
|
|
||||||
void SceneCamera::calculate_projection()
|
void SceneCamera::calculate_projection()
|
||||||
{
|
{
|
||||||
// TODO(Light): implement ortho perspective
|
|
||||||
if (m_projection_type == ProjectionType::Orthographic)
|
if (m_projection_type == ProjectionType::Orthographic)
|
||||||
{
|
{
|
||||||
// throw std::runtime_error { "ortho perspective not supported yet" };
|
m_projection = glm::ortho(
|
||||||
|
-m_orthographic_specification.size * 0.5f * m_aspect_ratio,
|
||||||
|
m_orthographic_specification.size * 0.5f * m_aspect_ratio,
|
||||||
|
-m_orthographic_specification.size * 0.5f,
|
||||||
|
m_orthographic_specification.size * 0.5f,
|
||||||
|
m_orthographic_specification.far_plane,
|
||||||
|
m_orthographic_specification.near_plane
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else // perspective
|
||||||
|
{
|
||||||
|
m_projection = glm::perspective(
|
||||||
|
m_perspective_specification.vertical_fov,
|
||||||
|
m_aspect_ratio,
|
||||||
|
m_perspective_specification.near_plane,
|
||||||
|
m_perspective_specification.far_plane
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// defaults to perspective for now...
|
|
||||||
m_projection = math::perspective(
|
|
||||||
m_perspective_specification.vertical_fov,
|
|
||||||
m_aspect_ratio,
|
|
||||||
m_perspective_specification.near_plane,
|
|
||||||
m_perspective_specification.far_plane
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace lt
|
} // namespace lt
|
|
@ -1,3 +1,3 @@
|
||||||
add_library_module(lt_debug instrumentor.cpp)
|
add_library_module(lt_debug instrumentor.cpp)
|
||||||
target_link_libraries(lt_debug PUBLIC logger)
|
target_link_libraries(lt_debug PUBLIC logger)
|
||||||
target_precompile_headers(lt_debug PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/private/pch.hpp)
|
target_precompile_headers(lt_debug PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src/pch.hpp)
|
||||||
|
|
36
modules/debug/include/debug/assertions.hpp
Normal file
36
modules/debug/include/debug/assertions.hpp
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <logger/logger.hpp>
|
||||||
|
|
||||||
|
namespace lt {
|
||||||
|
|
||||||
|
struct FailedAssertion: std::exception
|
||||||
|
{
|
||||||
|
FailedAssertion(const char *file, int line)
|
||||||
|
{
|
||||||
|
log_crt("Assertion failed in: {} (line {})", file, line);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template<typename Expression_T, typename... Args>
|
||||||
|
constexpr void ensure(Expression_T &&expression, std::format_string<Args...> fmt, Args &&...args)
|
||||||
|
{
|
||||||
|
if (!static_cast<bool>(expression))
|
||||||
|
{
|
||||||
|
Logger::log(LogLvl::critical, fmt, std::forward<Args>(args)...);
|
||||||
|
throw ::lt::FailedAssertion(__FILE__, __LINE__);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Expression_T>
|
||||||
|
constexpr void ensure(Expression_T &&expression, const char *message)
|
||||||
|
{
|
||||||
|
if (!static_cast<bool>(expression))
|
||||||
|
{
|
||||||
|
Logger::log(LogLvl::critical, message);
|
||||||
|
throw ::lt::FailedAssertion(__FILE__, __LINE__);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace lt
|
|
@ -1,3 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <lt_debug/assertions.hpp>
|
|
|
@ -1,36 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <format>
|
|
||||||
#include <logger/logger.hpp>
|
|
||||||
#include <source_location>
|
|
||||||
|
|
||||||
namespace lt {
|
|
||||||
|
|
||||||
template<typename Expression_T, typename... Args_T>
|
|
||||||
struct ensure
|
|
||||||
{
|
|
||||||
ensure(
|
|
||||||
Expression_T expression,
|
|
||||||
std::format_string<Args_T...> fmt,
|
|
||||||
Args_T &&...args,
|
|
||||||
const std::source_location &location = std::source_location::current()
|
|
||||||
)
|
|
||||||
{
|
|
||||||
if (!static_cast<bool>(expression))
|
|
||||||
{
|
|
||||||
throw std::runtime_error { std::format(
|
|
||||||
"exception: {}\nlocation: {}:{}",
|
|
||||||
std::format(fmt, std::forward<Args_T>(args)...),
|
|
||||||
location.file_name(),
|
|
||||||
location.line()
|
|
||||||
) };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
template<typename Expression_T, typename... Args_T>
|
|
||||||
ensure(Expression_T, std::format_string<Args_T...>, Args_T &&...)
|
|
||||||
-> ensure<Expression_T, Args_T...>;
|
|
||||||
|
|
||||||
} // namespace lt
|
|
|
@ -1,5 +1,5 @@
|
||||||
|
#include <debug/instrumentor.hpp>
|
||||||
#include <logger/logger.hpp>
|
#include <logger/logger.hpp>
|
||||||
#include <lt_debug/instrumentor.hpp>
|
|
||||||
|
|
||||||
namespace lt {
|
namespace lt {
|
||||||
|
|
3
modules/debug/src/pch.hpp
Normal file
3
modules/debug/src/pch.hpp
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <debug/assertions.hpp>
|
|
@ -1,4 +1,5 @@
|
||||||
add_library_module(ecs entity.cpp scene.cpp uuid.cpp )
|
add_library_module(ecs entity.cpp scene.cpp uuid.cpp serializer.cpp)
|
||||||
target_link_libraries(ecs
|
target_link_libraries(ecs
|
||||||
PUBLIC logger lt_debug EnTT::EnTT input camera math
|
PUBLIC logger lt_debug EnTT::EnTT renderer input camera
|
||||||
|
PRIVATE yaml-cpp::yaml-cpp asset_manager
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <math/vec4.hpp>
|
#include <glm/glm.hpp>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
namespace lt {
|
namespace lt {
|
||||||
|
@ -15,7 +15,7 @@ struct SpriteRendererComponent
|
||||||
|
|
||||||
SpriteRendererComponent(
|
SpriteRendererComponent(
|
||||||
Ref<Texture> _texture,
|
Ref<Texture> _texture,
|
||||||
const math::vec4 &_tint = math::vec4 { 1.0f, 1.0f, 1.0f, 1.0f }
|
const glm::vec4 &_tint = glm::vec4(1.0f, 1.0f, 1.0f, 1.0f)
|
||||||
)
|
)
|
||||||
: texture(std::move(std::move(_texture)))
|
: texture(std::move(std::move(_texture)))
|
||||||
, tint(_tint)
|
, tint(_tint)
|
||||||
|
@ -29,7 +29,7 @@ struct SpriteRendererComponent
|
||||||
|
|
||||||
Ref<Texture> texture;
|
Ref<Texture> texture;
|
||||||
|
|
||||||
math::vec4 tint {};
|
glm::vec4 tint {};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace lt
|
} // namespace lt
|
45
modules/ecs/include/ecs/components/transform.hpp
Normal file
45
modules/ecs/include/ecs/components/transform.hpp
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define GLM_ENABLE_EXPERIMENTAL
|
||||||
|
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
|
#include <glm/gtx/transform.hpp>
|
||||||
|
|
||||||
|
namespace lt {
|
||||||
|
|
||||||
|
struct TransformComponent
|
||||||
|
{
|
||||||
|
TransformComponent(const TransformComponent &) = default;
|
||||||
|
|
||||||
|
TransformComponent(
|
||||||
|
const glm::vec3 &_translation = glm::vec3(0.0f, 0.0f, 0.0f),
|
||||||
|
const glm::vec3 &_scale = glm::vec3(1.0f, 1.0f, 1.0f),
|
||||||
|
const glm::vec3 &_rotation = glm::vec3(0.0f, 0.0f, 0.0f)
|
||||||
|
)
|
||||||
|
|
||||||
|
: translation(_translation)
|
||||||
|
, scale(_scale)
|
||||||
|
, rotation(_rotation)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_transform() const -> glm::mat4
|
||||||
|
{
|
||||||
|
return glm::translate(translation) * glm::rotate(rotation.z, glm::vec3(0.0f, 0.0f, 1.0f))
|
||||||
|
* glm::scale(scale);
|
||||||
|
}
|
||||||
|
|
||||||
|
operator const glm::mat4() const
|
||||||
|
{
|
||||||
|
return get_transform();
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::vec3 translation;
|
||||||
|
|
||||||
|
glm::vec3 scale;
|
||||||
|
|
||||||
|
glm::vec3 rotation;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace lt
|
|
@ -3,7 +3,7 @@
|
||||||
#include <ecs/components/transform.hpp>
|
#include <ecs/components/transform.hpp>
|
||||||
#include <ecs/uuid.hpp>
|
#include <ecs/uuid.hpp>
|
||||||
#include <entt/entt.hpp>
|
#include <entt/entt.hpp>
|
||||||
#include <functional>
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
namespace lt {
|
namespace lt {
|
||||||
|
|
||||||
|
@ -13,17 +13,11 @@ class Framebuffer;
|
||||||
class Scene
|
class Scene
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
template<typename... T>
|
void on_create();
|
||||||
auto group()
|
|
||||||
{
|
|
||||||
return m_registry.group(entt::get<T...>);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
void on_update(float deltaTime);
|
||||||
auto view()
|
|
||||||
{
|
void on_render(const Ref<Framebuffer> &targetFrameBuffer = nullptr);
|
||||||
return m_registry.view<T>();
|
|
||||||
}
|
|
||||||
|
|
||||||
auto create_entity(
|
auto create_entity(
|
||||||
const std::string &name,
|
const std::string &name,
|
||||||
|
@ -32,12 +26,6 @@ public:
|
||||||
|
|
||||||
auto get_entity_by_tag(const std::string &tag) -> Entity;
|
auto get_entity_by_tag(const std::string &tag) -> Entity;
|
||||||
|
|
||||||
auto get_entt_registry() -> entt::registry &
|
|
||||||
{
|
|
||||||
return m_registry;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class Entity;
|
friend class Entity;
|
||||||
|
|
||||||
|
@ -54,12 +42,4 @@ private:
|
||||||
) -> Entity;
|
) -> Entity;
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace ecs {
|
|
||||||
|
|
||||||
using Registry = Scene;
|
|
||||||
|
|
||||||
using Entity = ::lt::Entity;
|
|
||||||
|
|
||||||
} // namespace ecs
|
|
||||||
|
|
||||||
} // namespace lt
|
} // namespace lt
|
|
@ -1,31 +0,0 @@
|
||||||
#include <ecs/components.hpp>
|
|
||||||
#include <ecs/entity.hpp>
|
|
||||||
#include <ecs/scene.hpp>
|
|
||||||
|
|
||||||
namespace lt {
|
|
||||||
|
|
||||||
auto Scene::create_entity(const std::string &name, const TransformComponent &transform) -> Entity
|
|
||||||
{
|
|
||||||
return create_entity_with_uuid(name, UUID(), transform);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto Scene::get_entity_by_tag(const std::string &tag) -> Entity
|
|
||||||
{
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
auto Scene::create_entity_with_uuid(
|
|
||||||
const std::string &name,
|
|
||||||
UUID uuid,
|
|
||||||
const TransformComponent &transform
|
|
||||||
) -> Entity
|
|
||||||
{
|
|
||||||
auto entity = Entity { m_registry.create(), this };
|
|
||||||
entity.add_component<TagComponent>(name);
|
|
||||||
entity.add_component<TransformComponent>(transform);
|
|
||||||
entity.add_component<UUIDComponent>(uuid);
|
|
||||||
|
|
||||||
return entity;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace lt
|
|
|
@ -1,14 +0,0 @@
|
||||||
#include <ecs/uuid.hpp>
|
|
||||||
|
|
||||||
namespace lt {
|
|
||||||
|
|
||||||
std::mt19937_64 UUID::s_engine = std::mt19937_64(std::random_device()());
|
|
||||||
|
|
||||||
std::uniform_int_distribution<uint64_t>
|
|
||||||
UUID::s_distribution = std::uniform_int_distribution<uint64_t> {};
|
|
||||||
|
|
||||||
UUID::UUID(uint64_t uuid /* = -1 */): m_uuid(uuid == -1 ? s_distribution(s_engine) : uuid)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace lt
|
|
|
@ -1,43 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <math/mat4.hpp>
|
|
||||||
#include <math/vec3.hpp>
|
|
||||||
|
|
||||||
namespace lt {
|
|
||||||
|
|
||||||
struct TransformComponent
|
|
||||||
{
|
|
||||||
TransformComponent(const TransformComponent &) = default;
|
|
||||||
|
|
||||||
TransformComponent(
|
|
||||||
const math::vec3 &_translation = math::vec3(0.0f, 0.0f, 0.0f),
|
|
||||||
const math::vec3 &_scale = math::vec3(1.0f, 1.0f, 1.0f),
|
|
||||||
const math::vec3 &_rotation = math::vec3(0.0f, 0.0f, 0.0f)
|
|
||||||
)
|
|
||||||
|
|
||||||
: translation(_translation)
|
|
||||||
, scale(_scale)
|
|
||||||
, rotation(_rotation)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] auto get_transform() const -> math::mat4
|
|
||||||
{
|
|
||||||
return math::translate(translation)
|
|
||||||
* math::rotate(rotation.z, math::vec3 { 0.0f, 0.0f, 1.0f }) //
|
|
||||||
* math::scale(scale);
|
|
||||||
}
|
|
||||||
|
|
||||||
operator const math::mat4() const
|
|
||||||
{
|
|
||||||
return get_transform();
|
|
||||||
}
|
|
||||||
|
|
||||||
math::vec3 translation;
|
|
||||||
|
|
||||||
math::vec3 scale;
|
|
||||||
|
|
||||||
math::vec3 rotation;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace lt
|
|
111
modules/ecs/src/scene.cpp
Normal file
111
modules/ecs/src/scene.cpp
Normal file
|
@ -0,0 +1,111 @@
|
||||||
|
#include <camera/component.hpp>
|
||||||
|
#include <ecs/components.hpp>
|
||||||
|
#include <ecs/entity.hpp>
|
||||||
|
#include <ecs/scene.hpp>
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
#include <renderer/renderer.hpp>
|
||||||
|
|
||||||
|
namespace lt {
|
||||||
|
|
||||||
|
void Scene::on_create()
|
||||||
|
{
|
||||||
|
/* native scripts */
|
||||||
|
{
|
||||||
|
m_registry.view<NativeScriptComponent>().each([](NativeScriptComponent &nsc) {
|
||||||
|
if (nsc.instance == nullptr)
|
||||||
|
{
|
||||||
|
nsc.instance = nsc.CreateInstance();
|
||||||
|
nsc.instance->on_create();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scene::on_update(float deltaTime)
|
||||||
|
{
|
||||||
|
/* native scripts */
|
||||||
|
{
|
||||||
|
m_registry.view<NativeScriptComponent>().each([=](NativeScriptComponent &nsc) {
|
||||||
|
nsc.instance->on_update(deltaTime);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scene::on_render(const Ref<Framebuffer> &targetFrameBuffer /* = nullptr */)
|
||||||
|
{
|
||||||
|
auto *sceneCamera = (Camera *)nullptr;
|
||||||
|
auto *sceneCameraTransform = (TransformComponent *)nullptr;
|
||||||
|
|
||||||
|
/* scene camera */
|
||||||
|
{
|
||||||
|
m_registry.group(entt::get<TransformComponent, CameraComponent>)
|
||||||
|
.each([&](TransformComponent &transformComp, CameraComponent &cameraComp) {
|
||||||
|
if (cameraComp.isPrimary)
|
||||||
|
{
|
||||||
|
sceneCamera = &cameraComp.camera;
|
||||||
|
sceneCameraTransform = &transformComp;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/* draw quads */
|
||||||
|
{
|
||||||
|
if (sceneCamera)
|
||||||
|
{
|
||||||
|
Renderer::begin_scene(sceneCamera, *sceneCameraTransform, targetFrameBuffer);
|
||||||
|
|
||||||
|
m_registry.group(entt::get<TransformComponent, SpriteRendererComponent>)
|
||||||
|
.each([](TransformComponent &transformComp,
|
||||||
|
SpriteRendererComponent &spriteRendererComp) {
|
||||||
|
Renderer::draw_quad(
|
||||||
|
transformComp,
|
||||||
|
spriteRendererComp.tint,
|
||||||
|
spriteRendererComp.texture
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
Renderer::end_scene();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Scene::create_entity(const std::string &name, const TransformComponent &transform) -> Entity
|
||||||
|
{
|
||||||
|
return create_entity_with_uuid(name, UUID(), transform);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Scene::get_entity_by_tag(const std::string &tag) -> Entity
|
||||||
|
{
|
||||||
|
// TagComponent tagComp(tag);
|
||||||
|
// entt::entity entity = entt::to_entity(m_registry, tagComp);
|
||||||
|
auto entity = Entity {};
|
||||||
|
|
||||||
|
m_registry.view<TagComponent>().each([&](TagComponent &tagComp) {
|
||||||
|
// if (tagComp.tag == tag)
|
||||||
|
// entity = entity(entt::to_entity(m_registry, tagComp), this);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (entity.is_valid())
|
||||||
|
{
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
ensure(false, "Scene::get_entity_by_tag: failed to find entity by tag: {}", tag);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Scene::create_entity_with_uuid(
|
||||||
|
const std::string &name,
|
||||||
|
UUID uuid,
|
||||||
|
const TransformComponent &transform
|
||||||
|
) -> Entity
|
||||||
|
{
|
||||||
|
auto entity = Entity { m_registry.create(), this };
|
||||||
|
entity.add_component<TagComponent>(name);
|
||||||
|
entity.add_component<TransformComponent>(transform);
|
||||||
|
entity.add_component<UUIDComponent>(uuid);
|
||||||
|
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace lt
|
|
@ -2,16 +2,14 @@
|
||||||
#include <camera/component.hpp>
|
#include <camera/component.hpp>
|
||||||
#include <ecs/components.hpp>
|
#include <ecs/components.hpp>
|
||||||
#include <ecs/serializer.hpp>
|
#include <ecs/serializer.hpp>
|
||||||
#include <math/vec3.hpp>
|
|
||||||
#include <math/vec4.hpp>
|
|
||||||
#include <yaml-cpp/yaml.h>
|
#include <yaml-cpp/yaml.h>
|
||||||
|
|
||||||
namespace YAML {
|
namespace YAML {
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct convert<lt::math::vec3>
|
struct convert<glm::vec3>
|
||||||
{
|
{
|
||||||
static auto encode(const lt::math::vec3 &rhs) -> Node
|
static auto encode(const glm::vec3 &rhs) -> Node
|
||||||
{
|
{
|
||||||
auto node = Node {};
|
auto node = Node {};
|
||||||
node.push_back(rhs.x);
|
node.push_back(rhs.x);
|
||||||
|
@ -20,7 +18,7 @@ struct convert<lt::math::vec3>
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
static auto decode(const Node &node, lt::math::vec3 &rhs) -> bool
|
static auto decode(const Node &node, glm::vec3 &rhs) -> bool
|
||||||
{
|
{
|
||||||
if (!node.IsSequence() || node.size() != 3)
|
if (!node.IsSequence() || node.size() != 3)
|
||||||
{
|
{
|
||||||
|
@ -35,9 +33,9 @@ struct convert<lt::math::vec3>
|
||||||
};
|
};
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct convert<lt::math::vec4>
|
struct convert<glm::vec4>
|
||||||
{
|
{
|
||||||
static auto encode(const lt::math::vec4 &rhs) -> Node
|
static auto encode(const glm::vec4 &rhs) -> Node
|
||||||
{
|
{
|
||||||
auto node = Node {};
|
auto node = Node {};
|
||||||
node.push_back(rhs.x);
|
node.push_back(rhs.x);
|
||||||
|
@ -47,7 +45,7 @@ struct convert<lt::math::vec4>
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
static auto decode(const Node &node, lt::math::vec4 &rhs) -> bool
|
static auto decode(const Node &node, glm::vec4 &rhs) -> bool
|
||||||
{
|
{
|
||||||
if (!node.IsSequence() || node.size() != 4)
|
if (!node.IsSequence() || node.size() != 4)
|
||||||
{
|
{
|
||||||
|
@ -65,14 +63,14 @@ struct convert<lt::math::vec4>
|
||||||
|
|
||||||
namespace lt {
|
namespace lt {
|
||||||
|
|
||||||
auto operator<<(YAML::Emitter &out, const math::vec3 &v) -> YAML::Emitter &
|
auto operator<<(YAML::Emitter &out, const glm::vec3 &v) -> YAML::Emitter &
|
||||||
{
|
{
|
||||||
out << YAML::Flow;
|
out << YAML::Flow;
|
||||||
out << YAML::BeginSeq << v.x << v.y << v.z << YAML::EndSeq;
|
out << YAML::BeginSeq << v.x << v.y << v.z << YAML::EndSeq;
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto operator<<(YAML::Emitter &out, const math::vec4 &v) -> YAML::Emitter &
|
auto operator<<(YAML::Emitter &out, const glm::vec4 &v) -> YAML::Emitter &
|
||||||
{
|
{
|
||||||
out << YAML::Flow;
|
out << YAML::Flow;
|
||||||
out << YAML::BeginSeq << v.x << v.y << v.z << v.w << YAML::EndSeq;
|
out << YAML::BeginSeq << v.x << v.y << v.z << v.w << YAML::EndSeq;
|
||||||
|
@ -158,10 +156,9 @@ auto SceneSerializer::deserialize(const std::string &file_path) -> bool
|
||||||
.get_component<TransformComponent>();
|
.get_component<TransformComponent>();
|
||||||
|
|
||||||
entityTransforomComponent.translation = transformComponent["Translation"]
|
entityTransforomComponent.translation = transformComponent["Translation"]
|
||||||
.as<math::vec3>();
|
.as<glm::vec3>();
|
||||||
entityTransforomComponent.rotation = transformComponent["Rotation"]
|
entityTransforomComponent.rotation = transformComponent["Rotation"].as<glm::vec3>();
|
||||||
.as<math::vec3>();
|
entityTransforomComponent.scale = transformComponent["Scale"].as<glm::vec3>();
|
||||||
entityTransforomComponent.scale = transformComponent["Scale"].as<math::vec3>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* #TEMPORARY SOLUTION# */
|
/* #TEMPORARY SOLUTION# */
|
||||||
|
@ -171,7 +168,7 @@ auto SceneSerializer::deserialize(const std::string &file_path) -> bool
|
||||||
auto &entitySpriteRendererComponent = deserializedEntity
|
auto &entitySpriteRendererComponent = deserializedEntity
|
||||||
.add_component<SpriteRendererComponent>();
|
.add_component<SpriteRendererComponent>();
|
||||||
entitySpriteRendererComponent.tint = spriteRendererComponent["Tint"]
|
entitySpriteRendererComponent.tint = spriteRendererComponent["Tint"]
|
||||||
.as<math::vec4>();
|
.as<glm::vec4>();
|
||||||
|
|
||||||
auto texturePath = spriteRendererComponent["Texture"].as<std::string>();
|
auto texturePath = spriteRendererComponent["Texture"].as<std::string>();
|
||||||
|
|
||||||
|
@ -216,7 +213,7 @@ auto SceneSerializer::deserialize(const std::string &file_path) -> bool
|
||||||
);
|
);
|
||||||
|
|
||||||
entityCameraComponent.camera.set_background_color(
|
entityCameraComponent.camera.set_background_color(
|
||||||
cameraSpecifications["BackgroundColor"].as<math::vec4>()
|
cameraSpecifications["BackgroundColor"].as<glm::vec4>()
|
||||||
);
|
);
|
||||||
|
|
||||||
entityCameraComponent.isPrimary = cameraComponent["IsPrimary"].as<bool>();
|
entityCameraComponent.isPrimary = cameraComponent["IsPrimary"].as<bool>();
|
12
modules/ecs/src/uuid.cpp
Normal file
12
modules/ecs/src/uuid.cpp
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
#include <ecs/uuid.hpp>
|
||||||
|
|
||||||
|
namespace lt {
|
||||||
|
|
||||||
|
auto UUID::s_engine = std::mt19937_64(std::random_device()());
|
||||||
|
auto UUID::s_distribution = std::uniform_int_distribution<uint64_t> {};
|
||||||
|
|
||||||
|
UUID::UUID(uint64_t uuid /* = -1 */): m_uuid(uuid == -1 ? s_distribution(s_engine) : uuid)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace lt
|
|
@ -1,2 +1,2 @@
|
||||||
add_library_module(input input.cpp)
|
add_library_module(input input.cpp)
|
||||||
target_link_libraries(input PUBLIC surface math imgui::imgui logger)
|
target_link_libraries(input PUBLIC spdlog::spdlog glm::glm imgui logger)
|
||||||
|
|
41
modules/input/include/input/events/char.hpp
Normal file
41
modules/input/include/input/events/char.hpp
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <input/events/event.hpp>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
namespace lt {
|
||||||
|
|
||||||
|
class SetCharEvent: public Event
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SetCharEvent(unsigned int character): m_character(character)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_character() const -> int
|
||||||
|
{
|
||||||
|
return m_character;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_info_lt_log() const -> std::string override
|
||||||
|
{
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << "CharSet: " << m_character;
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_event_type() const -> EventType override
|
||||||
|
{
|
||||||
|
return ::lt::EventType::SetChar;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto has_category(EventCategory category) const -> bool override
|
||||||
|
{
|
||||||
|
return static_cast<uint8_t>(InputEventCategory | KeyboardEventCategory) & category;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const unsigned int m_character;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace lt
|
56
modules/input/include/input/events/event.hpp
Normal file
56
modules/input/include/input/events/event.hpp
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace lt {
|
||||||
|
|
||||||
|
enum class EventType : uint8_t
|
||||||
|
{
|
||||||
|
None = 0,
|
||||||
|
|
||||||
|
// input
|
||||||
|
MouseMoved,
|
||||||
|
WheelScrolled,
|
||||||
|
ButtonPressed,
|
||||||
|
ButtonReleased,
|
||||||
|
KeyPressed,
|
||||||
|
KeyRepeated,
|
||||||
|
KeyReleased,
|
||||||
|
SetChar,
|
||||||
|
|
||||||
|
// window
|
||||||
|
WindowMoved,
|
||||||
|
WindowResized,
|
||||||
|
WindowClosed,
|
||||||
|
WindowLostFocus,
|
||||||
|
WindowGainFocus,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum EventCategory : uint8_t
|
||||||
|
{
|
||||||
|
None = 0,
|
||||||
|
|
||||||
|
WindowEventCategory = bit(0),
|
||||||
|
InputEventCategory = bit(1),
|
||||||
|
KeyboardEventCategory = bit(2),
|
||||||
|
MouseEventCategory = bit(3),
|
||||||
|
};
|
||||||
|
|
||||||
|
class Event
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Event() = default;
|
||||||
|
|
||||||
|
virtual ~Event() = default;
|
||||||
|
|
||||||
|
[[nodiscard]] virtual auto get_event_type() const -> EventType = 0;
|
||||||
|
|
||||||
|
[[nodiscard]] virtual auto get_info_lt_log() const -> std::string = 0;
|
||||||
|
|
||||||
|
[[nodiscard]] virtual auto has_category(EventCategory category) const -> bool = 0;
|
||||||
|
|
||||||
|
friend auto operator<<(std::ostream &os, const Event &e) -> std::ostream &
|
||||||
|
{
|
||||||
|
return os << e.get_info_lt_log();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace lt
|
107
modules/input/include/input/events/keyboard.hpp
Normal file
107
modules/input/include/input/events/keyboard.hpp
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <input/events/event.hpp>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
namespace lt {
|
||||||
|
|
||||||
|
class KeyPressedEvent: public Event
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
KeyPressedEvent(int key): m_key(key)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_key() const -> int
|
||||||
|
{
|
||||||
|
return m_key;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_info_lt_log() const -> std::string override
|
||||||
|
{
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << "KeyPressed: " << m_key;
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_event_type() const -> EventType override
|
||||||
|
{
|
||||||
|
return ::lt::EventType::KeyPressed;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto has_category(EventCategory category) const -> bool override
|
||||||
|
{
|
||||||
|
return static_cast<uint8_t>(InputEventCategory | KeyboardEventCategory) & category;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const int m_key;
|
||||||
|
};
|
||||||
|
|
||||||
|
class KeyRepeatEvent: public Event
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
KeyRepeatEvent(int key): m_key(key)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_key() const -> int
|
||||||
|
{
|
||||||
|
return m_key;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_info_lt_log() const -> std::string override
|
||||||
|
{
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << "KeyRepeated: " << m_key;
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_event_type() const -> EventType override
|
||||||
|
{
|
||||||
|
return ::lt::EventType::KeyRepeated;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto has_category(EventCategory category) const -> bool override
|
||||||
|
{
|
||||||
|
return static_cast<uint8_t>(InputEventCategory | KeyboardEventCategory) & category;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const int m_key;
|
||||||
|
};
|
||||||
|
|
||||||
|
class KeyReleasedEvent: public Event
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
KeyReleasedEvent(int key): m_key(key)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_key() const -> int
|
||||||
|
{
|
||||||
|
return m_key;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_info_lt_log() const -> std::string override
|
||||||
|
{
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << "KeyReleased: " << m_key;
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_event_type() const -> EventType override
|
||||||
|
{
|
||||||
|
return ::lt::EventType::KeyReleased;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto has_category(EventCategory category) const -> bool override
|
||||||
|
{
|
||||||
|
return static_cast<uint8_t>(InputEventCategory | KeyboardEventCategory) & category;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const int m_key;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace lt
|
151
modules/input/include/input/events/mouse.hpp
Normal file
151
modules/input/include/input/events/mouse.hpp
Normal file
|
@ -0,0 +1,151 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
#include <input/events/event.hpp>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
namespace lt {
|
||||||
|
|
||||||
|
class MouseMovedEvent: public Event
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MouseMovedEvent(float x, float y): m_position(x, y)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_position() const -> const glm::vec2 &
|
||||||
|
{
|
||||||
|
return m_position;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_x() const -> float
|
||||||
|
{
|
||||||
|
return m_position.x;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_y() const -> float
|
||||||
|
{
|
||||||
|
return m_position.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_info_lt_log() const -> std::string override
|
||||||
|
{
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << "MouseMoved: " << m_position.x << ", " << m_position.y;
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_event_type() const -> EventType override
|
||||||
|
{
|
||||||
|
return ::lt::EventType::MouseMoved;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto has_category(EventCategory category) const -> bool override
|
||||||
|
{
|
||||||
|
return static_cast<uint8_t>(InputEventCategory | MouseEventCategory) & category;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const glm::vec2 m_position;
|
||||||
|
};
|
||||||
|
|
||||||
|
class WheelScrolledEvent: public Event
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
WheelScrolledEvent(float offset): m_offset(offset)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_offset() const -> float
|
||||||
|
{
|
||||||
|
return m_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_info_lt_log() const -> std::string override
|
||||||
|
{
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << "WheelScrolled: " << m_offset;
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_event_type() const -> EventType override
|
||||||
|
{
|
||||||
|
return ::lt::EventType::WheelScrolled;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto has_category(EventCategory category) const -> bool override
|
||||||
|
{
|
||||||
|
return static_cast<uint8_t>(InputEventCategory | MouseEventCategory) & category;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const float m_offset;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ButtonPressedEvent: public Event
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ButtonPressedEvent(int button): m_button(button)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_button() const -> int
|
||||||
|
{
|
||||||
|
return m_button;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_info_lt_log() const -> std::string override
|
||||||
|
{
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << "ButtonPressed: " << m_button;
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_event_type() const -> EventType override
|
||||||
|
{
|
||||||
|
return ::lt::EventType::ButtonPressed;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto has_category(EventCategory category) const -> bool override
|
||||||
|
{
|
||||||
|
return static_cast<uint8_t>(InputEventCategory | MouseEventCategory) & category;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const int m_button;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ButtonReleasedEvent: public Event
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ButtonReleasedEvent(int button): m_button(button)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_button() const -> int
|
||||||
|
{
|
||||||
|
return m_button;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_info_lt_log() const -> std::string override
|
||||||
|
{
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << "ButtonReleased: " << m_button;
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_event_type() const -> EventType override
|
||||||
|
{
|
||||||
|
return ::lt::EventType::ButtonReleased;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto has_category(EventCategory category) const -> bool override
|
||||||
|
{
|
||||||
|
return static_cast<uint8_t>(InputEventCategory | MouseEventCategory) & category;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const int m_button;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace lt
|
133
modules/input/include/input/events/window.hpp
Normal file
133
modules/input/include/input/events/window.hpp
Normal file
|
@ -0,0 +1,133 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
#include <input/events/event.hpp>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
namespace lt {
|
||||||
|
|
||||||
|
class WindowClosedEvent: public Event
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
[[nodiscard]] auto get_info_lt_log() const -> std::string override
|
||||||
|
{
|
||||||
|
return "WindowClosedEvent";
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_event_type() const -> EventType override
|
||||||
|
{
|
||||||
|
return ::lt::EventType::WindowClosed;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto has_category(EventCategory category) const -> bool override
|
||||||
|
{
|
||||||
|
return static_cast<uint8_t>(WindowEventCategory) & category;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class WindowMovedEvent: public Event
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
WindowMovedEvent(int x, int y): m_position(x, y)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_position() const -> const glm::ivec2 &
|
||||||
|
{
|
||||||
|
return m_position;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_info_lt_log() const -> std::string override
|
||||||
|
{
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << "WindwoMoved: " << m_position.x << ", " << m_position.y;
|
||||||
|
return ss.str();
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_event_type() const -> EventType override
|
||||||
|
{
|
||||||
|
return ::lt::EventType::WindowMoved;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto has_category(EventCategory category) const -> bool override
|
||||||
|
{
|
||||||
|
return static_cast<uint8_t>(WindowEventCategory) & category;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const glm::ivec2 m_position;
|
||||||
|
};
|
||||||
|
|
||||||
|
class WindowResizedEvent: public Event
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
WindowResizedEvent(unsigned int width, unsigned int height): m_size(width, height)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_size() const -> const glm::uvec2 &
|
||||||
|
{
|
||||||
|
return m_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_info_lt_log() const -> std::string override
|
||||||
|
{
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << "WindowResized: " << m_size.x << ", " << m_size.y;
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_event_type() const -> EventType override
|
||||||
|
{
|
||||||
|
return ::lt::EventType::WindowResized;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto has_category(EventCategory category) const -> bool override
|
||||||
|
{
|
||||||
|
return static_cast<uint8_t>(WindowEventCategory) & category;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const glm::uvec2 m_size;
|
||||||
|
};
|
||||||
|
|
||||||
|
class WindowLostFocusEvent: public Event
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
[[nodiscard]] auto get_info_lt_log() const -> std::string override
|
||||||
|
{
|
||||||
|
return "WindowLostFocus";
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_event_type() const -> EventType override
|
||||||
|
{
|
||||||
|
return ::lt::EventType::WindowLostFocus;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto has_category(EventCategory category) const -> bool override
|
||||||
|
{
|
||||||
|
return static_cast<uint8_t>(WindowEventCategory) & category;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class WindowGainFocusEvent: public Event
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
[[nodiscard]] auto get_info_lt_log() const -> std::string override
|
||||||
|
{
|
||||||
|
return "WindowGainFocus";
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_event_type() const -> EventType override
|
||||||
|
{
|
||||||
|
return ::lt::EventType::WindowGainFocus;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto has_category(EventCategory category) const -> bool override
|
||||||
|
{
|
||||||
|
return static_cast<uint8_t>(WindowEventCategory) & category;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace lt
|
|
@ -1,7 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <math/vec2.hpp>
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
namespace lt {
|
namespace lt {
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ public:
|
||||||
return instance().m_mouse_buttons[code];
|
return instance().m_mouse_buttons[code];
|
||||||
}
|
}
|
||||||
|
|
||||||
static auto get_mouse_position(int /*code*/) -> const math::vec2 &
|
static auto get_mouse_position(int /*code*/) -> const glm::vec2 &
|
||||||
{
|
{
|
||||||
return instance().m_mouse_position;
|
return instance().m_mouse_position;
|
||||||
}
|
}
|
||||||
|
@ -66,9 +66,9 @@ private:
|
||||||
|
|
||||||
std::array<bool, 8> m_mouse_buttons {};
|
std::array<bool, 8> m_mouse_buttons {};
|
||||||
|
|
||||||
math::vec2 m_mouse_position;
|
glm::vec2 m_mouse_position;
|
||||||
|
|
||||||
math::vec2 m_mouse_delta;
|
glm::vec2 m_mouse_delta;
|
||||||
|
|
||||||
float m_mouse_wheel_delta {};
|
float m_mouse_wheel_delta {};
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
#include <input/system.hpp>
|
|
||||||
|
|
||||||
namespace lt::input {
|
|
||||||
|
|
||||||
} // namespace lt::input
|
|
|
@ -1,64 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <surface/system.hpp>
|
|
||||||
|
|
||||||
namespace lt::input {
|
|
||||||
|
|
||||||
template<class... Ts>
|
|
||||||
struct overloads: Ts...
|
|
||||||
{
|
|
||||||
using Ts::operator()...;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @note If this system is attached, it will always consume the input events f rom surface.
|
|
||||||
* Therefore if you want any input detection mechanism, callbacks should be setup with this
|
|
||||||
* system and not directly with surface.
|
|
||||||
*/
|
|
||||||
class System
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
System(lt::surface::System &surface_system)
|
|
||||||
{
|
|
||||||
surface_system.add_event_listener([this](auto &&event) {
|
|
||||||
return handle_event(std::forward<decltype(event)>(event));
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
private:
|
|
||||||
auto handle_event(const lt::surface::System::Event &event) -> bool
|
|
||||||
{
|
|
||||||
const auto visitor = overloads {
|
|
||||||
[this](const lt::surface::KeyPressedEvent &event) {
|
|
||||||
m_keys[event.get_key()] = true;
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
|
|
||||||
[](const lt::surface::KeyRepeatEvent &) { return false; },
|
|
||||||
|
|
||||||
[](const lt::surface::KeyReleasedEvent &) { return false; },
|
|
||||||
|
|
||||||
[](const lt::surface::KeySetCharEvent &) { return false; },
|
|
||||||
|
|
||||||
[](const lt::surface::MouseMovedEvent &) { return false; },
|
|
||||||
|
|
||||||
[](const lt::surface::WheelScrolledEvent &) { return false; },
|
|
||||||
|
|
||||||
[](const lt::surface::ButtonPressedEvent &) { return false; },
|
|
||||||
|
|
||||||
[](const lt::surface::ButtonReleasedEvent &) { return false; },
|
|
||||||
|
|
||||||
[](const auto &) { return false; },
|
|
||||||
};
|
|
||||||
|
|
||||||
return std::visit(visitor, event);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setup_callbacks(GLFWwindow *handle);
|
|
||||||
|
|
||||||
std::array<bool, 512> m_keys {};
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace lt::input
|
|
|
@ -1,5 +1,10 @@
|
||||||
#include <imgui.h>
|
#include <imgui.h>
|
||||||
|
#include <input/events/char.hpp>
|
||||||
|
#include <input/events/event.hpp>
|
||||||
|
#include <input/events/keyboard.hpp>
|
||||||
|
#include <input/events/mouse.hpp>
|
||||||
#include <input/input.hpp>
|
#include <input/input.hpp>
|
||||||
|
#include <input/key_codes.hpp>
|
||||||
#include <logger/logger.hpp>
|
#include <logger/logger.hpp>
|
||||||
|
|
||||||
namespace lt {
|
namespace lt {
|
||||||
|
@ -31,8 +36,8 @@ void Input::restart_input_state()
|
||||||
m_keyboad_keys.fill(false);
|
m_keyboad_keys.fill(false);
|
||||||
m_mouse_buttons.fill(false);
|
m_mouse_buttons.fill(false);
|
||||||
|
|
||||||
m_mouse_position = math::vec2(0.0f);
|
m_mouse_position = glm::vec2(0.0f);
|
||||||
m_mouse_delta = math::vec2(0.0f);
|
m_mouse_delta = glm::vec2(0.0f);
|
||||||
m_mouse_wheel_delta = 0.0f;
|
m_mouse_wheel_delta = 0.0f;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1 +1,2 @@
|
||||||
add_library_module(logger logger.cpp)
|
add_library_module(logger logger.cpp)
|
||||||
|
target_link_libraries(logger PUBLIC spdlog::spdlog)
|
||||||
|
|
|
@ -1,9 +1,15 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <format>
|
#include <format>
|
||||||
#include <print>
|
#include <memory>
|
||||||
|
#include <spdlog/sinks/basic_file_sink.h>
|
||||||
|
#include <spdlog/sinks/stdout_color_sinks.h>
|
||||||
|
#include <spdlog/spdlog.h>
|
||||||
|
|
||||||
/** Severity of a log message. */
|
/** @brief Severity of a log message.
|
||||||
|
*
|
||||||
|
* @note Values reflect spdlog::lvl
|
||||||
|
*/
|
||||||
enum class LogLvl : uint8_t
|
enum class LogLvl : uint8_t
|
||||||
{
|
{
|
||||||
/** Lowest and most vebose log level, for tracing execution paths and events */
|
/** Lowest and most vebose log level, for tracing execution paths and events */
|
||||||
|
@ -28,7 +34,11 @@ enum class LogLvl : uint8_t
|
||||||
off = 6,
|
off = 6,
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Simple console logger */
|
namespace spdlog {
|
||||||
|
class logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Responsible for logging */
|
||||||
class Logger
|
class Logger
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -37,19 +47,26 @@ public:
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
void static log(LogLvl lvl, std::format_string<Args...> fmt, Args &&...args)
|
void static log(LogLvl lvl, std::format_string<Args...> fmt, Args &&...args)
|
||||||
{
|
{
|
||||||
std::ignore = lvl;
|
instance().spd_logger->log(
|
||||||
std::println(fmt, std::forward<Args>(args)...);
|
(spdlog::level::level_enum)lvl,
|
||||||
|
std::format(fmt, std::forward<Args>(args)...)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void static log(LogLvl lvl, const char *message)
|
void static log(LogLvl lvl, const char *message)
|
||||||
{
|
{
|
||||||
std::ignore = lvl;
|
instance().spd_logger->log((spdlog::level::level_enum)lvl, message);
|
||||||
std::println("{}", message);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Logger() = default;
|
Logger();
|
||||||
|
|
||||||
|
~Logger();
|
||||||
|
|
||||||
|
auto static instance() -> Logger &;
|
||||||
|
|
||||||
|
std::shared_ptr<spdlog::logger> spd_logger;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
|
@ -1 +0,0 @@
|
||||||
#include <logger/logger.hpp>
|
|
18
modules/logger/src/logger.cpp
Normal file
18
modules/logger/src/logger.cpp
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
#include <logger/logger.hpp>
|
||||||
|
|
||||||
|
Logger::Logger(): spd_logger(spdlog::stdout_color_mt("Logger"))
|
||||||
|
{
|
||||||
|
spd_logger->set_pattern("%^%v%$");
|
||||||
|
spd_logger->set_level(spdlog::level::level_enum::trace);
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger::~Logger()
|
||||||
|
{
|
||||||
|
spdlog::drop_all();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Logger::instance() -> Logger &
|
||||||
|
{
|
||||||
|
static auto logger = Logger {};
|
||||||
|
return logger;
|
||||||
|
}
|
|
@ -1 +0,0 @@
|
||||||
add_library_module(math)
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue