Compare commits
No commits in common. "66866387f1671fad598539d5d0682707a4555b22" and "b766c1dc35cb8c292da76457be091a9092a5ee15" have entirely different histories.
66866387f1
...
b766c1dc35
@ -1,18 +0,0 @@
|
|||||||
[bumpversion]
|
|
||||||
current_version = ALPHA-2.0.0
|
|
||||||
commit = True
|
|
||||||
tag = True
|
|
||||||
tag_name = v{new_version}
|
|
||||||
|
|
||||||
[bumpversion:file:VERSION]
|
|
||||||
search = {current_version}
|
|
||||||
replace = {new_version}
|
|
||||||
|
|
||||||
[bumpversion:part:major]
|
|
||||||
first_value = 2
|
|
||||||
|
|
||||||
[bumpversion:part:minor]
|
|
||||||
first_value = 0
|
|
||||||
|
|
||||||
[bumpversion:part:patch]
|
|
||||||
first_value = 0
|
|
@ -1,58 +0,0 @@
|
|||||||
# Generated from CLion C/C++ Code Style settings
|
|
||||||
---
|
|
||||||
Language: Cpp
|
|
||||||
BasedOnStyle: LLVM
|
|
||||||
AccessModifierOffset: -4
|
|
||||||
AlignConsecutiveAssignments: false
|
|
||||||
AlignConsecutiveDeclarations: false
|
|
||||||
AlignOperands: true
|
|
||||||
AlignTrailingComments: false
|
|
||||||
AlwaysBreakTemplateDeclarations: Yes
|
|
||||||
BraceWrapping:
|
|
||||||
AfterCaseLabel: false
|
|
||||||
AfterClass: false
|
|
||||||
AfterControlStatement: false
|
|
||||||
AfterEnum: false
|
|
||||||
AfterFunction: false
|
|
||||||
AfterNamespace: false
|
|
||||||
AfterStruct: false
|
|
||||||
AfterUnion: false
|
|
||||||
AfterExternBlock: false
|
|
||||||
BeforeCatch: false
|
|
||||||
BeforeElse: false
|
|
||||||
BeforeLambdaBody: false
|
|
||||||
BeforeWhile: false
|
|
||||||
SplitEmptyFunction: true
|
|
||||||
SplitEmptyRecord: true
|
|
||||||
SplitEmptyNamespace: true
|
|
||||||
BreakBeforeBraces: Custom
|
|
||||||
BreakConstructorInitializers: AfterColon
|
|
||||||
BreakConstructorInitializersBeforeComma: false
|
|
||||||
ColumnLimit: 120
|
|
||||||
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
|
||||||
ContinuationIndentWidth: 8
|
|
||||||
IncludeCategories:
|
|
||||||
- Regex: '^<.*'
|
|
||||||
Priority: 1
|
|
||||||
- Regex: '^".*'
|
|
||||||
Priority: 2
|
|
||||||
- Regex: '.*'
|
|
||||||
Priority: 3
|
|
||||||
IncludeIsMainRegex: '([-_](test|unittest))?$'
|
|
||||||
IndentCaseLabels: true
|
|
||||||
IndentWidth: 4
|
|
||||||
InsertNewlineAtEOF: true
|
|
||||||
MacroBlockBegin: ''
|
|
||||||
MacroBlockEnd: ''
|
|
||||||
MaxEmptyLinesToKeep: 2
|
|
||||||
NamespaceIndentation: All
|
|
||||||
SpaceAfterCStyleCast: true
|
|
||||||
SpaceAfterTemplateKeyword: false
|
|
||||||
SpaceBeforeRangeBasedForLoopColon: false
|
|
||||||
SpaceInEmptyParentheses: false
|
|
||||||
SpacesInAngles: false
|
|
||||||
SpacesInConditionalStatement: false
|
|
||||||
SpacesInCStyleCastParentheses: false
|
|
||||||
SpacesInParentheses: false
|
|
||||||
TabWidth: 4
|
|
||||||
...
|
|
24
.gitignore
vendored
24
.gitignore
vendored
@ -1,6 +1,22 @@
|
|||||||
# IDE Generated Files
|
# IDE Files
|
||||||
cmake-build-debug/
|
.vscode/
|
||||||
|
.jb/
|
||||||
.idea/
|
.idea/
|
||||||
|
|
||||||
# Build folders
|
# Build directories
|
||||||
*build/
|
build/
|
||||||
|
build-vs/
|
||||||
|
build-debug/
|
||||||
|
build-release/
|
||||||
|
build-minsizerel/
|
||||||
|
cmake-build-debug/
|
||||||
|
build*/
|
||||||
|
|
||||||
|
# Tooling files
|
||||||
|
output.txt
|
||||||
|
buildall.bat
|
||||||
|
typer.py
|
||||||
|
|
||||||
|
# Sandbox Assets
|
||||||
|
assets/
|
||||||
|
art/
|
||||||
|
292
CMakeLists.txt
292
CMakeLists.txt
@ -1,76 +1,242 @@
|
|||||||
CMAKE_MINIMUM_REQUIRED(VERSION 3.18)
|
cmake_minimum_required(VERSION 3.28)
|
||||||
PROJECT(ICEngine LANGUAGES CXX C VERSION 1.0.0)
|
|
||||||
|
|
||||||
# Read version for logger
|
project(IsoEngine LANGUAGES CXX)
|
||||||
FILE(READ "${CMAKE_CURRENT_SOURCE_DIR}/VERSION" VERSION_TEXT)
|
|
||||||
STRING(STRIP "${VERSION_TEXT}" VERSION_TEXT)
|
|
||||||
STRING(REGEX MATCH "([A-Z]+)-([0-9]+)\\.([0-9]+)\\.([0-9]+)" _ ${VERSION_TEXT})
|
|
||||||
SET(PROJECT_VERSION ${CMAKE_MATCH_1}-${CMAKE_MATCH_2}.${CMAKE_MATCH_3}.${CMAKE_MATCH_4})
|
|
||||||
ADD_DEFINITIONS(-DPROJECT_VERSION=\"${PROJECT_VERSION}\")
|
|
||||||
|
|
||||||
OPTION(BUILD_ENGINE_AS_SHARED_LIBRARY "Build engine as a shared library" OFF)
|
# Options for shared/static libraries, and client/server examples
|
||||||
OPTION(BUILD_DEPS_AS_SHARED_LIBRARIES "Builds engine's dependencies as shared libraries" OFF)
|
option(BUILD_SHARED_LIBS "Build engine library dependencies as shared (DLLs)" OFF)
|
||||||
OPTION(BUILD_EXAMPLES "Builds examples to showcase engine" ON)
|
option(BUILD_CLIENT "Build the client example" ON)
|
||||||
|
option(BUILD_SERVER "Build the server example" ON)
|
||||||
|
|
||||||
IF (CMAKE_GENERATOR MATCHES "Visual Studio|Xcode")
|
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
||||||
SET(CMAKE_CONFIGURATION_TYPES "Debug;Release;MinSizeRel" CACHE STRING "" FORCE)
|
message(STATUS "No build type specified, defaulting to Debug")
|
||||||
ELSE ()
|
set(CMAKE_BUILD_TYPE "Debug" CACHE STRING "Choose the type of build." FORCE)
|
||||||
IF (NOT CMAKE_BUILD_TYPE)
|
endif()
|
||||||
MESSAGE(" | ICEngine | No build type specified, defaulting to Debug")
|
|
||||||
SET(CMAKE_BUILD_TYPE "Debug" CACHE STRING "Choose the type of build: Debug, Release, MinSizeRel" FORCE)
|
|
||||||
ENDIF ()
|
|
||||||
ENDIF ()
|
|
||||||
|
|
||||||
SET(ARCHITECTURE "x64")
|
set(CMAKE_CXX_STANDARD 20)
|
||||||
SET(CMAKE_CXX_STANDARD 20)
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
SET(CMAKE_CXX_STANDARD_REQUIRED ON)
|
set(CMAKE_XCODE_GENERATE_SCHEME ON)
|
||||||
SET(CMAKE_XCODE_GENERATE_SCHEME ON)
|
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||||
SET(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
|
||||||
SET(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
|
||||||
|
|
||||||
MESSAGE(STATUS "Building for x64 architecture")
|
# Output directory settings
|
||||||
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m64")
|
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
|
||||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -m64")
|
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
|
||||||
|
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
|
||||||
|
|
||||||
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${ARCH_DIR}/bin)
|
if(POLICY CMP0077)
|
||||||
SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${ARCH_DIR}/lib)
|
cmake_policy(SET CMP0077 NEW)
|
||||||
SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${ARCH_DIR}/lib)
|
endif()
|
||||||
|
|
||||||
IF (MSVC)
|
set(FETCHCONTENT_QUIET OFF)
|
||||||
ADD_COMPILE_OPTIONS(/W4 /WX)
|
include(FetchContent)
|
||||||
ELSE ()
|
|
||||||
ADD_COMPILE_OPTIONS(-Wall -Wextra -Werror -Wpedantic)
|
|
||||||
ENDIF ()
|
|
||||||
|
|
||||||
INCLUDE_DIRECTORIES(
|
# enet is header-only
|
||||||
engine/src/core
|
set(ENET_INCLUDE_DIR "${CMAKE_CURRENT_LIST_DIR}/vendor/enet")
|
||||||
|
|
||||||
|
FetchContent_Declare(
|
||||||
|
raylib
|
||||||
|
URL https://github.com/raysan5/raylib/archive/refs/tags/5.0.zip
|
||||||
|
)
|
||||||
|
set(BUILD_EXAMPLES OF CACHE BOOL "" FORCE)
|
||||||
|
set(SUPPORT_EVENTS_WAITING ON CACHE BOOL "" FORCE)
|
||||||
|
set(SUPPORT_BUSY_WAIT_LOOP OFF CACHE BOOL "" FORCE)
|
||||||
|
|
||||||
|
if (BUILD_SHARED_LIBS)
|
||||||
|
set(RAYLIB_LIBTYPE SHARED)
|
||||||
|
endif()
|
||||||
|
FetchContent_MakeAvailable(raylib)
|
||||||
|
|
||||||
|
FetchContent_Declare(
|
||||||
|
imgui
|
||||||
|
GIT_REPOSITORY https://github.com/ocornut/imgui.git
|
||||||
|
GIT_TAG v1.91.1
|
||||||
|
GIT_SHALLOW TRUE
|
||||||
|
)
|
||||||
|
FetchContent_MakeAvailable(imgui)
|
||||||
|
|
||||||
|
add_library(ImGui ${imgui_SOURCE_DIR}/imgui.cpp
|
||||||
|
${imgui_SOURCE_DIR}/imgui_demo.cpp
|
||||||
|
${imgui_SOURCE_DIR}/imgui_draw.cpp
|
||||||
|
${imgui_SOURCE_DIR}/imgui_tables.cpp
|
||||||
|
${imgui_SOURCE_DIR}/imgui_widgets.cpp
|
||||||
|
)
|
||||||
|
target_include_directories(ImGui PUBLIC ${imgui_SOURCE_DIR})
|
||||||
|
|
||||||
|
FetchContent_Declare(
|
||||||
|
rlimgui
|
||||||
|
GIT_REPOSITORY https://github.com/raylib-extras/rlImGui.git
|
||||||
|
GIT_TAG main
|
||||||
|
GIT_SHALLOW TRUE
|
||||||
|
)
|
||||||
|
FetchContent_MakeAvailable(rlimgui)
|
||||||
|
|
||||||
|
FetchContent_Declare(
|
||||||
|
box2d
|
||||||
|
GIT_REPOSITORY https://github.com/erincatto/box2d.git
|
||||||
|
GIT_TAG v3.0.0
|
||||||
|
)
|
||||||
|
FetchContent_MakeAvailable(box2d)
|
||||||
|
|
||||||
|
FetchContent_Declare(
|
||||||
|
entt
|
||||||
|
GIT_REPOSITORY https://github.com/skypjack/entt.git
|
||||||
|
GIT_TAG v3.13.2
|
||||||
|
)
|
||||||
|
FetchContent_MakeAvailable(entt)
|
||||||
|
|
||||||
|
FetchContent_Declare(
|
||||||
|
physfs
|
||||||
|
GIT_REPOSITORY https://github.com/icculus/physfs.git
|
||||||
|
GIT_TAG release-3.2.0
|
||||||
|
)
|
||||||
|
# PhysFS settings (default: static)
|
||||||
|
set(PHYSFS_BUILD_STATIC ON CACHE BOOL "Build PhysFS static library" FORCE)
|
||||||
|
set(PHYSFS_BUILD_SHARED OFF CACHE BOOL "Do not build PhysFS shared library" FORCE)
|
||||||
|
if(BUILD_SHARED_LIBS)
|
||||||
|
set(PHYSFS_BUILD_SHARED ON CACHE BOOL "Build PhysFS shared library" FORCE)
|
||||||
|
set(PHYSFS_BUILD_STATIC OFF CACHE BOOL "Do not build PhysFS static library" FORCE)
|
||||||
|
endif()
|
||||||
|
set(PHYSFS_BUILD_TEST OFF CACHE BOOL "Disable PhysFS test program" FORCE)
|
||||||
|
FetchContent_MakeAvailable(physfs)
|
||||||
|
|
||||||
|
# Main Engine Library
|
||||||
|
set(ENGINE_SOURCES
|
||||||
|
src/IsoEngine.cpp
|
||||||
|
src/enet_client.cpp
|
||||||
|
src/enet_server.cpp
|
||||||
|
|
||||||
|
src/Logger.cpp
|
||||||
|
|
||||||
|
src/components/sprite_component.cpp
|
||||||
|
src/components/physics_component.cpp
|
||||||
|
src/components/input_component.cpp
|
||||||
|
src/components/ui_component.cpp
|
||||||
|
|
||||||
|
src/scene_manager.cpp
|
||||||
|
src/filepacker.cpp
|
||||||
|
)
|
||||||
|
if (WIN32)
|
||||||
|
list(APPEND ENGINE_SOURCES src/platform/windows/FatalHandlerWindows.cpp)
|
||||||
|
elseif(UNIX)
|
||||||
|
list(APPEND ENGINE_SOURCES src/platform/posix/FatalHandlerPosix.cpp)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_library(IsoEngine ${ENGINE_SOURCES})
|
||||||
|
|
||||||
|
target_include_directories(IsoEngine PUBLIC
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/src
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/src/components
|
||||||
|
${raylib_SOURCE_DIR}
|
||||||
|
${imgui_SOURCE_DIR}
|
||||||
|
${rlimgui_SOURCE_DIR}
|
||||||
|
${box2d_SOURCE_DIR}/include
|
||||||
|
${physfs_SOURCE_DIR}/src
|
||||||
|
${entt_SOURCE_DIR}/src
|
||||||
|
${ENET_INCLUDE_DIR}
|
||||||
)
|
)
|
||||||
|
|
||||||
SET(EngineSources
|
target_link_libraries(IsoEngine PRIVATE raylib box2d EnTT::EnTT)
|
||||||
engine/src/core/ICEngine.cpp
|
target_precompile_headers(IsoEngine PRIVATE src/IsoEnginePCH.h)
|
||||||
)
|
|
||||||
|
|
||||||
IF (BUILD_ENGINE_AS_SHARED_LIBRARY)
|
# PhysFS linkage
|
||||||
ADD_LIBRARY(ICEngine SHARED ${EngineSources})
|
if(BUILD_SHARED_LIBS)
|
||||||
SET_TARGET_PROPERTIES(ICEngine PROPERTIES
|
target_link_libraries(IsoEngine PRIVATE PhysFS::PhysFS)
|
||||||
OUTPUT_NAME "ICEngine"
|
else()
|
||||||
WINDOWS_EXPORT_ALL_SYMBOLS ON
|
target_link_libraries(IsoEngine PRIVATE PhysFS::PhysFS-static)
|
||||||
|
target_compile_definitions(IsoEngine PRIVATE PHYSFS_STATIC)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# rlImGui library linking
|
||||||
|
add_library(rlImGui ${rlimgui_SOURCE_DIR}/rlImGui.cpp)
|
||||||
|
target_include_directories(rlImGui PUBLIC ${rlimgui_SOURCE_DIR} ${imgui_SOURCE_DIR})
|
||||||
|
target_link_libraries(rlImGui PRIVATE raylib ImGui)
|
||||||
|
target_link_libraries(IsoEngine PRIVATE ImGui rlImGui)
|
||||||
|
|
||||||
|
# Example executables (client/server)
|
||||||
|
if(BUILD_CLIENT)
|
||||||
|
# Client executable
|
||||||
|
set(CLIENT_SOURCE "${CMAKE_CURRENT_LIST_DIR}/sandbox/client.cpp")
|
||||||
|
add_executable(client ${CLIENT_SOURCE})
|
||||||
|
target_include_directories(client PRIVATE ${ENET_INCLUDE_DIR})
|
||||||
|
target_link_libraries(client PRIVATE IsoEngine raylib)
|
||||||
|
|
||||||
|
# Platform-specific linking for client (Windows)
|
||||||
|
if(WIN32)
|
||||||
|
target_link_libraries(client PRIVATE winmm ws2_32)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Server executable
|
||||||
|
set(SERVER_SOURCE "${CMAKE_CURRENT_LIST_DIR}/sandbox/server.cpp")
|
||||||
|
add_executable(server ${SERVER_SOURCE})
|
||||||
|
target_include_directories(server PRIVATE ${ENET_INCLUDE_DIR})
|
||||||
|
target_link_libraries(server PRIVATE IsoEngine)
|
||||||
|
|
||||||
|
# Platform-specific linking for server (Windows)
|
||||||
|
if(WIN32)
|
||||||
|
target_link_libraries(server PRIVATE winmm ws2_32)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Platform-specific linking for IsoEngine (Raylib and Winsock for ENet on Windows)
|
||||||
|
if(WIN32)
|
||||||
|
target_link_libraries(IsoEngine PRIVATE winmm ws2_32)
|
||||||
|
add_definitions(-DWIN32_LEAN_AND_MEAN)
|
||||||
|
add_definitions(-D_WINSOCK_DEPRECATED_NO_WARNINGS)
|
||||||
|
add_definitions(-D_HAS_EXCEPTIONS=0)
|
||||||
|
elseif(APPLE)
|
||||||
|
target_link_libraries(IsoEngine PRIVATE "-framework CoreVideo" "-framework IOKit" "-framework Cocoa" "-framework GLUT" "-framework OpenGL")
|
||||||
|
else()
|
||||||
|
target_link_libraries(IsoEngine PRIVATE m pthread GL dl X11)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Build Configuration Optimizations
|
||||||
|
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||||
|
message(STATUS "Configuring Debug build: No optimizations applied.")
|
||||||
|
target_compile_definitions(IsoEngine PRIVATE ENABLE_LOGGING)
|
||||||
|
elseif(CMAKE_BUILD_TYPE STREQUAL "Release")
|
||||||
|
message(STATUS "Configuring Release build: Applying moderate optimizations.")
|
||||||
|
target_compile_options(IsoEngine PRIVATE -O2)
|
||||||
|
if(BUILD_CLIENT OR BUILD_SANDBOX)
|
||||||
|
target_compile_options(client PRIVATE -O2)
|
||||||
|
target_compile_options(server PRIVATE -O2)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Strip symbols after building
|
||||||
|
if(NOT MSVC)
|
||||||
|
add_custom_command(TARGET IsoEngine POST_BUILD
|
||||||
|
COMMAND ${CMAKE_STRIP} --strip-unneeded $<TARGET_FILE:IsoEngine>
|
||||||
|
COMMENT "Stripping unneeded symbols from the IsoEngine binary in Release build."
|
||||||
)
|
)
|
||||||
ELSE ()
|
if(BUILD_CLIENT OR BUILD_SANDBOX)
|
||||||
ADD_LIBRARY(ICEngine STATIC ${EngineSources})
|
add_custom_command(TARGET client POST_BUILD
|
||||||
SET_TARGET_PROPERTIES(ICEngine PROPERTIES OUTPUT_NAME "ICEngine")
|
COMMAND ${CMAKE_STRIP} --strip-unneeded $<TARGET_FILE:client>
|
||||||
ENDIF ()
|
COMMENT "Stripping unneeded symbols from the client binary in Release build."
|
||||||
|
)
|
||||||
|
add_custom_command(TARGET server POST_BUILD
|
||||||
|
COMMAND ${CMAKE_STRIP} --strip-unneeded $<TARGET_FILE:server>
|
||||||
|
COMMENT "Stripping unneeded symbols from the server binary in Release build."
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
elseif(CMAKE_BUILD_TYPE STREQUAL "MinSizeRel")
|
||||||
|
message(STATUS "Configuring MinSizeRel build: Applying aggressive size optimizations.")
|
||||||
|
target_compile_options(IsoEngine PRIVATE -Os -ffunction-sections -fdata-sections)
|
||||||
|
target_link_options(IsoEngine PRIVATE -Wl,--gc-sections -Wl,--as-needed)
|
||||||
|
|
||||||
IF (BUILD_EXAMPLES)
|
# Strip symbols aggressively after building
|
||||||
INCLUDE_DIRECTORIES(examples/server)
|
if(NOT MSVC)
|
||||||
INCLUDE_DIRECTORIES(examples/client)
|
add_custom_command(TARGET IsoEngine POST_BUILD
|
||||||
|
COMMAND ${CMAKE_STRIP} --strip-all $<TARGET_FILE:IsoEngine>
|
||||||
ADD_EXECUTABLE(server_example examples/server/server.cpp)
|
COMMENT "Stripping all symbols from the IsoEngine binary in MinSizeRel build."
|
||||||
TARGET_LINK_LIBRARIES(server_example PRIVATE ICEngine)
|
)
|
||||||
|
if(BUILD_CLIENT OR BUILD_SANDBOX)
|
||||||
ADD_EXECUTABLE(client_example examples/client/client.cpp)
|
add_custom_command(TARGET client POST_BUILD
|
||||||
TARGET_LINK_LIBRARIES(client_example PRIVATE ICEngine)
|
COMMAND ${CMAKE_STRIP} --strip-all $<TARGET_FILE:client>
|
||||||
|
COMMENT "Stripping all symbols from the client binary in MinSizeRel build."
|
||||||
SET_TARGET_PROPERTIES(server_example PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
|
)
|
||||||
SET_TARGET_PROPERTIES(client_example PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
|
add_custom_command(TARGET server POST_BUILD
|
||||||
ENDIF ()
|
COMMAND ${CMAKE_STRIP} --strip-all $<TARGET_FILE:server>
|
||||||
|
COMMENT "Stripping all symbols from the server binary in MinSizeRel build."
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
32
README.md
32
README.md
@ -1,36 +1,8 @@
|
|||||||
# ICEngine
|
# Iso Engine
|
||||||
|
|
||||||
Smol little game engine since I have no idea what I'm doing
|
Smol little game engine since I have no idea what I'm doing
|
||||||
|
|
||||||
# Notice:
|
# Notice:
|
||||||
|
|
||||||
Since this uses the newer cpp modules, you need to make sure your compiler + build system + IDE supports this. You can
|
Since this uses the newer cpp modules, you need to make sure your compiler + build system + IDE supports this. You can
|
||||||
find more
|
find more info [on this stack overflow post](https://stackoverflow.com/questions/57300495/how-to-use-c20-modules-with-cmake).
|
||||||
info [on this stack overflow post](https://stackoverflow.com/questions/57300495/how-to-use-c20-modules-with-cmake).
|
|
||||||
|
|
||||||
## Building
|
|
||||||
Find more info about building the project in the `docs/Building.md` file.
|
|
||||||
|
|
||||||
(CMake >= 3.28)
|
|
||||||
|
|
||||||
# Using the engine as a library
|
|
||||||
You're more than welcome to use this engine for your game. The recommended way to build the project is using CMake:
|
|
||||||
|
|
||||||
### Fetch Content:
|
|
||||||
```cmake
|
|
||||||
# Enable FetchContent module
|
|
||||||
include(FetchContent)
|
|
||||||
|
|
||||||
# Fetch the external repository
|
|
||||||
FetchContent_Declare(
|
|
||||||
ICEngine
|
|
||||||
GIT_REPOSITORY http://proudcricle:3001/illyum/ICEngine.git
|
|
||||||
GIT_TAG main
|
|
||||||
)
|
|
||||||
|
|
||||||
# Then add your sources and executable
|
|
||||||
add_executable(MyGame main.cpp)
|
|
||||||
|
|
||||||
# Link the ICEngine library to your project
|
|
||||||
target_link_libraries(MyGame PRIVATE ICEngine)
|
|
||||||
```
|
|
||||||
|
@ -1,19 +0,0 @@
|
|||||||
# Building
|
|
||||||
|
|
||||||
ICEngine supports both single and multi type configuration types:
|
|
||||||
Make/Ninja
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
|
|
||||||
cmake --build build
|
|
||||||
```
|
|
||||||
|
|
||||||
\- OR -
|
|
||||||
|
|
||||||
Visual Studio:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cmake -S . -B build -G "Visual Studio 16 2019" # or your preferred Visual Studio version
|
|
||||||
cmake --build build --config Debug
|
|
||||||
cmake --build build --config Release
|
|
||||||
```
|
|
@ -1,39 +0,0 @@
|
|||||||
# Dev Notes
|
|
||||||
|
|
||||||
### Version Bumping
|
|
||||||
|
|
||||||
We use a tool called `bump2version` to manage bumping versions in the project. To ensure a clean git history and avoid
|
|
||||||
conflicts, follow these steps when bumping the version:
|
|
||||||
|
|
||||||
1. **Before bumping the version**, always `git pull` to ensure you have the latest changes from the repository.
|
|
||||||
2. Ensure no other copies of the repo are being worked on or committed before running the `bump2version` tool.
|
|
||||||
3. Bump the version using the command:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
bumpversion [major|minor|patch]
|
|
||||||
```
|
|
||||||
|
|
||||||
This will:
|
|
||||||
|
|
||||||
1. Update the version in the VERSION file.
|
|
||||||
1. Automatically commit the version bump.
|
|
||||||
1. Create a Git tag with the new version (e.g., vALPHA-2.0.1).
|
|
||||||
|
|
||||||
Push your changes and the tag to the remote repository after bumping the version:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git push origin master --tags
|
|
||||||
```
|
|
||||||
|
|
||||||
ersioning Guidelines
|
|
||||||
|
|
||||||
We follow a versioning structure of ALPHA-major.minor.patch. Here’s a breakdown of the versioning rules:
|
|
||||||
|
|
||||||
- **Major**: The major version is incremented for significant changes that introduce new features or incompatible API
|
|
||||||
changes.
|
|
||||||
- **Minor**: The minor version is incremented for adding new functionality in a backwards-compatible manner.
|
|
||||||
- **Patch**: The patch version is incremented for bug fixes and minor improvements that don’t affect the existing
|
|
||||||
functionality.
|
|
||||||
|
|
||||||
This will be managed by a CI/CD pipeline (or Gitea Actions) later down the line, but for now, follow these manual steps
|
|
||||||
carefully to ensure version consistency.
|
|
20
docs/ideas.md
Normal file
20
docs/ideas.md
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
# Ideas for this/future engine
|
||||||
|
Also just an outline for stuff
|
||||||
|
|
||||||
|
- Custom Logger
|
||||||
|
- CMake / Premake / XMake
|
||||||
|
- Event System
|
||||||
|
- Window Handler (support multiple windows)
|
||||||
|
- Layer system
|
||||||
|
- Math helpers
|
||||||
|
- Static/Dynamic linking
|
||||||
|
- Export or Build (export game as game file, or build your own exe directly)
|
||||||
|
- Shader System
|
||||||
|
- Entity Component System?
|
||||||
|
- Profiling
|
||||||
|
- Scripting? (lua?) + while-running / preprocessed scripts
|
||||||
|
- Tools (Sprite Sheet Tools, etc)
|
||||||
|
- Asset Manager / Pipeline (choose between .pak or individual files)
|
||||||
|
- Physics
|
||||||
|
- Collision Detection
|
||||||
|
|
@ -1,3 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by illyum on 9/15/2024.
|
|
||||||
//
|
|
@ -1,19 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by illyum on 9/14/2024.
|
|
||||||
//
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
class Logger {
|
|
||||||
public:
|
|
||||||
void logVersion() {
|
|
||||||
std::cout << "ICEngine Version: " << PROJECT_VERSION << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
void logCrash(const std::string& errorMessage) {
|
|
||||||
std::cerr << "Crash detected in version " << PROJECT_VERSION << ": " << errorMessage << std::endl;
|
|
||||||
}
|
|
||||||
};
|
|
@ -1,11 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by illyum on 9/15/2024.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include <Logger.hpp>
|
|
||||||
|
|
||||||
int main() {
|
|
||||||
Logger logger;
|
|
||||||
logger.logVersion();
|
|
||||||
return 0;
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by illyum on 9/15/2024.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include <Logger.hpp>
|
|
||||||
|
|
||||||
int main() {
|
|
||||||
Logger logger;
|
|
||||||
logger.logVersion();
|
|
||||||
return 0;
|
|
||||||
}
|
|
99
sandbox/client.cpp
Normal file
99
sandbox/client.cpp
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
#include "IsoEngine.h"
|
||||||
|
#include "components.h"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#define ENABLE_LOGGING
|
||||||
|
|
||||||
|
enum class MenuState {
|
||||||
|
MAIN_MENU,
|
||||||
|
OPTIONS,
|
||||||
|
QUIT
|
||||||
|
};
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
int screenWidth = 800;
|
||||||
|
int screenHeight = 600;
|
||||||
|
IsoEngine engine(screenWidth, screenHeight, nullptr);
|
||||||
|
engine.Initialize();
|
||||||
|
|
||||||
|
SceneManager& sceneManager = engine.GetSceneManager();
|
||||||
|
entt::entity mainMenuScene = sceneManager.CreateScene();
|
||||||
|
|
||||||
|
auto& registry = engine.GetRegistry();
|
||||||
|
|
||||||
|
// Button dimensions
|
||||||
|
float buttonWidth = 200.0f;
|
||||||
|
float buttonHeight = 50.0f;
|
||||||
|
float spacing = 20.0f; // Vertical spacing between buttons
|
||||||
|
|
||||||
|
// Center X position
|
||||||
|
float centerX = screenWidth / 2 - buttonWidth / 2;
|
||||||
|
|
||||||
|
// Y positions for each button
|
||||||
|
float singlePlayerY = screenHeight / 2 - (buttonHeight + spacing);
|
||||||
|
float quitButtonY = screenHeight / 2 + (buttonHeight + spacing);
|
||||||
|
|
||||||
|
// Create a UI button for "Single Player"
|
||||||
|
entt::entity singlePlayerButton = registry.create();
|
||||||
|
registry.emplace<TransformComponent>(singlePlayerButton, centerX, singlePlayerY, 1.0f, 1.0f, 0.0f); // Centered horizontally
|
||||||
|
registry.emplace<UIComponent>(singlePlayerButton, "Single Player", buttonWidth, buttonHeight, [&]() {
|
||||||
|
std::cout << "Single Player button clicked!" << std::endl;
|
||||||
|
});
|
||||||
|
registry.emplace<LayerComponent>(singlePlayerButton, 1); // Main menu on layer 1
|
||||||
|
|
||||||
|
// Create a "Quit" button
|
||||||
|
entt::entity quitButton = registry.create();
|
||||||
|
registry.emplace<TransformComponent>(quitButton, centerX, quitButtonY, 1.0f, 1.0f, 0.0f); // Centered horizontally
|
||||||
|
registry.emplace<UIComponent>(quitButton, "Quit", buttonWidth, buttonHeight, [&]() {
|
||||||
|
engine.Shutdown();
|
||||||
|
});
|
||||||
|
registry.emplace<LayerComponent>(quitButton, 1); // Also on layer 1
|
||||||
|
|
||||||
|
// Create an "F3" debug overlay on a higher layer
|
||||||
|
entt::entity debugOverlay = registry.create();
|
||||||
|
registry.emplace<TransformComponent>(debugOverlay, 10.0f, 10.0f, 1.0f, 1.0f, 0.0f); // Placed at top-left corner
|
||||||
|
registry.emplace<UIComponent>(debugOverlay, "FPS: 60\nPosition: (100, 200)", 300.0f, 100.0f, nullptr);
|
||||||
|
registry.emplace<LayerComponent>(debugOverlay, 2); // Debug overlay on layer 2
|
||||||
|
|
||||||
|
// Set active scene to the main menu
|
||||||
|
sceneManager.SetActiveScene(mainMenuScene);
|
||||||
|
|
||||||
|
// Run the engine loop
|
||||||
|
engine.Run();
|
||||||
|
|
||||||
|
engine.Shutdown();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// entt::entity gameScene = sceneManager.CreateScene();
|
||||||
|
// sceneManager.SetActiveScene(gameScene);
|
||||||
|
//
|
||||||
|
// entt::entity player = engine.GetRegistry().create();
|
||||||
|
// engine.GetRegistry().emplace<TransformComponent>(player, 400.0f, 300.0f, 1.0f, 1.0f, 0.0f);
|
||||||
|
//
|
||||||
|
// auto& inputComponent = engine.GetRegistry().emplace<InputComponent>(player);
|
||||||
|
//
|
||||||
|
// inputComponent.BindKey(InputAction::MOVE_UP, KEY_W);
|
||||||
|
// inputComponent.BindKey(InputAction::MOVE_DOWN, KEY_S);
|
||||||
|
// inputComponent.BindKey(InputAction::MOVE_LEFT, KEY_A);
|
||||||
|
// inputComponent.BindKey(InputAction::MOVE_RIGHT, KEY_D);
|
||||||
|
//
|
||||||
|
// inputComponent.SetActionCallback(InputAction::MOVE_UP, [&]() {
|
||||||
|
// auto& transform = engine.GetRegistry().get<TransformComponent>(player);
|
||||||
|
// transform.y -= 5.0f;
|
||||||
|
// });
|
||||||
|
// inputComponent.SetActionCallback(InputAction::MOVE_DOWN, [&]() {
|
||||||
|
// auto& transform = engine.GetRegistry().get<TransformComponent>(player);
|
||||||
|
// transform.y += 5.0f;
|
||||||
|
// });
|
||||||
|
// inputComponent.SetActionCallback(InputAction::MOVE_LEFT, [&]() {
|
||||||
|
// auto& transform = engine.GetRegistry().get<TransformComponent>(player);
|
||||||
|
// transform.x -= 5.0f;
|
||||||
|
// });
|
||||||
|
// inputComponent.SetActionCallback(InputAction::MOVE_RIGHT, [&]() {
|
||||||
|
// auto& transform = engine.GetRegistry().get<TransformComponent>(player);
|
||||||
|
// transform.x += 5.0f;
|
||||||
|
// });
|
4
sandbox/server.cpp
Normal file
4
sandbox/server.cpp
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
|
||||||
|
int main() {
|
||||||
|
return 0;
|
||||||
|
}
|
19
src/FatalHandler.h
Normal file
19
src/FatalHandler.h
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
//
|
||||||
|
// Created by illyum on 9/13/2024.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef FATALHANDLER_H
|
||||||
|
#define FATALHANDLER_H
|
||||||
|
|
||||||
|
#include <IsoEnginePCH.h>
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: Implement warning popup/crash handler (platform specific)
|
||||||
|
// TODO: Separate fatal handlers for core (the engine) and app (the user's app)
|
||||||
|
// maybe let the user handle their own fatal errors if they so choose, or they can use the default? similar
|
||||||
|
// to how the user has to specify an engine application
|
||||||
|
namespace IsoEngine {
|
||||||
|
void FatalHandler(const std::string& message);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //FATALHANDLER_H
|
68
src/IsoEngine.cpp
Normal file
68
src/IsoEngine.cpp
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
#include "IsoEngine.h"
|
||||||
|
|
||||||
|
#include <Logger.h>
|
||||||
|
|
||||||
|
#include "components.h"
|
||||||
|
#include <raylib.h>
|
||||||
|
|
||||||
|
IsoEngine::IsoEngine(int screenWidth, int screenHeight, Network* network)
|
||||||
|
: screenWidth(screenWidth), screenHeight(screenHeight), network(network), sceneManager(registry) {}
|
||||||
|
|
||||||
|
IsoEngine::~IsoEngine() {
|
||||||
|
Shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
void IsoEngine::Initialize() {
|
||||||
|
InitWindow(screenWidth, screenHeight, "IsoEngine Game");
|
||||||
|
SetTargetFPS(60);
|
||||||
|
|
||||||
|
if (network) {
|
||||||
|
network->Initialize();
|
||||||
|
}
|
||||||
|
Logger::GetCoreLogger().AddOutputStream(&std::cout);
|
||||||
|
Logger::GetAppLogger().AddOutputStream(&std::cout);
|
||||||
|
CORE_LOG_INFO("Engine initialized!");
|
||||||
|
}
|
||||||
|
|
||||||
|
void IsoEngine::Run() {
|
||||||
|
while (isRunning && !WindowShouldClose()) {
|
||||||
|
Update();
|
||||||
|
Render();
|
||||||
|
|
||||||
|
if (network) {
|
||||||
|
network->ReceiveData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void IsoEngine::Shutdown() {
|
||||||
|
sceneManager.RenderActiveScene();
|
||||||
|
CloseWindow();
|
||||||
|
|
||||||
|
if (network) {
|
||||||
|
network->Shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
CORE_LOG_INFO("Engine shut down");
|
||||||
|
}
|
||||||
|
|
||||||
|
void IsoEngine::Update() {
|
||||||
|
if (IsKeyPressed(KEY_ESCAPE)) {
|
||||||
|
isRunning = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
sceneManager.UpdateActiveScene(GetFrameTime());
|
||||||
|
sceneManager.UpdateUI(registry);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IsoEngine::Render() {
|
||||||
|
BeginDrawing();
|
||||||
|
ClearBackground(RAYWHITE);
|
||||||
|
|
||||||
|
sceneManager.RenderActiveScene();
|
||||||
|
|
||||||
|
DrawText("IsoEngine Running!", 10, 10, 20, DARKGRAY);
|
||||||
|
sceneManager.RenderUI(registry);
|
||||||
|
DrawFPS(10, 100);
|
||||||
|
EndDrawing();
|
||||||
|
}
|
30
src/IsoEngine.h
Normal file
30
src/IsoEngine.h
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <entt/entt.hpp>
|
||||||
|
#include "network.h"
|
||||||
|
#include "scene_manager.h"
|
||||||
|
|
||||||
|
class IsoEngine {
|
||||||
|
public:
|
||||||
|
IsoEngine(int screenWidth, int screenHeight, Network* network);
|
||||||
|
~IsoEngine();
|
||||||
|
|
||||||
|
void Initialize();
|
||||||
|
void Run();
|
||||||
|
void Shutdown();
|
||||||
|
|
||||||
|
SceneManager& GetSceneManager() { return sceneManager; }
|
||||||
|
|
||||||
|
entt::registry& GetRegistry() { return registry; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
void Update();
|
||||||
|
void Render();
|
||||||
|
|
||||||
|
bool isRunning = true;
|
||||||
|
int screenWidth;
|
||||||
|
int screenHeight;
|
||||||
|
Network* network;
|
||||||
|
entt::registry registry;
|
||||||
|
SceneManager sceneManager;
|
||||||
|
};
|
28
src/IsoEnginePCH.h
Normal file
28
src/IsoEnginePCH.h
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
//
|
||||||
|
// Created by illyum on 9/12/2024.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef ISOENGINEPCH_H
|
||||||
|
#define ISOENGINEPCH_H
|
||||||
|
|
||||||
|
// #ifdef WIN32
|
||||||
|
// #include <Windows.h>
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <sstream>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <iostream>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <functional>
|
||||||
|
#include <fstream>
|
||||||
|
#include <ctime>
|
||||||
|
#include <deque>
|
||||||
|
#include <mutex>
|
||||||
|
#include <format>
|
||||||
|
|
||||||
|
|
||||||
|
#endif //ISOENGINEPCH_H
|
63
src/Logger.cpp
Normal file
63
src/Logger.cpp
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
#include "Logger.h"
|
||||||
|
#include "FatalHandler.h"
|
||||||
|
|
||||||
|
Logger& Logger::GetCoreLogger() {
|
||||||
|
static Logger coreLogger;
|
||||||
|
return coreLogger;
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger& Logger::GetAppLogger() {
|
||||||
|
static Logger appLogger;
|
||||||
|
return appLogger;
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger::Logger() {}
|
||||||
|
|
||||||
|
void Logger::AddOutputStream(std::ostream* stream) {
|
||||||
|
outputStreams.push_back(stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Logger::SetLogLevel(LogLevel level) {
|
||||||
|
logLevel = level;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Logger::Log(LogLevel level, const std::string& message) {
|
||||||
|
if (level >= logLevel) {
|
||||||
|
LogInternal(level, message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Logger::LogInternal(LogLevel level, const std::string& message) {
|
||||||
|
std::string time = GetCurrentTime();
|
||||||
|
std::string levelStr = LevelToString(level);
|
||||||
|
|
||||||
|
for (auto* stream : outputStreams) {
|
||||||
|
*stream << time << " [" << levelStr << "]: " << message << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Logger::GetCurrentTime() {
|
||||||
|
auto now = std::chrono::system_clock::now();
|
||||||
|
auto in_time_t = std::chrono::system_clock::to_time_t(now);
|
||||||
|
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << std::put_time(std::localtime(&in_time_t), "%Y/%m/%d %H:%M:%S");
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Logger::LevelToString(LogLevel level) {
|
||||||
|
switch (level) {
|
||||||
|
case LogLevel::TRACE_l: return "TRACE";
|
||||||
|
case LogLevel::DEBUG_l: return "DEBUG";
|
||||||
|
case LogLevel::INFO_l: return "INFO";
|
||||||
|
case LogLevel::WARN_l: return "WARN";
|
||||||
|
case LogLevel::ERROR_l: return "ERROR";
|
||||||
|
case LogLevel::FATAL_l: return "FATAL";
|
||||||
|
default: return "UNKNOWN";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename... Args>
|
||||||
|
void Logger::FatalHandler(const std::string& format, Args... args) {
|
||||||
|
IsoEngine::FatalHandler(format, args...);
|
||||||
|
}
|
77
src/Logger.h
Normal file
77
src/Logger.h
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <IsoEnginePCH.h>
|
||||||
|
|
||||||
|
enum class LogLevel {
|
||||||
|
TRACE_l,
|
||||||
|
DEBUG_l,
|
||||||
|
INFO_l,
|
||||||
|
WARN_l,
|
||||||
|
ERROR_l,
|
||||||
|
FATAL_l
|
||||||
|
};
|
||||||
|
|
||||||
|
class Logger {
|
||||||
|
public:
|
||||||
|
static Logger& GetCoreLogger();
|
||||||
|
static Logger& GetAppLogger();
|
||||||
|
|
||||||
|
void Log(LogLevel level, const std::string& message);
|
||||||
|
|
||||||
|
template<typename... Args>
|
||||||
|
void LogFormat(LogLevel level, const std::string& format, Args&&... args) {
|
||||||
|
if (level >= logLevel) {
|
||||||
|
std::string formattedMessage = std::vformat(format, std::make_format_args(std::forward<Args>(args)...));
|
||||||
|
LogInternal(level, formattedMessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AddOutputStream(std::ostream* stream);
|
||||||
|
void SetLogLevel(LogLevel level);
|
||||||
|
|
||||||
|
template<typename... Args>
|
||||||
|
static void FatalHandler(const std::string& format, Args... args);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Logger();
|
||||||
|
void LogInternal(LogLevel level, const std::string& message);
|
||||||
|
std::string GetCurrentTime();
|
||||||
|
std::string LevelToString(LogLevel level);
|
||||||
|
|
||||||
|
std::vector<std::ostream*> outputStreams;
|
||||||
|
LogLevel logLevel = LogLevel::TRACE_l;
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef ENABLE_LOGGING
|
||||||
|
|
||||||
|
#define LOG_TRACE(...) Logger::GetAppLogger().LogFormat(LogLevel::TRACE_l, __VA_ARGS__)
|
||||||
|
#define LOG_DEBUG(...) Logger::GetAppLogger().LogFormat(LogLevel::DEBUG_l, __VA_ARGS__)
|
||||||
|
#define LOG_INFO(...) Logger::GetAppLogger().LogFormat(LogLevel::INFO_l, __VA_ARGS__)
|
||||||
|
#define LOG_WARN(...) Logger::GetAppLogger().LogFormat(LogLevel::WARN_l, __VA_ARGS__)
|
||||||
|
#define LOG_ERROR(...) Logger::GetAppLogger().LogFormat(LogLevel::ERROR_l, __VA_ARGS__)
|
||||||
|
#define LOG_FATAL(...) Logger::FatalHandler(__VA_ARGS__)
|
||||||
|
|
||||||
|
#define CORE_LOG_TRACE(...) Logger::GetCoreLogger().LogFormat(LogLevel::TRACE_l, __VA_ARGS__)
|
||||||
|
#define CORE_LOG_DEBUG(...) Logger::GetCoreLogger().LogFormat(LogLevel::DEBUG_l, __VA_ARGS__)
|
||||||
|
#define CORE_LOG_INFO(...) Logger::GetCoreLogger().LogFormat(LogLevel::INFO_l, __VA_ARGS__)
|
||||||
|
#define CORE_LOG_WARN(...) Logger::GetCoreLogger().LogFormat(LogLevel::WARN_l, __VA_ARGS__)
|
||||||
|
#define CORE_LOG_ERROR(...) Logger::GetCoreLogger().LogFormat(LogLevel::ERROR_l, __VA_ARGS__)
|
||||||
|
#define CORE_LOG_FATAL(...) Logger::FatalHandler(__VA_ARGS__)
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define LOG_TRACE(...)
|
||||||
|
#define LOG_DEBUG(...)
|
||||||
|
#define LOG_INFO(...)
|
||||||
|
#define LOG_WARN(...)
|
||||||
|
#define LOG_ERROR(...)
|
||||||
|
#define LOG_FATAL(...) Logger::FatalHandler(__VA_ARGS__)
|
||||||
|
|
||||||
|
#define CORE_LOG_TRACE(...)
|
||||||
|
#define CORE_LOG_DEBUG(...)
|
||||||
|
#define CORE_LOG_INFO(...)
|
||||||
|
#define CORE_LOG_WARN(...)
|
||||||
|
#define CORE_LOG_ERROR(...)
|
||||||
|
#define CORE_LOG_FATAL(...) Logger::FatalHandler(__VA_ARGS__)
|
||||||
|
|
||||||
|
#endif
|
10
src/components.h
Normal file
10
src/components.h
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "components/sprite_component.h"
|
||||||
|
#include "components/scene_component.h"
|
||||||
|
#include "components/transform_component.h"
|
||||||
|
#include "components/health_component.h"
|
||||||
|
#include "components/input_component.h"
|
||||||
|
#include "components/physics_component.h"
|
||||||
|
#include "components/ui_component.h"
|
||||||
|
#include "components/layer_component.h"
|
8
src/components/health_component.h
Normal file
8
src/components/health_component.h
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
struct HealthComponent {
|
||||||
|
int currentHealth;
|
||||||
|
int maxHealth;
|
||||||
|
|
||||||
|
HealthComponent(int max) : maxHealth(max), currentHealth(max) {}
|
||||||
|
};
|
20
src/components/input_component.cpp
Normal file
20
src/components/input_component.cpp
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#include "input_component.h"
|
||||||
|
#include <raylib.h>
|
||||||
|
|
||||||
|
void InputComponent::BindKey(InputAction action, int key) {
|
||||||
|
keyBindings[action] = key;
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputComponent::Update() {
|
||||||
|
for (const auto& [action, key] : keyBindings) {
|
||||||
|
if (IsKeyDown(key)) {
|
||||||
|
if (actionCallbacks.find(action) != actionCallbacks.end()) {
|
||||||
|
actionCallbacks[action]();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputComponent::SetActionCallback(InputAction action, std::function<void()> callback) {
|
||||||
|
actionCallbacks[action] = std::move(callback);
|
||||||
|
}
|
23
src/components/input_component.h
Normal file
23
src/components/input_component.h
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
enum class InputAction {
|
||||||
|
MOVE_UP,
|
||||||
|
MOVE_DOWN,
|
||||||
|
MOVE_LEFT,
|
||||||
|
MOVE_RIGHT,
|
||||||
|
};
|
||||||
|
|
||||||
|
class InputComponent {
|
||||||
|
public:
|
||||||
|
InputComponent() = default;
|
||||||
|
|
||||||
|
void BindKey(InputAction action, int key);
|
||||||
|
|
||||||
|
void Update();
|
||||||
|
|
||||||
|
void SetActionCallback(InputAction action, std::function<void()> callback);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unordered_map<InputAction, int> keyBindings;
|
||||||
|
std::unordered_map<InputAction, std::function<void()>> actionCallbacks;
|
||||||
|
};
|
7
src/components/layer_component.h
Normal file
7
src/components/layer_component.h
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
struct LayerComponent {
|
||||||
|
int layer;
|
||||||
|
|
||||||
|
LayerComponent(int layer = 0) : layer(layer) {}
|
||||||
|
};
|
6
src/components/physics_component.cpp
Normal file
6
src/components/physics_component.cpp
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#include "physics_component.h"
|
||||||
|
|
||||||
|
void PhysicsComponent::Update(float deltaTime) {
|
||||||
|
velocityX += accelerationX * deltaTime;
|
||||||
|
velocityY += accelerationY * deltaTime;
|
||||||
|
}
|
10
src/components/physics_component.h
Normal file
10
src/components/physics_component.h
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
struct PhysicsComponent {
|
||||||
|
float velocityX = 0.0f;
|
||||||
|
float velocityY = 0.0f;
|
||||||
|
float accelerationX = 0.0f;
|
||||||
|
float accelerationY = 0.0f;
|
||||||
|
|
||||||
|
void Update(float deltaTime);
|
||||||
|
};
|
1
src/components/scene_component.cpp
Normal file
1
src/components/scene_component.cpp
Normal file
@ -0,0 +1 @@
|
|||||||
|
#include "scene_component.h"
|
5
src/components/scene_component.h
Normal file
5
src/components/scene_component.h
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
struct SceneComponent {
|
||||||
|
bool isActive;
|
||||||
|
};
|
18
src/components/sprite_component.cpp
Normal file
18
src/components/sprite_component.cpp
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#include "sprite_component.h"
|
||||||
|
#include <raylib.h>
|
||||||
|
|
||||||
|
#include "Logger.h"
|
||||||
|
#include "transform_component.h"
|
||||||
|
|
||||||
|
|
||||||
|
void SpriteComponent::Render(float x, float y) const {
|
||||||
|
if (texture) {
|
||||||
|
DrawTexture(*reinterpret_cast<Texture2D*>(texture), x, y, WHITE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SpriteComponent::Render(TransformComponent transform) const {
|
||||||
|
if (texture) {
|
||||||
|
DrawTexture(*reinterpret_cast<Texture2D*>(texture), transform.x, transform.y, WHITE);
|
||||||
|
}
|
||||||
|
}
|
15
src/components/sprite_component.h
Normal file
15
src/components/sprite_component.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "transform_component.h"
|
||||||
|
|
||||||
|
|
||||||
|
struct SpriteComponent {
|
||||||
|
public:
|
||||||
|
void* texture; // void* to abstract Texture2D
|
||||||
|
void Render(float x, float y) const;
|
||||||
|
void Render(TransformComponent transform) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Usage:
|
||||||
|
// SpriteComponent sprite;
|
||||||
|
// sprite.texture = static_cast<void*>(&your_texture);
|
11
src/components/transform_component.h
Normal file
11
src/components/transform_component.h
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
|
||||||
|
class TransformComponent {
|
||||||
|
public:
|
||||||
|
float x = 0.0f;
|
||||||
|
float y = 0.0f;
|
||||||
|
float scaleX = 1.0f;
|
||||||
|
float scaleY = 1.0f;
|
||||||
|
float rotation = 0.0f;
|
||||||
|
};
|
5
src/components/ui_component.cpp
Normal file
5
src/components/ui_component.cpp
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
//
|
||||||
|
// Created by illyum on 9/12/2024.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "ui_component.h"
|
18
src/components/ui_component.h
Normal file
18
src/components/ui_component.h
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
enum class UIState {
|
||||||
|
NORMAL,
|
||||||
|
HOVERED,
|
||||||
|
CLICKED
|
||||||
|
};
|
||||||
|
|
||||||
|
struct UIComponent {
|
||||||
|
std::string text;
|
||||||
|
float width;
|
||||||
|
float height;
|
||||||
|
std::function<void()> onClick;
|
||||||
|
UIState state = UIState::NORMAL;
|
||||||
|
|
||||||
|
UIComponent(std::string text, float width, float height, std::function<void()> onClick)
|
||||||
|
: text(std::move(text)), width(width), height(height), onClick(std::move(onClick)) {}
|
||||||
|
};
|
64
src/enet_client.cpp
Normal file
64
src/enet_client.cpp
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
#include "network.h"
|
||||||
|
#include <enet.h>
|
||||||
|
#include "Logger.h"
|
||||||
|
|
||||||
|
class ENetClient : public Network {
|
||||||
|
public:
|
||||||
|
ENetClient() : client(nullptr), peer(nullptr) {}
|
||||||
|
|
||||||
|
void Initialize() override {
|
||||||
|
if (enet_initialize() != 0) {
|
||||||
|
CORE_LOG_FATAL("An error occurred while initializing ENet");
|
||||||
|
throw std::runtime_error("An error occurred while initializing ENet");
|
||||||
|
}
|
||||||
|
|
||||||
|
client = enet_host_create(nullptr, 1, 2, 0, 0);
|
||||||
|
if (!client) {
|
||||||
|
CORE_LOG_FATAL("An error occurred while creating the ENet client");
|
||||||
|
throw std::runtime_error("An error occurred while initializing ENet Client");
|
||||||
|
}
|
||||||
|
|
||||||
|
ENetAddress address;
|
||||||
|
enet_address_set_host(&address, "localhost");
|
||||||
|
address.port = 1234;
|
||||||
|
|
||||||
|
peer = enet_host_connect(client, &address, 2, 0);
|
||||||
|
if (!peer) {
|
||||||
|
CORE_LOG_ERROR("No available peers for initiating connection");
|
||||||
|
}
|
||||||
|
|
||||||
|
CORE_LOG_TRACE("ENet client initialized and connected to server");
|
||||||
|
}
|
||||||
|
|
||||||
|
void Shutdown() override {
|
||||||
|
if (peer) {
|
||||||
|
enet_peer_disconnect(peer, 0);
|
||||||
|
CORE_LOG_TRACE("Disconnected from peer");
|
||||||
|
}
|
||||||
|
enet_host_destroy(client);
|
||||||
|
enet_deinitialize();
|
||||||
|
CORE_LOG_TRACE("ENet client shut down");
|
||||||
|
}
|
||||||
|
|
||||||
|
void SendData(const void* data, size_t size) override {
|
||||||
|
if (peer) {
|
||||||
|
ENetPacket* packet = enet_packet_create(data, size, ENET_PACKET_FLAG_RELIABLE);
|
||||||
|
enet_peer_send(peer, 0, packet);
|
||||||
|
CORE_LOG_TRACE("Data sent to server");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReceiveData() override {
|
||||||
|
ENetEvent event;
|
||||||
|
while (enet_host_service(client, &event, 0) > 0) {
|
||||||
|
if (event.type == ENET_EVENT_TYPE_RECEIVE) {
|
||||||
|
CORE_LOG_TRACE("Received packet: {}", std::string(reinterpret_cast<const char*>(event.packet->data)));
|
||||||
|
enet_packet_destroy(event.packet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
ENetHost* client;
|
||||||
|
ENetPeer* peer;
|
||||||
|
};
|
48
src/enet_server.cpp
Normal file
48
src/enet_server.cpp
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
#include "network.h"
|
||||||
|
#include <enet.h>
|
||||||
|
|
||||||
|
|
||||||
|
class ENetServer : public Network {
|
||||||
|
public:
|
||||||
|
ENetServer() : server(nullptr) {}
|
||||||
|
|
||||||
|
void Initialize() override {
|
||||||
|
if (enet_initialize() != 0) {
|
||||||
|
std::cerr << "An error occurred while initializing ENet.\n";
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
ENetAddress address;
|
||||||
|
address.host = ENET_HOST_ANY;
|
||||||
|
address.port = 1234;
|
||||||
|
|
||||||
|
server = enet_host_create(&address, 32, 2, 0, 0);
|
||||||
|
if (!server) {
|
||||||
|
std::cerr << "An error occurred while trying to create the server.\n";
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Shutdown() override {
|
||||||
|
enet_host_destroy(server);
|
||||||
|
enet_deinitialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SendData(const void* data, size_t size) override {
|
||||||
|
ENetPacket* packet = enet_packet_create(data, size, ENET_PACKET_FLAG_RELIABLE);
|
||||||
|
enet_host_broadcast(server, 0, packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReceiveData() override {
|
||||||
|
ENetEvent event;
|
||||||
|
while (enet_host_service(server, &event, 0) > 0) {
|
||||||
|
if (event.type == ENET_EVENT_TYPE_RECEIVE) {
|
||||||
|
std::cout << "Received packet from client: " << event.packet->data << "\n";
|
||||||
|
enet_packet_destroy(event.packet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
ENetHost* server;
|
||||||
|
};
|
193
src/filepacker.cpp
Normal file
193
src/filepacker.cpp
Normal file
@ -0,0 +1,193 @@
|
|||||||
|
//
|
||||||
|
// Created by illyum on 9/13/2024.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "filepacker.h"
|
||||||
|
|
||||||
|
#include "Logger.h"
|
||||||
|
|
||||||
|
bool FilePacker::Pack(const std::string &directoryPath, const std::string &outputBapFile) {
|
||||||
|
BapHeader header;
|
||||||
|
std::ofstream outputFile(outputBapFile, std::ios::binary);
|
||||||
|
|
||||||
|
if (!outputFile) {
|
||||||
|
CORE_LOG_ERROR("Failed to open output file");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::memcpy(header.magic, static_cast<const char*>("BAP"), 3);
|
||||||
|
header.version = PACKER_VERSION;
|
||||||
|
header.fileCount = 0;
|
||||||
|
|
||||||
|
std::vector<std::pair<FileEntry, std::vector<char>>> filesData;
|
||||||
|
size_t headerSize = 3 + sizeof(header.version) + sizeof(header.fileCount);
|
||||||
|
|
||||||
|
for (const auto& entry : std::filesystem::directory_iterator(directoryPath)) {
|
||||||
|
if (entry.is_regular_file()) {
|
||||||
|
FileEntry fileEntry;
|
||||||
|
fileEntry.filePath = entry.path().string();
|
||||||
|
|
||||||
|
// TODO: Implement filetype detection
|
||||||
|
fileEntry.fileType = RAWBINARY;
|
||||||
|
fileEntry.compressedSize = COMPRESSION_NONE;
|
||||||
|
|
||||||
|
std::ifstream inputFile(entry.path(), std::ios::binary | std::ios::ate);
|
||||||
|
if (!inputFile) {
|
||||||
|
CORE_LOG_ERROR("FilePacker::Pack(): Failed to open file for packing: {}", entry.path().string());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
fileEntry.dataSize = inputFile.tellg();
|
||||||
|
inputFile.seekg(0, std::ios::beg);
|
||||||
|
std::vector<char> fileData(fileEntry.dataSize);
|
||||||
|
inputFile.read(fileData.data(), fileEntry.dataSize);
|
||||||
|
inputFile.close();
|
||||||
|
|
||||||
|
// TODO: Implement data compression
|
||||||
|
std::vector<char> compressedData = CompressData(fileData, fileEntry.compression);
|
||||||
|
fileEntry.compressedSize = compressedData.size();
|
||||||
|
|
||||||
|
filesData.emplace_back(fileEntry, std::move(compressedData));
|
||||||
|
size_t pathLength = fileEntry.filePath.size();
|
||||||
|
size_t metadataLength = fileEntry.metadata.size();
|
||||||
|
|
||||||
|
headerSize += sizeof(pathLength) + pathLength + sizeof(fileEntry.fileType) + sizeof(fileEntry.compression)
|
||||||
|
+ sizeof(fileEntry.dataSize) + sizeof(fileEntry.compressedSize) + sizeof(fileEntry.dataOffset)
|
||||||
|
+ sizeof(metadataLength) + metadataLength;
|
||||||
|
|
||||||
|
header.fileEntries.push_back(fileEntry);
|
||||||
|
header.fileCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
outputFile.seekp(headerSize, std::ios::beg);
|
||||||
|
for (size_t i = 0; i < filesData.size(); ++i) {
|
||||||
|
auto& fileEntry = header.fileEntries[i];
|
||||||
|
const auto& compressedData = filesData[i].second;
|
||||||
|
fileEntry.dataOffset = outputFile.tellp();
|
||||||
|
outputFile.write(compressedData.data(), compressedData.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
outputFile.seekp(0, std::ios::beg);
|
||||||
|
WriteHeader(outputFile, header);
|
||||||
|
outputFile.close();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<FileEntry> FilePacker::listFiles(const std::string& bapFile) {
|
||||||
|
std::ifstream inputFile(bapFile, std::ios::binary);
|
||||||
|
if (!inputFile) {
|
||||||
|
CORE_LOG_FATAL("Failed to open .bap file for listing: {}", bapFile);
|
||||||
|
throw std::runtime_error("File could not be opened");
|
||||||
|
}
|
||||||
|
|
||||||
|
BapHeader header = ReadHeader(inputFile);
|
||||||
|
inputFile.close();
|
||||||
|
return header.fileEntries;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FilePacker::ExtractFile(const std::string& bapFile, const std::string& fileName, const std::string& outputPath) {
|
||||||
|
std::ifstream inputFile(bapFile, std::ios::binary);
|
||||||
|
if (!inputFile) {
|
||||||
|
CORE_LOG_ERROR("Failed to open .bap file for extraction: {}", bapFile);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
BapHeader header = ReadHeader(inputFile);
|
||||||
|
for (const auto& fileEntry : header.fileEntries) {
|
||||||
|
if (fileEntry.filePath == fileName) {
|
||||||
|
std::ofstream outFile(outputPath, std::ios::binary);
|
||||||
|
if (!outFile) {
|
||||||
|
CORE_LOG_ERROR("Failed to create output file: {}", outputPath);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<char> compressedData(fileEntry.compressedSize);
|
||||||
|
inputFile.seekg(fileEntry.dataOffset, std::ios::beg);
|
||||||
|
inputFile.read(compressedData.data(), compressedData.size());
|
||||||
|
std::vector<char> decompressedData = DecompressData(compressedData, fileEntry.compression);
|
||||||
|
outFile.write(decompressedData.data(), decompressedData.size());
|
||||||
|
outFile.close();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CORE_LOG_ERROR("File not found in .bap archive: {}", fileName);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FilePacker::WriteHeader(std::ofstream& outFile, const BapHeader& header) {
|
||||||
|
outFile.write(header.magic, 3);
|
||||||
|
outFile.write(reinterpret_cast<const char*>(&header.version), sizeof(header.version));
|
||||||
|
outFile.write(reinterpret_cast<const char*>(&header.fileCount), sizeof(header.fileCount));
|
||||||
|
|
||||||
|
for (const auto& fileEntry : header.fileEntries) {
|
||||||
|
size_t pathLength = fileEntry.filePath.size();
|
||||||
|
outFile.write(reinterpret_cast<const char*>(&pathLength), sizeof(pathLength));
|
||||||
|
outFile.write(fileEntry.filePath.c_str(), pathLength);
|
||||||
|
outFile.write(reinterpret_cast<const char*>(&fileEntry.fileType), sizeof(fileEntry.fileType));
|
||||||
|
outFile.write(reinterpret_cast<const char*>(&fileEntry.compression), sizeof(fileEntry.compression));
|
||||||
|
outFile.write(reinterpret_cast<const char*>(&fileEntry.dataSize), sizeof(fileEntry.dataSize));
|
||||||
|
outFile.write(reinterpret_cast<const char*>(&fileEntry.compressedSize), sizeof(fileEntry.compressedSize));
|
||||||
|
outFile.write(reinterpret_cast<const char*>(&fileEntry.dataOffset), sizeof(fileEntry.dataOffset));
|
||||||
|
|
||||||
|
size_t metadataLength = fileEntry.metadata.size();
|
||||||
|
outFile.write(reinterpret_cast<const char*>(&metadataLength), sizeof(metadataLength));
|
||||||
|
outFile.write(fileEntry.metadata.c_str(), metadataLength);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BapHeader FilePacker::ReadHeader(std::ifstream& inFile) {
|
||||||
|
BapHeader header;
|
||||||
|
|
||||||
|
inFile.read(header.magic, 3);
|
||||||
|
inFile.read(reinterpret_cast<char*>(&header.version), sizeof(header.version));
|
||||||
|
inFile.read(reinterpret_cast<char*>(&header.fileCount), sizeof(header.fileCount));
|
||||||
|
|
||||||
|
if (header.version != PACKER_VERSION) {
|
||||||
|
CORE_LOG_FATAL("FilePacker::ReadHeader(): Wrong .bap file version.");
|
||||||
|
throw std::runtime_error("Invalid bap file version");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < header.fileCount; ++i) {
|
||||||
|
FileEntry fileEntry;
|
||||||
|
|
||||||
|
size_t pathLength;
|
||||||
|
inFile.read(reinterpret_cast<char*>(&pathLength), sizeof(pathLength));
|
||||||
|
|
||||||
|
fileEntry.filePath.resize(pathLength);
|
||||||
|
inFile.read(fileEntry.filePath.data(), pathLength);
|
||||||
|
|
||||||
|
inFile.read(reinterpret_cast<char*>(&fileEntry.fileType), sizeof(fileEntry.fileType));
|
||||||
|
inFile.read(reinterpret_cast<char*>(&fileEntry.compression), sizeof(fileEntry.compression));
|
||||||
|
inFile.read(reinterpret_cast<char*>(&fileEntry.dataSize), sizeof(fileEntry.dataSize));
|
||||||
|
inFile.read(reinterpret_cast<char*>(&fileEntry.compressedSize), sizeof(fileEntry.compressedSize));
|
||||||
|
inFile.read(reinterpret_cast<char*>(&fileEntry.dataOffset), sizeof(fileEntry.dataOffset));
|
||||||
|
|
||||||
|
size_t metadataLength;
|
||||||
|
inFile.read(reinterpret_cast<char*>(&metadataLength), sizeof(metadataLength));
|
||||||
|
|
||||||
|
fileEntry.metadata.resize(metadataLength);
|
||||||
|
inFile.read(fileEntry.metadata.data(), metadataLength);
|
||||||
|
|
||||||
|
header.fileEntries.push_back(fileEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
return header;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<char> FilePacker::CompressData(const std::vector<char>& input, CompressionType compression) {
|
||||||
|
// IMPL: Implement actual compression on a per file basis
|
||||||
|
if (compression == COMPRESSION_NONE) {
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<char> FilePacker::DecompressData(const std::vector<char>& input, CompressionType compression) {
|
||||||
|
// IMPL: Implement decompression on a per file basis
|
||||||
|
if (compression == COMPRESSION_NONE) {
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
|
||||||
|
return input;
|
||||||
|
}
|
55
src/filepacker.h
Normal file
55
src/filepacker.h
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
//
|
||||||
|
// Created by illyum on 9/13/2024.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef FILEPACKER_H
|
||||||
|
#define FILEPACKER_H
|
||||||
|
|
||||||
|
#include <IsoEnginePCH.h>
|
||||||
|
|
||||||
|
#define BAP_MAGIC "BAP"
|
||||||
|
#define PACKER_VERSION 1
|
||||||
|
|
||||||
|
enum CompressionType {
|
||||||
|
COMPRESSION_NONE,
|
||||||
|
COMPRESSION_LZMA
|
||||||
|
};
|
||||||
|
|
||||||
|
enum FileType {
|
||||||
|
PNG,
|
||||||
|
RAWTEXT,
|
||||||
|
RAWBINARY
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FileEntry {
|
||||||
|
std::string filePath;
|
||||||
|
FileType fileType;
|
||||||
|
CompressionType compression;
|
||||||
|
size_t dataSize;
|
||||||
|
size_t compressedSize;
|
||||||
|
std::string metadata;
|
||||||
|
size_t dataOffset;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BapHeader {
|
||||||
|
char magic[3];
|
||||||
|
int version;
|
||||||
|
int fileCount;
|
||||||
|
std::vector<FileEntry> fileEntries;
|
||||||
|
};
|
||||||
|
|
||||||
|
class FilePacker {
|
||||||
|
public:
|
||||||
|
bool Pack(const std::string& directoryPath, const std::string& outputBapFile);
|
||||||
|
bool Unpack(const std::string& bapFile, const std::string& outputDirectory);
|
||||||
|
std::vector<FileEntry> listFiles(const std::string& bapFile);
|
||||||
|
bool ExtractFile(const std::string& bapFile, const std::string& fileName, const std::string& outputPath);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void WriteHeader(std::ofstream& outFile, const BapHeader& header);
|
||||||
|
BapHeader ReadHeader(std::ifstream& inFile);
|
||||||
|
std::vector<char> CompressData(const std::vector<char>& input, CompressionType compression);
|
||||||
|
std::vector<char> DecompressData(const std::vector<char>& input, CompressionType compression);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //FILEPACKER_H
|
14
src/network.h
Normal file
14
src/network.h
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define SERVER_PORT 6771
|
||||||
|
#define SERVER_ADDRESS "127.0.0.1"
|
||||||
|
|
||||||
|
class Network {
|
||||||
|
public:
|
||||||
|
virtual void Initialize() = 0;
|
||||||
|
virtual void Shutdown() = 0;
|
||||||
|
virtual void SendData(const void* data, size_t size) = 0;
|
||||||
|
virtual void ReceiveData() = 0;
|
||||||
|
|
||||||
|
virtual ~Network() = default;
|
||||||
|
};
|
38
src/platform/posix/FatalHandlerPosix.cpp
Normal file
38
src/platform/posix/FatalHandlerPosix.cpp
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
//
|
||||||
|
// Created by illyum on 9/13/2024.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "FatalHandler.h"
|
||||||
|
#include <execinfo.h>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
|
#include <format>
|
||||||
|
|
||||||
|
namespace IsoEngine {
|
||||||
|
|
||||||
|
template<typename... Args>
|
||||||
|
void FatalHandler(const std::string& format, Args... args) {
|
||||||
|
std::ostringstream stream;
|
||||||
|
stream << std::format(format, args...);
|
||||||
|
|
||||||
|
// TODO: change the name of the file to reflect the time the crash happened
|
||||||
|
std::ofstream crashFile("crash.log", std::ios::app);
|
||||||
|
crashFile << "FATAL ERROR: " << stream.str() << std::endl;
|
||||||
|
|
||||||
|
void* callstack[128];
|
||||||
|
int frames = backtrace(callstack, 128);
|
||||||
|
char** symbols = backtrace_symbols(callstack, frames);
|
||||||
|
|
||||||
|
crashFile << "Stack trace:\n";
|
||||||
|
for (int i = 0; i < frames; ++i) {
|
||||||
|
crashFile << symbols[i] << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(symbols);
|
||||||
|
crashFile.close();
|
||||||
|
|
||||||
|
std::abort();
|
||||||
|
}
|
||||||
|
}
|
64
src/platform/windows/FatalHandlerWindows.cpp
Normal file
64
src/platform/windows/FatalHandlerWindows.cpp
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
//
|
||||||
|
// Created by illyum on 9/13/2024.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "FatalHandler.h"
|
||||||
|
#include <windows.h>
|
||||||
|
#include <dbghelp.h>
|
||||||
|
#include <fstream>
|
||||||
|
#include <sstream>
|
||||||
|
#include <format>
|
||||||
|
|
||||||
|
#pragma comment(lib, "dbghelp.lib")
|
||||||
|
|
||||||
|
namespace IsoEngine {
|
||||||
|
template<typename... Args>
|
||||||
|
void FatalHandler(const std::string &format, Args... args) {
|
||||||
|
std::ostringstream stream;
|
||||||
|
stream << std::format(format, args...);
|
||||||
|
|
||||||
|
// TODO: change the name of the file to reflect the time the crash happened
|
||||||
|
std::ofstream crashFile("crash.log", std::ios::app);
|
||||||
|
crashFile << "FATAL ERROR: " << stream.str() << std::endl;
|
||||||
|
|
||||||
|
HANDLE process = GetCurrentProcess();
|
||||||
|
SymInitialize(process, NULL, TRUE);
|
||||||
|
|
||||||
|
CONTEXT context;
|
||||||
|
RtlCaptureContext(&context);
|
||||||
|
|
||||||
|
STACKFRAME64 stackFrame = {};
|
||||||
|
stackFrame.AddrPC.Offset = context.Rip;
|
||||||
|
stackFrame.AddrPC.Mode = AddrModeFlat;
|
||||||
|
stackFrame.AddrFrame.Offset = context.Rbp;
|
||||||
|
stackFrame.AddrFrame.Mode = AddrModeFlat;
|
||||||
|
stackFrame.AddrStack.Offset = context.Rsp;
|
||||||
|
stackFrame.AddrStack.Mode = AddrModeFlat;
|
||||||
|
|
||||||
|
crashFile << "Stack trace:\n";
|
||||||
|
while (StackWalk64(IMAGE_FILE_MACHINE_AMD64, process, GetCurrentThread(), &stackFrame, &context, NULL,
|
||||||
|
SymFunctionTableAccess64, SymGetModuleBase64, NULL)) {
|
||||||
|
DWORD64 address = stackFrame.AddrPC.Offset;
|
||||||
|
if (address == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)];
|
||||||
|
PSYMBOL_INFO symbol = (PSYMBOL_INFO) buffer;
|
||||||
|
symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
|
||||||
|
symbol->MaxNameLen = MAX_SYM_NAME;
|
||||||
|
|
||||||
|
DWORD64 displacement = 0;
|
||||||
|
if (SymFromAddr(process, address, &displacement, symbol)) {
|
||||||
|
crashFile << symbol->Name << " - 0x" << std::hex << symbol->Address << std::dec << "\n";
|
||||||
|
} else {
|
||||||
|
crashFile << "Unresolved symbol at address: 0x" << std::hex << address << std::dec << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SymCleanup(process);
|
||||||
|
crashFile.close();
|
||||||
|
|
||||||
|
std::abort();
|
||||||
|
}
|
||||||
|
}
|
110
src/scene_manager.cpp
Normal file
110
src/scene_manager.cpp
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
#include "scene_manager.h"
|
||||||
|
|
||||||
|
#include "Logger.h"
|
||||||
|
#include "raylib.h"
|
||||||
|
|
||||||
|
SceneManager::SceneManager(entt::registry& registry) : registry(registry), activeScene(entt::null) {}
|
||||||
|
|
||||||
|
void SceneManager::SetActiveScene(entt::entity scene) {
|
||||||
|
if (activeScene != entt::null) {
|
||||||
|
auto& currentScene = registry.get<SceneComponent>(activeScene);
|
||||||
|
currentScene.isActive = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
activeScene = scene;
|
||||||
|
auto& newScene = registry.get<SceneComponent>(activeScene);
|
||||||
|
newScene.isActive = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
entt::entity SceneManager::CreateScene() {
|
||||||
|
entt::entity scene = registry.create();
|
||||||
|
registry.emplace<SceneComponent>(scene, false);
|
||||||
|
return scene;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SceneManager::UpdateActiveScene(float delta) {
|
||||||
|
if (activeScene != entt::null) {
|
||||||
|
// Iterate over entities in the active scene that have an InputComponent
|
||||||
|
auto view = registry.view<InputComponent>();
|
||||||
|
for (auto entity : view) {
|
||||||
|
auto& inputComponent = view.get<InputComponent>(entity);
|
||||||
|
inputComponent.Update(); // This will call the input logic
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SceneManager::RenderActiveScene() {
|
||||||
|
if (activeScene != entt::null) {
|
||||||
|
// Create a multimap to store entities sorted by layer
|
||||||
|
std::multimap<int, entt::entity> layeredEntities;
|
||||||
|
|
||||||
|
// Gather all entities with a LayerComponent
|
||||||
|
auto view = registry.view<LayerComponent, SpriteComponent, TransformComponent>();
|
||||||
|
for (auto entity : view) {
|
||||||
|
auto& layer = view.get<LayerComponent>(entity);
|
||||||
|
layeredEntities.insert({ layer.layer, entity });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Render all entities sorted by layer
|
||||||
|
for (auto& pair : layeredEntities) {
|
||||||
|
auto entity = pair.second;
|
||||||
|
auto& sprite = registry.get<SpriteComponent>(entity);
|
||||||
|
auto& transform = registry.get<TransformComponent>(entity);
|
||||||
|
|
||||||
|
// Render the sprite at the position defined by the TransformComponent
|
||||||
|
sprite.Render(transform);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SceneManager::UpdateUI(entt::registry& registry) {
|
||||||
|
Vector2 mousePosition = GetMousePosition(); // This assumes a raylib-like GetMousePosition, adapt as needed for your system
|
||||||
|
|
||||||
|
auto view = registry.view<UIComponent, TransformComponent>();
|
||||||
|
for (auto entity : view) {
|
||||||
|
auto& ui = view.get<UIComponent>(entity);
|
||||||
|
auto& transform = view.get<TransformComponent>(entity);
|
||||||
|
|
||||||
|
// Check if the mouse is over the button
|
||||||
|
bool isHovered = (mousePosition.x > transform.x && mousePosition.x < transform.x + ui.width &&
|
||||||
|
mousePosition.y > transform.y && mousePosition.y < transform.y + ui.height);
|
||||||
|
|
||||||
|
if (isHovered) {
|
||||||
|
ui.state = IsMouseButtonPressed(MOUSE_LEFT_BUTTON) ? UIState::CLICKED : UIState::HOVERED;
|
||||||
|
|
||||||
|
// If clicked, call the onClick function
|
||||||
|
if (ui.state == UIState::CLICKED && ui.onClick) {
|
||||||
|
ui.onClick();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ui.state = UIState::NORMAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SceneManager::RenderUI(entt::registry& registry) {
|
||||||
|
auto view = registry.view<UIComponent, TransformComponent>();
|
||||||
|
|
||||||
|
for (auto entity : view) {
|
||||||
|
auto& ui = view.get<UIComponent>(entity);
|
||||||
|
auto& transform = view.get<TransformComponent>(entity);
|
||||||
|
|
||||||
|
// Render the button background
|
||||||
|
Color buttonColor = DARKGRAY;
|
||||||
|
if (ui.state == UIState::HOVERED) {
|
||||||
|
buttonColor = LIGHTGRAY;
|
||||||
|
} else if (ui.state == UIState::CLICKED) {
|
||||||
|
buttonColor = GRAY;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use the raw transform position (no adjustment to center screen)
|
||||||
|
DrawRectangle(transform.x, transform.y, ui.width, ui.height, buttonColor);
|
||||||
|
|
||||||
|
// Render the button text (centered within the button)
|
||||||
|
int textWidth = MeasureText(ui.text.c_str(), 20);
|
||||||
|
int textX = transform.x + (ui.width / 2) - (textWidth / 2);
|
||||||
|
int textY = transform.y + (ui.height / 2) - 10; // Slight vertical adjustment
|
||||||
|
|
||||||
|
DrawText(ui.text.c_str(), textX, textY, 20, BLACK);
|
||||||
|
}
|
||||||
|
}
|
20
src/scene_manager.h
Normal file
20
src/scene_manager.h
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <entt/entt.hpp>
|
||||||
|
#include <components.h>
|
||||||
|
|
||||||
|
class SceneManager {
|
||||||
|
public:
|
||||||
|
SceneManager(entt::registry& registry);
|
||||||
|
|
||||||
|
void SetActiveScene(entt::entity scene);
|
||||||
|
entt::entity CreateScene();
|
||||||
|
void UpdateActiveScene(float delta);
|
||||||
|
void RenderActiveScene();
|
||||||
|
void UpdateUI(entt::registry& registry);
|
||||||
|
void RenderUI(entt::registry& registry);
|
||||||
|
|
||||||
|
private:
|
||||||
|
entt::registry& registry;
|
||||||
|
entt::entity activeScene;
|
||||||
|
};
|
6102
vendor/enet/enet.h
vendored
Normal file
6102
vendor/enet/enet.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user