Test font pas fini

This commit is contained in:
Tom Ray
2026-06-21 21:53:01 +02:00
parent 9f4740e20f
commit ab43ad1604
54 changed files with 2040 additions and 573 deletions
+70 -281
View File
@@ -1,8 +1,7 @@
# Nous voulons un cmake "récent" pour utiliser les dernières fonctionnalités. # Nous voulons un cmake "récent" pour utiliser les dernières fonctionnalités.
cmake_minimum_required(VERSION 3.20) cmake_minimum_required(VERSION 3.20)
set (CMAKE_CXX_STANDARD 23) set (CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_COMPILER clang++) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-exceptions")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti -fno-exceptions")
# Nom du projet. # Nom du projet.
set(PROJECT CosmicEngine) set(PROJECT CosmicEngine)
project(${PROJECT}) project(${PROJECT})
@@ -42,15 +41,6 @@ endif()
# ---------- Inclusion des packages sous linux ----------- # ---------- Inclusion des packages sous linux -----------
if(UNIX) if(UNIX)
# --------- Inclusion d'OpenGL ----------
# OpenGL Lib pour charger OpenGL, fournit avec les drivers, donc se trouve toute seul.
# find_package(OpenGL REQUIRED)
# if(OPENGL_FOUND)
# message("lib OpenGL Trouvé")
# else()
# message("lib OpenGL Introuvable")
# endif()
# ---------------------------------------
# ---------- Inclusion de GLM ----------- # ---------- Inclusion de GLM -----------
# GLM Lib pour mathématique, en mode header only. # GLM Lib pour mathématique, en mode header only.
@@ -86,129 +76,6 @@ if(UNIX)
message("lib EnTTlib Introuvable") message("lib EnTTlib Introuvable")
endif() endif()
# --------- Inclusion de Boost ----------
# Boost Lib pour diverse simplification
# set(Boost_USE_STATIC_LIBS OFF)
# set(Boost_USE_MULTITHREADED ON)
# set(Boost_USE_STATIC_RUNTIME OFF)
# find_package(Boost REQUIRED COMPONENTS log_setup log filesystem chrono thread date_time regex) # header only libraries must not be added here
# message(STATUS "Boost version: ${Boost_VERSION}")
# if(NOT TARGET Boost::filesystem)
# add_library(Boost::filesystem IMPORTED INTERFACE)
# set_property(TARGET Boost::filesystem PROPERTY
# INTERFACE_INCLUDE_DIRECTORIES ${Boost_INCLUDE_DIR})
# set_property(TARGET Boost::filesystem PROPERTY
# INTERFACE_LINK_LIBRARIES ${Boost_LIBRARIES})
# endif()
# if(NOT TARGET Boost::thread)
# add_library(Boost::thread IMPORTED INTERFACE)
# set_property(TARGET Boost::thread PROPERTY
# INTERFACE_INCLUDE_DIRECTORIES ${Boost_INCLUDE_DIR})
# set_property(TARGET Boost::thread PROPERTY
# INTERFACE_LINK_LIBRARIES ${Boost_LIBRARIES})
# endif()
# if(NOT TARGET Boost::chrono)
# add_library(Boost::chrono IMPORTED INTERFACE)
# set_property(TARGET Boost::chrono PROPERTY
# INTERFACE_INCLUDE_DIRECTORIES ${Boost_INCLUDE_DIR})
# set_property(TARGET Boost::chrono PROPERTY
# INTERFACE_LINK_LIBRARIES ${Boost_LIBRARIES})
# endif()
# if(NOT TARGET Boost::date_time)
# add_library(Boost::date_time IMPORTED INTERFACE)
# set_property(TARGET Boost::date_time PROPERTY
# INTERFACE_INCLUDE_DIRECTORIES ${Boost_INCLUDE_DIR})
# set_property(TARGET Boost::date_time PROPERTY
# INTERFACE_LINK_LIBRARIES ${Boost_LIBRARIES})
# endif()
# if(NOT TARGET Boost::regex)
# add_library(Boost::regex IMPORTED INTERFACE)
# set_property(TARGET Boost::regex PROPERTY
# INTERFACE_INCLUDE_DIRECTORIES ${Boost_INCLUDE_DIR})
# set_property(TARGET Boost::regex PROPERTY
# INTERFACE_LINK_LIBRARIES ${Boost_LIBRARIES})
# endif()
# if(NOT TARGET Boost::log)
# add_library(Boost::log IMPORTED INTERFACE)
# set_property(TARGET Boost::log PROPERTY
# INTERFACE_INCLUDE_DIRECTORIES ${Boost_INCLUDE_DIR})
# set_property(TARGET Boost::log PROPERTY
# INTERFACE_LINK_LIBRARIES ${Boost_LIBRARIES})
# endif()
# if(NOT TARGET Boost::log_setup)
# add_library(Boost::log_setup IMPORTED INTERFACE)
# set_property(TARGET Boost::log_setup PROPERTY
# INTERFACE_INCLUDE_DIRECTORIES ${Boost_INCLUDE_DIR})
# set_property(TARGET Boost::log_setup PROPERTY
# INTERFACE_LINK_LIBRARIES ${Boost_LIBRARIES})
# endif()
# if(Boost_FOUND)
# message("lib Boost Trouvé")
# else()
# message("lib Boost Introuvable")
# endif()
# ---------------------------------------
# -------- Inclusion de la SDL2 ----------
# SDL2 Lib pour fenetre et contrôle
# Les autre plateforme (Linux...) ont un installateur de paquet, la lib se trouve toute seul.
# find_package(SDL2 REQUIRED)
# if(SDL2_FOUND)
# message("lib SDL2 Trouvé")
# else()
# message("lib SDL2 Introuvable")
# endif()
# ---------------------------------------
# ------- Inclusion de SDL2_IMAGE --------
# SDL2_IMAGE Lib pour charger une image
# Les autre plateforme (Linux...) ont un installateur de paquet, la lib se trouve toute seul.
# find_package(SDL2_image QUIET)
# #find_library(SDL2_image libSDL2_image)
# if(SDL2_image_FOUND)
# message("lib SDL2_IMAGE Trouvé")
# else()
# message("lib SDL2_IMAGE Introuvable")
# endif()
# ---------------------------------------
# ------- Inclusion de SDL2_TTF --------
# SDL2_IMAGE Lib pour charger une police d'écriture.
# set(SDL2_ttf_DIR ./lib/CMake/Linux)
# # Les autre plateforme (Linux...) ont un installateur de paquet, la lib se trouve toute seul.
# find_package(SDL2_ttf QUIET)
# #find_library(SDL2_ttf libSDL2_ttf)
# if(SDL2_ttf_FOUND)
# message("lib SDL2_TTF Trouvé")
# else()
# message("lib SDL2_TTF Introuvable")
# endif()
# ---------------------------------------
# --------- Inclusion de GLEW -----------
# GLEW Lib pour charger utiliser OpenGL + extension
# Les autre plateforme (Linux...) ont un installateur de paquet, la lib se trouve toute seul.
# find_package(GLEW REQUIRED)
# if(GLEW_FOUND)
# message("lib GLEW Trouvé")
# else()
# message("lib GLEW Introuvable")
# endif()
# ---------------------------------------
# ---------- Inclusion de ASSIMP ----------- # ---------- Inclusion de ASSIMP -----------
# Assimp Lib import modèles 3D. # Assimp Lib import modèles 3D.
find_package(assimp REQUIRED) find_package(assimp REQUIRED)
@@ -219,31 +86,6 @@ if(UNIX)
endif() endif()
# --------------------------------------- # ---------------------------------------
# ---------- Inclusion de ODE -----------
# ODE Lib Moteur physique.
# set(ODE_DIR ./lib/CMake/Linux)
# # Les autre plateforme (Linux...) ont un installateur de paquet, la lib se trouve toute seul.
# find_package(ODE REQUIRED)
# if(ODE_FOUND)
# message("lib ODE Trouvé")
# else()
# message("lib ODE Introuvable")
# endif()
# ---------------------------------------
# --------- Inclusion de SNDFILE ----------
# SNDFILE Lib pour inclure le son.
# Les autre plateforme (Linux...) ont un installateur de paquet, la lib se trouve toute seul.
#set(SNDFILE_DIR ./lib/CMake/Linux)
# find_package(sndfile QUIET)#TODO corrige
# #find_library(sndfile libsndfile)
# if(sndfile_FOUND)
# message("lib SNDFILE Trouvé")
# else()
# message("lib SNDFILE Introuvable")
# endif()
# ---------------------------------------
# ---------- Inclusion de OpenAL----------- # ---------- Inclusion de OpenAL-----------
# OpenAL Lib gérer le son. # OpenAL Lib gérer le son.
# Les autre plateforme (Linux...) ont un installateur de paquet, la lib se trouve toute seul. # Les autre plateforme (Linux...) ont un installateur de paquet, la lib se trouve toute seul.
@@ -329,22 +171,6 @@ endif()
endif() endif()
# --------------------------------------- # ---------------------------------------
# ------- Inclusion de Spirv-cross --------
#Spirv-cross pour metadonnees shader spirv
# set(spirv_cross_core_DIR ./lib/CMake/Linux/spirv-crossConf)
# set(spirv_cross_glsl_DIR ./lib/CMake/Linux/spirv-crossConf)
# Les autre plateforme (Linux...) ont un installateur de paquet, la lib se trouve toute seul.
# find_package(spirv_cross_core QUIET)
# find_package(spirv_cross_glsl QUIET)
#find_library(SDL2_ttf libSDL2_ttf)
# if(spirv_cross_core_FOUND AND spirv_cross_glsl_FOUND)
# message("lib spirv_cross Trouvé")
# else()
# message("lib spirv_cross Introuvable")
# endif()
# ---------------------------------------
# ------- Inclusion de Spirv-cross -------- # ------- Inclusion de Spirv-cross --------
#Spirv-cross pour metadonnees shader spirv #Spirv-cross pour metadonnees shader spirv
set(spirvreflectlib_DIR ./lib/CMake/Linux/) set(spirvreflectlib_DIR ./lib/CMake/Linux/)
@@ -401,6 +227,20 @@ else()
endif() endif()
# --------------------------------------- # ---------------------------------------
# ------- Inclusion de MSDFATLASGEN --------
# Pour les font
set(MsdfAtlasGen_DIR ./lib/CMake/Linux)
find_package(MsdfAtlasGen REQUIRED)
if(MsdfAtlasGen_FOUND)
message("lib MsdfAtlasGen Trouvé")
else()
message("lib MsdfAtlasGen Introuvable")
endif()
# ---------------------------------------
endif() endif()
@@ -447,6 +287,22 @@ target_include_directories(Engine
${CMAKE_CURRENT_SOURCE_DIR}/src/Engine ${CMAKE_CURRENT_SOURCE_DIR}/src/Engine
) )
add_library(EngineHeaders INTERFACE)
target_include_directories(EngineHeaders INTERFACE
${CMAKE_CURRENT_SOURCE_DIR}/src/Engine
${GLM_INCLUDE_DIRS}
${JSONFMCPP_INCLUDE_DIRS}
${ENTT_INCLUDE_DIRS}
${JOLT_INCLUDE_DIRS}
${VMA_INCLUDE_DIRS}
${DRLIBS_INCLUDE_DIRS}
${MSDFATLASGEN_INCLUDE_DIRS}
${OPENAL_INCLUDE_DIR}
${SPIRV_REFLECT_INCLUDE_DIRS}
${ASSIMP_INCLUDE_DIRS}
${JSONVALIDATOR_INCLUDE_DIRS}
)
add_library(ScriptModule SHARED ${SRCS_SCRIPTS}) add_library(ScriptModule SHARED ${SRCS_SCRIPTS})
target_include_directories(ScriptModule PRIVATE ${HEADERS_ENGINE}) target_include_directories(ScriptModule PRIVATE ${HEADERS_ENGINE})
@@ -471,135 +327,68 @@ if(GENERATED_SPV_FILES)
) )
endif() endif()
add_dependencies(${PROJECT} Engine) add_dependencies(${PROJECT} EngineHeaders)
add_dependencies(Engine CompileSlangShaders) add_dependencies(Engine CompileSlangShaders)
add_dependencies(ScriptModule Engine) add_dependencies(ScriptModule EngineHeaders)
target_link_libraries(CosmicTest PRIVATE Catch2::Catch2WithMain Engine)
# Fichier include
# OpenGL
#include_directories(${OPENGL_INCLUDE_DIR})
# SDL2
#include_directories(${SDL2_INCLUDE_DIRS})
# GLEW
#include_directories(${GLEW_INCLUDE_DIRS})
# SDL2_image
#include_directories(${SDL2_IMAGE_INCLUDE_DIRS})
# SDL2_ttf
#include_directories(${SDL2_TTF_INCLUDE_DIRS})
# GLM
include_directories(${GLM_INCLUDE_DIRS}) include_directories(${GLM_INCLUDE_DIRS})
# JSONFMCPP
include_directories(${JSONFMCPP_INCLUDE_DIRS}) include_directories(${JSONFMCPP_INCLUDE_DIRS})
#ENTT
include_directories(${ENTT_INCLUDE_DIRS}) include_directories(${ENTT_INCLUDE_DIRS})
#include_directories(${SPIRV_INCLUDE_DIRS})
include_directories(${SPIRV_REFLECT_INCLUDE_DIRS}) include_directories(${SPIRV_REFLECT_INCLUDE_DIRS})
include_directories(${VMA_INCLUDE_DIRS}) include_directories(${VMA_INCLUDE_DIRS})
# ASSIMP
include_directories(${ASSIMP_INCLUDE_DIRS}) include_directories(${ASSIMP_INCLUDE_DIRS})
# ODE
#include_directories(${ODE_INCLUDE_DIRS})
include_directories(${JOLT_INCLUDE_DIRS}) include_directories(${JOLT_INCLUDE_DIRS})
# SNDFILE include_directories(${OPENAL_INCLUDE_DIR})
#include_directories(${SNDFILE_INCLUDE_DIRS})
# OPENAL
include_directories(${OPENAL_INCLUDE_DIRS})
include_directories(${JSONVALIDATOR_INCLUDE_DIRS}) include_directories(${JSONVALIDATOR_INCLUDE_DIRS})
include_directories(${DRLIBS_INCLUDE_DIRS}) include_directories(${DRLIBS_INCLUDE_DIRS})
target_link_libraries(Engine ${JSONVALIDATOR_LIBRARIES}) include_directories(${MSDFATLASGEN_INCLUDE_DIRS})
if(CMAKE_BUILD_TYPE STREQUAL "Debug") if(CMAKE_BUILD_TYPE STREQUAL "Debug")
target_compile_definitions(Engine PRIVATE target_compile_definitions(Engine PRIVATE
JPH_ENABLE_ASSERTS JPH_ENABLE_ASSERTS
JPH_PROFILE_ENABLED JPH_PROFILE_ENABLED
JPH_OBJECT_STREAM JPH_OBJECT_STREAM
JPH_DEBUG_RENDERER JPH_DEBUG_RENDERER
) )
target_compile_definitions(ScriptModule PRIVATE #target_compile_definitions(ScriptModule PRIVATE
JPH_ENABLE_ASSERTS # JPH_ENABLE_ASSERTS
JPH_PROFILE_ENABLED # JPH_PROFILE_ENABLED
JPH_OBJECT_STREAM # JPH_OBJECT_STREAM
JPH_DEBUG_RENDERER # JPH_DEBUG_RENDERER
) #)
else() # Release else() # Release
target_compile_definitions(Engine PRIVATE target_compile_definitions(Engine PRIVATE
JPH_OBJECT_STREAM JPH_OBJECT_STREAM
) )
target_compile_definitions(ScriptModule PRIVATE #target_compile_definitions(ScriptModule PRIVATE
JPH_OBJECT_STREAM # JPH_OBJECT_STREAM
) #)
endif() endif()
target_link_libraries(Engine target_link_libraries(Engine PRIVATE
debug ${JOLT_LIBRARIES_DEBUG} debug ${JOLT_LIBRARIES_DEBUG}
optimized ${JOLT_LIBRARIES_RELEASE} optimized ${JOLT_LIBRARIES_RELEASE}
SDL3::SDL3
SDL3_image
SDL3_ttf
Vulkan::Vulkan
spirv-reflect
${ASSIMP_LIBRARIES}
OpenAL::OpenAL
${JSONVALIDATOR_LIBRARIES}
${MSDFATLASGEN}
) )
# Fichier lib
# OpenGL
#target_link_libraries(Engine OpenMP::OpenMP_CXX)
# OpenMP target_link_libraries(CosmicTest PRIVATE Catch2::Catch2WithMain Engine EngineHeaders)
#target_link_libraries(Engine ${OPENGL_LIBRARIES}) target_link_libraries(ScriptModule PRIVATE EngineHeaders)
target_link_options(ScriptModule PRIVATE -Wl,--allow-shlib-undefined)
# SDL2 target_link_libraries(${PROJECT} PUBLIC Engine EngineHeaders)
#target_link_libraries(Engine ${SDL2_LIBRARIES}) target_link_options(${PROJECT} PRIVATE
target_link_libraries(Engine SDL3::SDL3) -Wl,--export-dynamic
# GLEW )
#target_link_libraries(Engine ${GLEW_LIBRARIES})
# SDL2_image
#target_link_libraries(Engine SDL2_image)
target_link_libraries(Engine SDL3_image)
# SDL2_ttf
#target_link_libraries(Engine SDL2_ttf)
target_link_libraries(Engine SDL3_ttf)
# Boost
#Vulkan
target_link_libraries(Engine Vulkan::Vulkan)
target_link_libraries(Engine spirv-reflect)
#target_link_libraries(Engine spirv-cross-glsl spirv-cross-core)
# ASSIMP
target_link_libraries(Engine ${ASSIMP_LIBRARIES})
# ODE
#target_link_libraries(Engine ${ODE_LIBRARIES})
# SNDFILE
#target_link_libraries(Engine sndfile)
# OPENAL
target_link_libraries(Engine OpenAL::OpenAL)
#target_link_libraries(Engine ${CMAKE_DL_LIBS})
#target_link_libraries(${PROJECT} ${CMAKE_DL_LIBS})
# Boost
# target_link_libraries(Engine Boost::boost)
# target_link_libraries(Engine Boost::filesystem)
# target_link_libraries(Engine Boost::chrono)
# target_link_libraries(Engine Boost::thread)
# target_link_libraries(Engine Boost::date_time)
# target_link_libraries(Engine Boost::regex)
# target_link_libraries(Engine Boost::log)
# target_link_libraries(Engine Boost::log_setup)
target_link_libraries(ScriptModule Engine)
target_link_libraries(${PROJECT} Engine)
if(UNIX) if(UNIX)
add_custom_command( add_custom_command(
Submodule lib/All/msdf-atlas-gen added at 2ede254314
+5
View File
@@ -0,0 +1,5 @@
set(MSDFATLASGEN "${CMAKE_CURRENT_SOURCE_DIR}/lib/All/msdf-atlas-gen/artery-font-format/artery-font; ${CMAKE_CURRENT_SOURCE_DIR}/lib/All/msdf-atlas-gen/msdf-atlas-gen; ${CMAKE_CURRENT_SOURCE_DIR}/lib/All/msdf-atlas-gen/msdfgen/ext; {CMAKE_CURRENT_SOURCE_DIR}/lib/All/msdf-atlas-gen/msdfgen/core")
set(MSDFGENEXT "${CMAKE_CURRENT_SOURCE_DIR}/lib/All/msdf-atlas-gen/msdfgen/libmsdfgen-ext.a")
set(MSDFGENCORE "${CMAKE_CURRENT_SOURCE_DIR}/lib/All/msdf-atlas-gen/msdfgen/libmsdfgen-core.a")
set(MSDFATLASGEN "${CMAKE_CURRENT_SOURCE_DIR}/lib/All/msdf-atlas-gen/libmsdf-atlas-gen.a")
@@ -0,0 +1,15 @@
#include "CCamera2D.hpp"
#include "Core/Kernel/CKernel.hpp"
namespace CosmicCore {
void CCamera2D::recalcProjection() {
//todo
float width = CKernelBase::instance()->getWindowWidth();
float height = CKernelBase::instance()->getWindowHeight();
//m_projection = glm::ortho(0.0f, width, 0.0f, height, -1.0f, 1.0f);
//m_projection //= glm::perspective(glm::radians(m_fov), m_aspect, m_near, m_far);
m_projection = glm::ortho(0.0f, width, height, 0.0f, -1.0f, 1.0f);
//m_projection[1][1] *= -1;
}
}
@@ -0,0 +1,117 @@
#ifndef CCAMERA2D_HPP
#define CCAMERA2D_HPP
#include "../CAbstractComponent.hpp"
//pour vulkan depth 0-1 (opengl [-1,1])
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include "../../Systems/Graphics/API/VulkanImplementation/VulkanImpl.hpp"
#include "../Geometry/CTransform2D.hpp"
namespace CosmicCore {
//TODO LES MAJ REELLES DUN MOUVEMENT TRANSFORM
//AJOUT DONC DE LA VUE ET AUTRE PARAM
//Pour le moment ne gère qu'une caméra fixe (UI)
class CCamera2D : public CAbstractComponent {
private:
glm::mat4 m_projection = glm::mat4(1.0f);
// GPU
struct Camera2DUBOData {
glm::mat4 projection;
};
std::array<VMABuffer, MAX_FRAMES_IN_FLIGHT> m_uniformBuffers;
std::array<void*, MAX_FRAMES_IN_FLIGHT> m_mappedData{};
std::array<ManagedDescriptorSet, MAX_FRAMES_IN_FLIGHT> m_descriptorSets;
void recalcProjection();
public:
CCamera2D(CEntity& entity) : CAbstractComponent(entity) {
recalcProjection();
}
~CCamera2D(){
destroy();
}
glm::mat4 getProjection() const { return m_projection; }
// GPU
void initUniformBuffer(VmaAllocator allocator) {
VulkanImpl* api = dynamic_cast<VulkanImpl*>(GraphicsAPI::getAPI().get());
for (uint32_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
VkBufferCreateInfo bufferInfo{};
bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
bufferInfo.size = sizeof(Camera2DUBOData);
bufferInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
VmaAllocationCreateInfo allocInfo{};
allocInfo.usage = VMA_MEMORY_USAGE_CPU_TO_GPU;
allocInfo.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT;
VmaAllocationInfo info{};
vmaCreateBuffer(allocator, &bufferInfo, &allocInfo,
&m_uniformBuffers[i].buffer,
&m_uniformBuffers[i].allocation,
&info);
m_mappedData[i] = info.pMappedData;
m_descriptorSets[i] = api->getDescriptorPoolManager().allocate(
*api->getProjection2DLayout()
);
vk::DescriptorBufferInfo descriptorBufferInfo{
vk::Buffer(m_uniformBuffers[i].buffer),
0,
sizeof(Camera2DUBOData)
};
vk::WriteDescriptorSet descriptorWrite{
*m_descriptorSets[i].set,
0, 0, 1,
vk::DescriptorType::eUniformBuffer,
{}, &descriptorBufferInfo
};
static_cast<vk::raii::Device*>(api->getDevice())->updateDescriptorSets(descriptorWrite, {});
}
}
void destroyUniformBuffer(VmaAllocator allocator) {
VulkanImpl* api = dynamic_cast<VulkanImpl*>(GraphicsAPI::getAPI().get());
for (uint32_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
api->getDescriptorPoolManager().free(m_descriptorSets[i]);
vmaDestroyBuffer(allocator, m_uniformBuffers[i].buffer,
m_uniformBuffers[i].allocation);
}
}
void updateUniformBuffer(uint32_t frameIndex, const CTransform2D& transform) {
Camera2DUBOData data{ m_projection};
memcpy(m_mappedData[frameIndex], &data, sizeof(data));
}
vk::raii::DescriptorSet& getDescriptorSet(uint32_t frameIndex) {
return m_descriptorSets[frameIndex].set;
}
void destroy()
{
VulkanImpl* api = dynamic_cast<VulkanImpl*>(GraphicsAPI::getAPI().get());
for (uint32_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
api->destroyBuffer(m_uniformBuffers[i], api->getCurrentFrameIndex());
api->destroyDescriptorSet(m_descriptorSets[i], api->getCurrentFrameIndex());
}
}
nlohmann::json to_json(){
return nlohmann::json();
};
};
} // namespace CosmicCore
#endif
@@ -0,0 +1,24 @@
#include "CCollider2D.hpp"
#include "Core/Component/Geometry/CTransform2D.hpp"
#include "Core/Kernel/CKernel.hpp"
namespace CosmicCore {
bool CCollider2D::shapeContains(glm::vec2 point) const {
auto& registry = getEntity().getRegistry();
// récupère le transform
auto& transform = registry.registry.get<CTransform2D>(*getEntity());
glm::vec2 abs = transform.getAbsolutePosition();
float y = CKernelBase::instance()->getWindowHeight();
switch (m_shape) {
case E2DShape::RECTANGLE: return point.x >= abs.x && point.x <= abs.x + transform.getSize().x && (y-point.y) >= abs.y && (y-point.y) <= abs.y + transform.getSize().y;
case E2DShape::CIRCLE: break;//TODO
case E2DShape::TEXT: break;
case E2DShape::POLYGON: break;
break;
}
return false;
}
}
@@ -0,0 +1,31 @@
#ifndef CCOLLIDER2D_HPP
#define CCOLLIDER2D_HPP
#include "Core/Component/CAbstractComponent.hpp"
#include "Core/Entity/CEntity.hpp"
#include "glm/ext/vector_float2.hpp"
namespace CosmicCore {
enum class E2DShape
{
RECTANGLE,
CIRCLE,
TEXT,
POLYGON
};
class CCollider2D: public CAbstractComponent
{
private:
E2DShape m_shape = E2DShape::RECTANGLE;
public:
CCollider2D(CEntity& entity, E2DShape shape): CAbstractComponent(entity), m_shape(shape){};
bool shapeContains(glm::vec2 point) const;
nlohmann::json to_json(){return nlohmann::json();};
};
}
#endif
@@ -78,6 +78,7 @@ namespace CosmicCore
return parentTransform.getInheritedTransformation() * m_transformation; return parentTransform.getInheritedTransformation() * m_transformation;
} }
glm::vec3 CTransform::getCenter(void) const { glm::vec3 CTransform::getCenter(void) const {
return m_center; return m_center;
} }
@@ -0,0 +1,64 @@
#include "CTransform2D.hpp"
#include "Core/Kernel/CKernel.hpp"
#include "Core/Systems/Graphics/API/VulkanImplementation/VulkanImpl.hpp"
#include <iostream>
namespace CosmicCore {
void CTransform2D::initUniformBuffer(VmaAllocator allocator)
{
if(m_gpuInitialized) return;
VulkanImpl* api = dynamic_cast<VulkanImpl*>(GraphicsAPI::getAPI().get());
for (uint32_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
VkBufferCreateInfo bufferInfo{};
bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
bufferInfo.size = sizeof(Transform2DUBO);
bufferInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
VmaAllocationCreateInfo allocInfo{};
allocInfo.usage = VMA_MEMORY_USAGE_CPU_TO_GPU;
allocInfo.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT;
VmaAllocationInfo info{};
vmaCreateBuffer(allocator, &bufferInfo, &allocInfo,
&m_uniformBuffers[i].buffer,
&m_uniformBuffers[i].allocation,
&info);
m_mappedData[i] = info.pMappedData;
m_descriptorSets[i] = api->getDescriptorPoolManager().allocate(api->getTransform2DLayout());
vk::DescriptorBufferInfo descriptorBufferInfo{vk::Buffer(m_uniformBuffers[i].buffer), 0, sizeof(Transform2DUBO)};
vk::WriteDescriptorSet descriptorWrite{m_descriptorSets[i].set, 0, 0,1, vk::DescriptorType::eUniformBuffer, {}, &descriptorBufferInfo};
static_cast<vk::raii::Device*>(api->getDevice())->updateDescriptorSets(descriptorWrite, {});
}
m_gpuInitialized = true;
}
void CTransform2D::destroyUniformBuffer()
{
if(!m_gpuInitialized) return;
VulkanImpl* api = dynamic_cast<VulkanImpl*>(GraphicsAPI::getAPI().get());
for (uint32_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
api->destroyBuffer(m_uniformBuffers[i], api->getCurrentFrameIndex());
api->destroyDescriptorSet(m_descriptorSets[i], api->getCurrentFrameIndex());
}
}
void CTransform2D::updateUniformBuffer(uint32_t frameIndex)
{
if (!m_gpuInitialized) return;
Transform2DUBO data{
getMatrix(),
m_size,
m_zOrder,
0.0f
};
memcpy(m_mappedData[frameIndex], &data, sizeof(data));
}
}
@@ -0,0 +1,109 @@
#ifndef CTRANSFORM2D_HPP
#define CTRANSFORM2D_HPP
#include "Core/Component/CAbstractComponent.hpp"
#include "Core/Systems/Graphics/API/VulkanImplementation/ManagedDescriptorSet.hpp"
#include "Core/Systems/Graphics/API/VulkanImplementation/VMABuffer.hpp"
#include "glm/ext/matrix_float4x4.hpp"
#include "glm/ext/vector_float2.hpp"
#include "glm/gtx/transform.hpp"
namespace CosmicCore {
struct Transform2DUBO {
glm::mat4 transform; // matrice 2D
glm::vec2 size; // taille pour le shader SDF
float zOrder;
float padding;
};
class CTransform2D : public CAbstractComponent {
glm::vec2 m_position = {0, 0};
glm::vec2 m_size = {100, 100};
glm::vec2 m_scale = {1, 1}; // scale indépendant de la taille
glm::vec2 m_anchor = {0, 0}; // 0=topleft, 0.5=center, 1=bottomright
glm::vec2 m_pivot = {0, 0};
float m_rotation = 0.0f;
float m_zOrder = 0.0f; // ordre de rendu UI
bool m_visible = true;
//TODO RELATIONSHIP2D ???
CTransform2D* m_parent = nullptr; // séparé de CRelationship 3D
std::array<VMABuffer, MAX_FRAMES_IN_FLIGHT> m_uniformBuffers;
std::array<void*, MAX_FRAMES_IN_FLIGHT> m_mappedData{};
std::array<ManagedDescriptorSet, MAX_FRAMES_IN_FLIGHT> m_descriptorSets;
bool m_gpuInitialized = false;
public:
explicit CTransform2D(CEntity& entity) : CAbstractComponent(entity) {}
~CTransform2D() {
if (m_gpuInitialized) destroyUniformBuffer();
}
CTransform2D(CTransform2D&&) = default;
CTransform2D& operator=(CTransform2D&&) = default;
CTransform2D(const CTransform2D&) = delete;
CTransform2D& operator=(const CTransform2D&) = delete;
CTransform2D& setPosition(glm::vec2 pos) { m_position = pos; return *this; }
CTransform2D& setSize(glm::vec2 size) { m_size = size; return *this; }
CTransform2D& setScale(glm::vec2 scale) { m_scale = scale;return *this; }
CTransform2D& setRotation(float rot) { m_rotation = rot; return *this; }
CTransform2D& setZOrder(float z) { m_zOrder = z; return *this; }
CTransform2D& setVisible(bool v) { m_visible = v; return *this; }
CTransform2D& setAnchor(glm::vec2 anchor) { m_anchor = anchor; return *this; }
CTransform2D& setPivot(glm::vec2 pivot) { m_pivot = pivot; return *this; }
CTransform2D& setParent(CTransform2D* p) { m_parent = p; return *this; }
glm::vec2 getPosition() const { return m_position; }
glm::vec2 getSize() const { return m_size; }
glm::vec2 getScale() const { return m_scale; }
float getRotation() const { return m_rotation; }
float getZOrder() const { return m_zOrder; }
bool isVisible() const { return m_visible; }
CTransform2D* getParent() const { return m_parent; }
glm::vec2 getAbsolutePosition() const {
glm::vec2 base = m_position;
/*if (m_parent) {
glm::vec2 parentPos = m_parent->getAbsolutePosition();
glm::vec2 parentSize = m_parent->getSize();
// anchor relatif à la taille du parent
base = parentPos + m_anchor * parentSize + m_position;
}*/
return base;
}
glm::mat4 getMatrix() const {
glm::vec2 absPos = getAbsolutePosition();
glm::vec2 pivotPx = m_pivot * m_size;
glm::mat4 mat = glm::mat4(1.0f);
mat = glm::translate(mat, glm::vec3(absPos + pivotPx, m_zOrder * 0.001f));
mat = glm::rotate(mat, glm::radians(m_rotation), {0, 0, 1});
mat = glm::scale(mat, glm::vec3(m_size * m_scale, 1));
mat = glm::translate(mat, glm::vec3(-m_pivot, 0));
return mat;
}
// ── GPU ───────────────────────────────────────────────────────────
void initUniformBuffer(VmaAllocator allocator);
void destroyUniformBuffer();
void updateUniformBuffer(uint32_t frameIndex);
vk::raii::DescriptorSet& getDescriptorSet(uint32_t frameIndex) {
return m_descriptorSets[frameIndex].set;
}
nlohmann::json to_json() {
return {};
}
};
}
#endif
@@ -0,0 +1,5 @@
#include "CRenderer2D.hpp"
namespace CosmicCore {
} // namespace CosmicCore
@@ -0,0 +1,21 @@
#ifndef CUIRENDERER_HPP
#define CUIRENDERER_HPP
#include "CAbstractRenderer.hpp"
#include "Core/Entity/CEntity.hpp"
#include "Core/Systems/Graphics/Data/Model/CModel2D.hpp"
namespace CosmicCore {
class CRenderer2D : public CAbstractRenderer{
CModel2D* m_model;
public:
CRenderer2D() = delete;
CRenderer2D(CEntity& e): CAbstractRenderer(e){};
CRenderer2D(CEntity& e, CModel2D* mod): CAbstractRenderer(e), m_model(mod){};
nlohmann::json to_json() override{return nlohmann::json();};
CModel2D* getModel(){return m_model;};
};
}
#endif
@@ -0,0 +1,27 @@
#ifndef CTEXTRENDERER_HPP
#define CTEXTRENDERER_HPP
#include "Core/Component/Graphics/CAbstractRenderer.hpp"
#include "Core/Entity/CEntity.hpp"
#include "Core/Systems/Graphics/Data/Font/CFont.hpp"
#include "Core/Systems/Graphics/Data/Model/CModel2D.hpp"
#include "nlohmann/json_fwd.hpp"
namespace CosmicCore {
//TODO pipeline vulkan dédié....
class CTextRenderer : public CAbstractRenderer
{
private:
CModel2D* m_model;
std::string m_text;
public:
CTextRenderer(CEntity& entity): CAbstractRenderer(entity){};
CTextRenderer(CEntity& e, CModel2D* mod): CAbstractRenderer(e), m_model(mod){};
CTextRenderer(CEntity& e, CModel2D* mod, std::string text): CAbstractRenderer(e), m_model(mod), m_text(text){};
CModel2D* getModel(){return m_model;};
const std::string& getText() const{return m_text;};
nlohmann::json to_json(){ return nlohmann::json(); };
};
}
#endif
@@ -18,9 +18,14 @@ namespace CosmicCore {
m_onReleased.push_back({actionName, cb, 0, false}); m_onReleased.push_back({actionName, cb, 0, false});
} }
void CInputManager::onMouseMove(std::function<void(CEntity&, glm::vec2)> cb) void CInputManager::addOnMouseMove(std::function<void(CEntity&, glm::vec2)> cb)
{ {
m_onMouseMove = cb; m_onMouseMove.emplace_back(cb);
}
void CInputManager::addOnGenericMouseLeftClick(std::function<void(CEntity&)> cb)
{
m_onMouseLeftClickReleased.emplace_back(GenericMouseClickAction(cb));
} }
// appelé par CInputWorld::updateWorld() // appelé par CInputWorld::updateWorld()
@@ -61,7 +66,20 @@ namespace CosmicCore {
} }
glm::vec2 mouseRel = inputWorld.getMouseRelative(); glm::vec2 mouseRel = inputWorld.getMouseRelative();
if (m_onMouseMove && (mouseRel.x != 0 || mouseRel.y != 0)) if (!m_onMouseMove.empty() && (mouseRel.x != 0 || mouseRel.y != 0))
m_onMouseMove(entity, mouseRel); {
for(auto& cbH : m_onMouseMove)
{
cbH.cb(entity, mouseRel);
}
}
//todo other click (onClick and right click)
if(!m_onMouseLeftClickReleased.empty() && inputWorld.isLeftMouseButtonJustReleased())
{
for(auto& clickCB : m_onMouseLeftClickReleased)
{
clickCB.cb(entity);
}
}
} }
} }
@@ -6,6 +6,7 @@
#include "../../Systems/Input/CInputDispatcher.hpp" #include "../../Systems/Input/CInputDispatcher.hpp"
#include "glm/fwd.hpp" #include "glm/fwd.hpp"
#include "nlohmann/json_fwd.hpp" #include "nlohmann/json_fwd.hpp"
#include <vector>
namespace CosmicCore { namespace CosmicCore {
@@ -19,12 +20,24 @@ namespace CosmicCore {
InputAction resolvedId = 0; InputAction resolvedId = 0;
bool resolved = false; bool resolved = false;
}; };
struct GenericMouseClickAction{
std::function<void(CEntity&)> cb;
};
struct MouseMovementAction{
std::function<void(CEntity&, glm::vec2)> cb;
};
std::vector<BoundAction> m_onHeld; std::vector<BoundAction> m_onHeld;
std::vector<BoundAction> m_onPressed; std::vector<BoundAction> m_onPressed;
std::vector<BoundAction> m_onReleased; std::vector<BoundAction> m_onReleased;
std::function<void(CEntity&, glm::vec2)> m_onMouseMove; std::vector<MouseMovementAction> m_onMouseMove;
std::vector<GenericMouseClickAction> m_onMouseLeftClickPressed;
std::vector<GenericMouseClickAction> m_onMouseLeftClickReleased;
std::vector<GenericMouseClickAction> m_onMouseRightClickPressed;
std::vector<GenericMouseClickAction> m_onMouseRightClickReleased;
bool m_enabled = true; bool m_enabled = true;
public: public:
@@ -33,8 +46,9 @@ namespace CosmicCore {
void onPressed(const std::string& actionName, std::function<void(CEntity&)> cb); void onPressed(const std::string& actionName, std::function<void(CEntity&)> cb);
void onHeld(const std::string& actionName, std::function<void(CEntity&)> cb); void onHeld(const std::string& actionName, std::function<void(CEntity&)> cb);
void onReleased(const std::string& actionNamen, std::function<void(CEntity&)> cb); void onReleased(const std::string& actionName, std::function<void(CEntity&)> cb);
void onMouseMove(std::function<void(CEntity&, glm::vec2)> cb); void addOnMouseMove(std::function<void(CEntity&, glm::vec2)> cb);
void addOnGenericMouseLeftClick(std::function<void(CEntity&)> cb);
void setEnabled(bool enabled) { m_enabled = enabled; } void setEnabled(bool enabled) { m_enabled = enabled; }
+2 -2
View File
@@ -47,9 +47,9 @@ namespace CosmicCore
//CEntity getParent(); //CEntity getParent();
template<typename compType, typename... Args> template<typename compType, typename... Args>
void addComponent(std::forward_list<Args...> args) void addComponent(Args&&... args)
{ {
m_registryReference().emplace<compType>(m_handle, *this, args); m_registryReference().emplace<compType>(m_handle, *this, std::forward<Args>(args)...);
} }
template<typename compType> template<typename compType>
+52 -7
View File
@@ -1,9 +1,26 @@
#ifndef CKERNEL_HPP #ifndef CKERNEL_HPP
#define CKERNEL_HPP #define CKERNEL_HPP
#include "Core/Component/Camera/CCamera.hpp"
#include "Core/Component/Camera/CCamera2D.hpp"
#include "Core/Component/Geometry/CTransform2D.hpp"
#include "Core/Component/Graphics/CRenderer2D.hpp"
#include "Core/Component/Graphics/CTextRenderer.hpp"
#include "Core/Systems/Graphics/Data/CModelLoader.hpp"
#include "Core/Systems/Graphics/Data/Material/CMaterial2D.hpp"
#include "Core/Systems/Graphics/Data/Mesh/CMesh2D.hpp"
#include "Core/Systems/Graphics/Data/Model/CModel2D.hpp"
#include "Core/Systems/Graphics/Shader/Implementations/CShaderImplVulkan.hpp"
#include "Core/Systems/Input/CInputDispatcher.hpp" #include "Core/Systems/Input/CInputDispatcher.hpp"
#include "../../Utils/Configurations/CBasicConfiguration.hpp" #include "../../Utils/Configurations/CBasicConfiguration.hpp"
#include "Core/Systems/Resources/API/CResourceAPI.hpp"
#include "Core/Systems/Resources/Font/CFontManager.hpp"
#include "Utils/Factory/ComponentFactory.hpp"
#include "glm/ext/vector_float4.hpp"
#include <cstddef>
#include <memory> #include <memory>
#include <vector>
#define GLM_ENABLE_EXPERIMENTAL #define GLM_ENABLE_EXPERIMENTAL
#include <glm/glm.hpp> #include <glm/glm.hpp>
#include <glm/gtx/transform.hpp> #include <glm/gtx/transform.hpp>
@@ -62,6 +79,8 @@ namespace CosmicCore {
virtual CScene* getActiveScene() = 0; virtual CScene* getActiveScene() = 0;
virtual void quit() = 0; virtual void quit() = 0;
virtual void cleanup() = 0; virtual void cleanup() = 0;
virtual unsigned int getWindowHeight() = 0;
virtual unsigned int getWindowWidth() = 0;
virtual ~CKernelBase() = default; virtual ~CKernelBase() = default;
}; };
@@ -100,15 +119,17 @@ namespace CosmicCore {
CKernel() = delete; CKernel() = delete;
std::string getName() { return m_gameName; }; std::string getName() override { return m_gameName; };
unsigned int getWindowHeight() override {return m_window.getHeight();};
unsigned int getWindowWidth() override {return m_window.getWidth();};
void cleanup(){m_sceneMap.clear();}; void cleanup() override {m_sceneMap.clear();};
unsigned int getDeltatime(void) { unsigned int getDeltatime(void) override {
return m_deltaTime; return m_deltaTime;
} }
void setDeltatime(unsigned int delta){ void setDeltatime(unsigned int delta) override{
m_deltaTime = delta; m_deltaTime = delta;
} }
@@ -122,7 +143,7 @@ namespace CosmicCore {
{ {
} }
CScene* getActiveScene() CScene* getActiveScene() override
{ {
return m_activeScene; return m_activeScene;
} }
@@ -131,7 +152,6 @@ namespace CosmicCore {
loadConfigurations(); loadConfigurations();
CContext::init(SDL_INIT_VIDEO | SDL_INIT_EVENTS | SDL_INIT_JOYSTICK | SDL_INIT_HAPTIC); CContext::init(SDL_INIT_VIDEO | SDL_INIT_EVENTS | SDL_INIT_JOYSTICK | SDL_INIT_HAPTIC);
CScriptAPI::init(); CScriptAPI::init();
//CScriptRegister::registerAllScripts(); //CScriptRegister::registerAllScripts();
CPhysicsAPI::init(); CPhysicsAPI::init();
@@ -143,6 +163,31 @@ namespace CosmicCore {
auto scene = CScene::load("scenes/scene1.json"); auto scene = CScene::load("scenes/scene1.json");
m_activeScene = scene.get(); m_activeScene = scene.get();
m_sceneMap[scene->getName()] = std::move(scene); m_sceneMap[scene->getName()] = std::move(scene);
auto font = CResourceAPI::resources().fonts().loadFont("assets/fonts/Arial");
auto ent = m_activeScene->createEntity();
ComponentFactory::Transform2DConfig trConf = {
{100.0,100.0},
{75.0,75.0},
{1.0,1.0},
{0.0,0.0},
0.0,
0.0,
true};
ComponentFactory::addTransform2D(ent, trConf);
Model2DLoadConfig config;
config.shaderName = "ui";
auto shader = CResourceAPI::resources().shaders().get(config.shaderName);
MeshMaterial2D mm2d;
mm2d.material = new CMaterial2D();
mm2d.material->m_color = {1,1,1,1};
mm2d.material->m_font = font;
mm2d.material->shader = static_cast<CShaderImplVulkan*>(shader);
mm2d.material->build();
mm2d.mesh = new CMesh2D();
mm2d.mesh->buildFromText(mm2d.material->m_font, "TEST DE FONT");
CModel2D* model = new CModel2D({mm2d});
ent.addComponent<CTextRenderer>(model);
} }
} }
@@ -241,7 +286,7 @@ namespace CosmicCore {
CContext::quit(); CContext::quit();
} }
void quit() { void quit() override {
m_finished = true; m_finished = true;
} }
+167 -2
View File
@@ -9,7 +9,13 @@
#include "../../Utils/Factory/CEntityFactory.hpp" #include "../../Utils/Factory/CEntityFactory.hpp"
#include "../../Utils/Factory/ComponentFactory.hpp" #include "../../Utils/Factory/ComponentFactory.hpp"
#include "Core/Component/Camera/CCamera2D.hpp"
#include "Core/Component/Collider/CCollider2D.hpp"
#include "Core/Component/Geometry/CTransform2D.hpp"
#include "Core/Component/Graphics/CRenderer2D.hpp"
#include "Core/Component/Graphics/CTextRenderer.hpp"
#include "Core/Component/Light/CLight.hpp" #include "Core/Component/Light/CLight.hpp"
#include "Core/Entity/EntityComponentManager.hpp"
#include "glm/ext/vector_float3.hpp" #include "glm/ext/vector_float3.hpp"
#include "glm/gtc/type_ptr.hpp" #include "glm/gtc/type_ptr.hpp"
#include "nlohmann/json_fwd.hpp" #include "nlohmann/json_fwd.hpp"
@@ -32,6 +38,11 @@ namespace CosmicCore {
m_audioWorld.initWorld(); m_audioWorld.initWorld();
m_scriptWorld.initWorld(); m_scriptWorld.initWorld();
m_lightsBuffer.init(); m_lightsBuffer.init();
//m_uiWorld.init();
m_ecManager.registry.sort<CTransform2D>([](const CTransform2D& lhs, const CTransform2D& rhs) {
return lhs.getZOrder() > rhs.getZOrder();
});
} }
@@ -44,6 +55,8 @@ namespace CosmicCore {
m_tangibleWorld.destroy(); m_tangibleWorld.destroy();
m_audioWorld.destroy(); m_audioWorld.destroy();
m_scriptWorld.destroy(); m_scriptWorld.destroy();
m_lightsBuffer.destroy();
//m_uiWorld.destroy();
} }
CEntity CScene::createEntity(){ CEntity CScene::createEntity(){
@@ -92,9 +105,11 @@ namespace CosmicCore {
m_lightsBuffer.update(frameIndex, lightsData); m_lightsBuffer.update(frameIndex, lightsData);
} }
void CScene::render3D(vk::raii::CommandBuffer& cmd, uint32_t frameIndex){
void CScene::render(vk::raii::CommandBuffer& cmd, uint32_t frameIndex){
auto entities = m_ecManager.registry.view<CRenderer, CTransform>(); auto entities = m_ecManager.registry.view<CRenderer, CTransform>();
if(entities.begin() != entities.end())
{
VulkanImpl* api = dynamic_cast<VulkanImpl*>(GraphicsAPI::getAPI().get()); VulkanImpl* api = dynamic_cast<VulkanImpl*>(GraphicsAPI::getAPI().get());
auto cam = m_ecManager.registry.view<CCamera, CTransform>(); auto cam = m_ecManager.registry.view<CCamera, CTransform>();
auto& camera = m_ecManager.registry.get<CCamera>(cam.front()); auto& camera = m_ecManager.registry.get<CCamera>(cam.front());
@@ -153,6 +168,103 @@ namespace CosmicCore {
} }
} }
} }
}
void CScene::render2D(vk::raii::CommandBuffer& cmd, uint32_t frameIndex){
auto entities = m_ecManager.registry.view<CRenderer2D, CTransform2D>();
auto textEntities = m_ecManager.registry.view<CTextRenderer, CTransform2D>();
if(entities.begin() != entities.end())
{
VulkanImpl* api = dynamic_cast<VulkanImpl*>(GraphicsAPI::getAPI().get());
auto cam = m_ecManager.registry.view<CCamera2D>();
auto& camera = m_ecManager.registry.get<CCamera2D>(cam.front());
auto& trCam = m_ecManager.registry.get<CTransform2D>(cam.front());
camera.updateUniformBuffer(frameIndex, trCam);
//
cmd.bindDescriptorSets(
vk::PipelineBindPoint::eGraphics,
api->getDefault2DPipelineLayout(), // layout du pipeline
2,
*camera.getDescriptorSet(frameIndex),
{}
);
for (auto& entity : entities) {
auto model = m_ecManager.registry.get<CRenderer2D>(entity).getModel();
auto& transform = m_ecManager.registry.get<CTransform2D>(entity);
transform.updateUniformBuffer(frameIndex);
// bind transform UBO (set = 1)
cmd.bindDescriptorSets(
vk::PipelineBindPoint::eGraphics,
api->getDefault2DPipelineLayout(), // layout du pipeline
0, // set = 1
*transform.getDescriptorSet(frameIndex),
{}
);
for (auto& mm : model->getMeshMaterials()) {
// ne rebind le pipeline que si le material change
//if (mesh.getMaterial() != boundMaterial) {
//boundMaterial = mesh.getMaterial();
cmd.bindPipeline(vk::PipelineBindPoint::eGraphics,
*mm.material->getPipeline());
cmd.bindDescriptorSets(vk::PipelineBindPoint::eGraphics,
*mm.material->getPipelineLayout(),
1,
*mm.material->getDescriptorSet(frameIndex),
{});
//}
cmd.bindVertexBuffers(0, vk::Buffer(mm.mesh->getVertexIndexBuffer().buffer), mm.mesh->getVertexOffset());
cmd.bindIndexBuffer(vk::Buffer(mm.mesh->getVertexIndexBuffer().buffer), mm.mesh->getIndexOffset(), vk::IndexType::eUint32);
cmd.drawIndexed(mm.mesh->getIndexCount(), 1, 0, 0, 0);
}
}
for (auto& entity : textEntities) {
auto& textRenderer = m_ecManager.registry.get<CTextRenderer>(entity);
auto& transform = m_ecManager.registry.get<CTransform2D>(entity);
auto model = textRenderer.getModel();
transform.updateUniformBuffer(frameIndex);
// bind transform UBO (set = 1)
cmd.bindDescriptorSets(
vk::PipelineBindPoint::eGraphics,
api->getDefault2DPipelineLayout(), // layout du pipeline
0, // set = 1
*transform.getDescriptorSet(frameIndex),
{}
);
for (auto& mm : model->getMeshMaterials()) {
// ne rebind le pipeline que si le material change
//if (mesh.getMaterial() != boundMaterial) {
//boundMaterial = mesh.getMaterial();
cmd.bindPipeline(vk::PipelineBindPoint::eGraphics,
*mm.material->getPipeline());
cmd.bindDescriptorSets(vk::PipelineBindPoint::eGraphics,
*mm.material->getPipelineLayout(),
1,
*mm.material->getDescriptorSet(frameIndex),
{});
//}
cmd.bindVertexBuffers(0, vk::Buffer(mm.mesh->getVertexIndexBuffer().buffer), mm.mesh->getVertexOffset());
cmd.bindIndexBuffer(vk::Buffer(mm.mesh->getVertexIndexBuffer().buffer), mm.mesh->getIndexOffset(), vk::IndexType::eUint32);
cmd.drawIndexed(mm.mesh->getIndexCount(), 1, 0, 0, 0);
}
}
}
}
void CScene::render(vk::raii::CommandBuffer& cmd, uint32_t frameIndex){
render3D(cmd, frameIndex);
render2D(cmd, frameIndex);
}
nlohmann::json CScene::to_json() nlohmann::json CScene::to_json()
{ {
@@ -285,6 +397,59 @@ namespace CosmicCore {
} }
} }
nlohmann::json& entities2D = sceneJson[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Scene_Entities2D)];
for(auto& entity : entities2D.items())
{
nlohmann::json& entityObj = entity.value();
auto ref = entityObj[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Entity2D_Ref)].get<unsigned int>();
nlohmann::json& components = entityObj[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Entity2D_Components)];
nlohmann::json& transform = components[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Component_Transform2D)];
nlohmann::json& camera = components[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Component_Camera2D)];
nlohmann::json& collider = components[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Component_Collider2D)];
nlohmann::json& renderer = components[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Component_Renderer2D)];
nlohmann::json& script = components[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Component_Script)];
auto trConfig(!transform.is_null() ? std::optional<CosmicUtils::ComponentFactory::Transform2DConfig>({
glm::make_vec2(transform[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Transform_Position2D)].get<std::vector<float>>().data()),
glm::make_vec2(transform[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Transform_Size2D)].get<std::vector<float>>().data()),
glm::make_vec2(transform[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Transform_Scale2D)].get<std::vector<float>>().data()),
glm::make_vec2(transform[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Transform_Pivot2D)].get<std::vector<float>>().data()),
transform[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Transform_Rotation2D)].get<float>(),
transform[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Transform_zOrder2D)].get<float>(),
transform[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Transform_Visible2D)].get<bool>()
}) : std::nullopt);
auto camConfig(!camera.is_null() ? std::optional<CosmicUtils::ComponentFactory::Camera2DConfig>({
camera[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Camera_Zoom2D)].get<float>()
}) : std::nullopt);
auto colliderConfig(!collider.is_null() ? std::optional<CosmicUtils::ComponentFactory::Collider2DConfig>({
static_cast<E2DShape>(collider[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Collider_Shape2D)].get<int>())
}) : std::nullopt);
auto rendererConfig(!renderer.is_null() ? std::optional<CosmicUtils::ComponentFactory::Renderer2DConfig>({
renderer[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Renderer_Model2D)].get<std::string>(),
renderer[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Renderer_Shader2D)].get<std::string>(),
}) : std::nullopt);
auto scriptConfig(!script.is_null() ? std::optional<CosmicUtils::ComponentFactory::ScriptConfig>({
script.get<std::vector<std::string>>()
}): std::nullopt);
CosmicUtils::CEntityFactory::Entity2DConfig config = {
entityObj[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Entity2D_Name)],
entityObj[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Entity2D_Description)],
trConfig,
camConfig,
rendererConfig,
colliderConfig,
scriptConfig
};
auto entityHandle = CosmicUtils::CEntityFactory::create(scene.get(), config);
}
//Connect entities to relationships //Connect entities to relationships
for(auto& [entityNb, handle]: idToHandle) for(auto& [entityNb, handle]: idToHandle)
{ {
+8
View File
@@ -9,6 +9,7 @@
#include "../Systems/Audio/CAudioWorld.hpp" #include "../Systems/Audio/CAudioWorld.hpp"
#include "../Systems/Scripts/CScriptWorld.hpp" #include "../Systems/Scripts/CScriptWorld.hpp"
#include "Core/Systems/Graphics/Data/Light/CLightsBuffer.hpp" #include "Core/Systems/Graphics/Data/Light/CLightsBuffer.hpp"
#include "Core/Systems/Graphics/UserInterface/CUIWorld.hpp"
namespace CosmicCore { namespace CosmicCore {
class CEntity; class CEntity;
@@ -21,6 +22,11 @@ namespace CosmicCore {
CAudioWorld m_audioWorld; CAudioWorld m_audioWorld;
CScriptWorld m_scriptWorld; CScriptWorld m_scriptWorld;
CLightsBuffer m_lightsBuffer; CLightsBuffer m_lightsBuffer;
//CUIWorld m_uiWorld;
void render3D(vk::raii::CommandBuffer& cmd, uint32_t frameIndex);
void render2D(vk::raii::CommandBuffer& cmd, uint32_t frameIndex);
public: public:
CScene() = delete; CScene() = delete;
CScene(std::string name); CScene(std::string name);
@@ -47,6 +53,7 @@ namespace CosmicCore {
CScriptWorld& getScriptWorld() {return m_scriptWorld;}; CScriptWorld& getScriptWorld() {return m_scriptWorld;};
//CUIWorld& getUIWorld() {return m_uiWorld;};
//CEntity* getActiveCamera(); //CEntity* getActiveCamera();
//void setActiveCamera(CEntity* newCamera); //void setActiveCamera(CEntity* newCamera);
@@ -87,6 +94,7 @@ namespace CosmicCore {
//unsigned int getMask(); //unsigned int getMask();
void render(vk::raii::CommandBuffer& cmd, uint32_t frameIndex); void render(vk::raii::CommandBuffer& cmd, uint32_t frameIndex);
void collectLights(vk::raii::CommandBuffer& cmd, uint32_t frameIndex); void collectLights(vk::raii::CommandBuffer& cmd, uint32_t frameIndex);
//void updateScript(); //void updateScript();
@@ -101,11 +101,16 @@ void VulkanImpl::cleanup(){
// descriptor set layouts + pipeline layout avant le device // descriptor set layouts + pipeline layout avant le device
defaultPipelineLayoutInfo = nullptr; defaultPipelineLayoutInfo = nullptr;
default2DPipelineLayoutInfo = nullptr;
cameraLayout = nullptr; cameraLayout = nullptr;
transformLayout = nullptr; transformLayout = nullptr;
materialLayout = nullptr; materialLayout = nullptr;
lightLayout = nullptr; lightLayout = nullptr;
projection2DLayout = nullptr;
transform2DLayout = nullptr;
material2DLayout = nullptr;
VmaTotalStatistics stats; VmaTotalStatistics stats;
vmaCalculateStatistics(allocator, &stats); vmaCalculateStatistics(allocator, &stats);
if (stats.total.statistics.allocationCount > 0) { if (stats.total.statistics.allocationCount > 0) {
@@ -646,6 +651,57 @@ void VulkanImpl::createDescriptorSetLayouts()
layouts.data() layouts.data()
}; };
defaultPipelineLayoutInfo = vk::raii::PipelineLayout(device, layoutInfo); defaultPipelineLayoutInfo = vk::raii::PipelineLayout(device, layoutInfo);
//Create 2D dfault pipeline
// set 0 - Transform : un UBO en vertex shader
vk::DescriptorSetLayoutBinding transform2DBinding{
0,
vk::DescriptorType::eUniformBuffer,
1,
vk::ShaderStageFlagBits::eVertex,
nullptr
};
transform2DLayout = vk::raii::DescriptorSetLayout(
device,
vk::DescriptorSetLayoutCreateInfo{{}, 1, &transform2DBinding}
);
// set 2 - Material : un UBO + deux samplers en fragment shader
std::array<vk::DescriptorSetLayoutBinding, 2> material2DBindings{{
{0, vk::DescriptorType::eUniformBuffer, 1, vk::ShaderStageFlagBits::eFragment, nullptr},
{1, vk::DescriptorType::eCombinedImageSampler, 1, vk::ShaderStageFlagBits::eFragment, nullptr}
}};
material2DLayout = vk::raii::DescriptorSetLayout(
device,
vk::DescriptorSetLayoutCreateInfo{{},
static_cast<uint32_t>(material2DBindings.size()),
material2DBindings.data()}
);
// set 2 - Projection : un UBO en vertex shader
vk::DescriptorSetLayoutBinding projBinding{
0, // binding
vk::DescriptorType::eUniformBuffer, // type
1, // count
vk::ShaderStageFlagBits::eVertex | vk::ShaderStageFlagBits::eFragment, // stage
nullptr
};
projection2DLayout = vk::raii::DescriptorSetLayout(
device,
vk::DescriptorSetLayoutCreateInfo{{}, 1, &projBinding}
);
std::array<vk::DescriptorSetLayout, 3> layouts2D{
*transform2DLayout,
*material2DLayout,
*projection2DLayout
};
vk::PipelineLayoutCreateInfo layout2DInfo{{},
static_cast<uint32_t>(layouts2D.size()),
layouts2D.data()
};
default2DPipelineLayoutInfo = vk::raii::PipelineLayout(device, layout2DInfo);
} }
//Fonction d'ajout de descriptor set qui regarde la taille de la pool, si la pool est dépassée, on ajoute une pool 2x plus grande //Fonction d'ajout de descriptor set qui regarde la taille de la pool, si la pool est dépassée, on ajoute une pool 2x plus grande
@@ -139,8 +139,14 @@ class VulkanImpl: public GraphicsAPI{
vk::raii::DescriptorSetLayout materialLayout = nullptr; // set 2 vk::raii::DescriptorSetLayout materialLayout = nullptr; // set 2
vk::raii::DescriptorSetLayout lightLayout = nullptr; // set 3 vk::raii::DescriptorSetLayout lightLayout = nullptr; // set 3
vk::raii::DescriptorSetLayout transform2DLayout = nullptr; // set 0
vk::raii::DescriptorSetLayout material2DLayout = nullptr; // set 1
vk::raii::DescriptorSetLayout projection2DLayout = nullptr; // set 2
DescriptorAllocator descriptorPoolManager; DescriptorAllocator descriptorPoolManager;
vk::raii::PipelineLayout defaultPipelineLayoutInfo = nullptr; vk::raii::PipelineLayout defaultPipelineLayoutInfo = nullptr;
vk::raii::PipelineLayout default2DPipelineLayoutInfo = nullptr;
vk::raii::Image depthImage = nullptr; vk::raii::Image depthImage = nullptr;
vk::raii::DeviceMemory depthImageMemory = nullptr; vk::raii::DeviceMemory depthImageMemory = nullptr;
@@ -198,6 +204,10 @@ class VulkanImpl: public GraphicsAPI{
vk::raii::DescriptorSetLayout& getMaterialLayout() { return materialLayout; } vk::raii::DescriptorSetLayout& getMaterialLayout() { return materialLayout; }
vk::raii::DescriptorSetLayout& getLightLayout() { return lightLayout; } vk::raii::DescriptorSetLayout& getLightLayout() { return lightLayout; }
vk::raii::DescriptorSetLayout& getTransform2DLayout() { return transform2DLayout; }
vk::raii::DescriptorSetLayout& getMaterial2DLayout() { return material2DLayout; }
vk::raii::DescriptorSetLayout& getProjection2DLayout() { return projection2DLayout; }
vk::raii::ImageView createImageView(vk::raii::Image& image, vk::Format format, vk::ImageAspectFlags aspectFlags); vk::raii::ImageView createImageView(vk::raii::Image& image, vk::Format format, vk::ImageAspectFlags aspectFlags);
void copyBuffer(VkBuffer src, VkBuffer dst, VkDeviceSize size); void copyBuffer(VkBuffer src, VkBuffer dst, VkDeviceSize size);
@@ -211,6 +221,7 @@ class VulkanImpl: public GraphicsAPI{
DescriptorAllocator& getDescriptorPoolManager(){return descriptorPoolManager;}; DescriptorAllocator& getDescriptorPoolManager(){return descriptorPoolManager;};
vk::raii::PipelineLayout& getDefaultPipelineLayout(){return defaultPipelineLayoutInfo;}; vk::raii::PipelineLayout& getDefaultPipelineLayout(){return defaultPipelineLayoutInfo;};
vk::raii::PipelineLayout& getDefault2DPipelineLayout(){return default2DPipelineLayoutInfo;};
void copyBufferToImage(const vk::raii::Buffer &buffer, vk::raii::Image &image, uint32_t width, uint32_t height); void copyBufferToImage(const vk::raii::Buffer &buffer, vk::raii::Image &image, uint32_t width, uint32_t height);
@@ -1,7 +1,12 @@
#include "CModelLoader.hpp" #include "CModelLoader.hpp"
#include <fstream>
#include "../API/GraphicsAPI.hpp" #include "../API/GraphicsAPI.hpp"
#include "../../Resources/API/CResourceAPI.hpp" #include "../../Resources/API/CResourceAPI.hpp"
#include "Core/Systems/Graphics/Data/Material/CMaterial2D.hpp"
#include "Core/Systems/Graphics/Data/Model/CModel2D.hpp"
#include "nlohmann/json_fwd.hpp"
#include <memory> #include <memory>
#include <string>
CModel* CModelLoader::loadModel(std::string fileName, const ModelLoadConfig& config) CModel* CModelLoader::loadModel(std::string fileName, const ModelLoadConfig& config)
{ {
@@ -190,3 +195,143 @@ CMaterial* CModelLoader::processMaterial(aiMaterial* mat, const std::string& dir
return ptr; return ptr;
} }
}*/ }*/
CosmicCore::CModel2D* CModelLoader::loadModel2D(std::string filename, const Model2DLoadConfig& config)
{
auto& rm = CResourceAPI::resources();
// Check cache first
auto cached = rm.models2D().get(filename);
if (cached) {
return cached.value();
}
// Load and parse JSON file
std::ifstream file(filename);
if (!file.is_open()) {
throw std::runtime_error("Failed to open 2D model file: " + filename);
}
nlohmann::json jsonData = nlohmann::json::parse(file);
std::vector<MeshMaterial2D> meshMaterials;
for(auto& mesh : jsonData["meshes"])
{
loadMesh2D(mesh, filename, meshMaterials, config);
}
// Create and register model2D
auto model2D = std::make_unique<CModel2D>(meshMaterials);
return rm.models2D().add(filename, std::move(model2D));
}
void CModelLoader::loadMesh2D(nlohmann::json& mesh, std::string filename, std::vector<CosmicCore::MeshMaterial2D>& meshes, const Model2DLoadConfig& config)
{
auto& rm = CResourceAPI::resources();
// Parse vertices
std::vector<Vertex2D> vertices;
if (mesh.contains("vertices") && mesh["vertices"].is_array()) {
for (const auto& v : mesh["vertices"]) {
Vertex2D vertex;
// Position (required: x, y)
vertex.m_position = glm::vec2(v["x"], v["y"]);
// TexCoords (optional, defaults to 0,0)
if (v.contains("u") && v.contains("v")) {
vertex.m_uv = glm::vec2(v["u"], v["v"]);
} else {
vertex.m_uv = glm::vec2(0.0f);
}
// Color (optional, defaults to white)
if (v.contains("r") && v.contains("g") && v.contains("b") && v.contains("a")) {
vertex.m_color = glm::vec4(v["r"], v["g"], v["b"], v["a"]);
} else {
vertex.m_color = glm::vec4(1.0f);
}
vertices.push_back(vertex);
}
}
// Parse indices
std::vector<uint32_t> indices;
if (mesh.contains("indices") && mesh["indices"].is_array()) {
for (const auto& i : mesh["indices"]) {
indices.push_back(i.get<uint32_t>());
}
}
if (vertices.empty() || indices.empty()) {
throw std::runtime_error("Invalid 2D model file: missing vertices or indices in " + filename);
}
// Create mesh key
std::string meshKey = filename + "_" + std::to_string(meshes.size()) + "_mesh2d";
// Create and setup CMesh2D
auto mesh2D = std::make_unique<CMesh2D>();
mesh2D->setVertices(vertices);
mesh2D->setIndexes(indices);
mesh2D->load();
CMesh2D* meshPtr = rm.meshes2D().add(meshKey, std::move(mesh2D));
CMaterial2D* matPtr = loadMaterial2D(mesh["material"], filename, config);
meshes.push_back({meshPtr, matPtr});
}
CosmicCore::CMaterial2D* CModelLoader::loadMaterial2D(nlohmann::json& material, std::string filename, const Model2DLoadConfig& config)
{
auto& rm = CResourceAPI::resources();
// Create material2D
CMaterial2D* material2D = nullptr;
std::string matKey = filename + "_mat2d";
auto cachedMat = rm.materials2D().get(matKey);
if (!cachedMat) {
auto mat = std::make_unique<CMaterial2D>();
// Parse material from JSON
if (material.contains("material")) {
auto& matJson = material["material"];
if (matJson.contains("color")) {
auto& color = matJson["color"];
mat->m_color = glm::vec4(
color.value("r", 1.0f),
color.value("g", 1.0f),
color.value("b", 1.0f),
color.value("a", 1.0f)
);
}
if (matJson.contains("alpha_blend")) {
mat->m_alphaBlend = matJson["alpha_blend"].get<bool>();
}
if (matJson.contains("texture")) {
std::string texPath = matJson["texture"];
mat->m_texture = rm.textures().loadTexture(texPath);
}
}
// Get shader from config
auto shader = rm.shaders().get(config.shaderName);
if (!shader) {
throw std::runtime_error("Shader not found: " + config.shaderName);
}
mat->shader = static_cast<CShaderImplVulkan*>(shader);
mat->build();
material2D = rm.materials2D().add(matKey, std::move(mat));
} else {
material2D = cachedMat.value();
}
return material2D;
}
@@ -6,8 +6,11 @@
#include <assimp/scene.h> #include <assimp/scene.h>
#include <assimp/postprocess.h> #include <assimp/postprocess.h>
#include "Core/Systems/Graphics/Data/Material/CMaterial2D.hpp"
#include "Core/Systems/Graphics/Data/Model/CModel2D.hpp"
#include "Model/CModel.hpp" #include "Model/CModel.hpp"
#include "Texture/CTexture.hpp" #include "Texture/CTexture.hpp"
#include "nlohmann/json_fwd.hpp"
struct ModelLoadConfig { struct ModelLoadConfig {
std::string shaderName = "triangle"; std::string shaderName = "triangle";
@@ -17,6 +20,14 @@ struct ModelLoadConfig {
bool forceReload = false; bool forceReload = false;
}; };
struct Model2DLoadConfig {
std::string shaderName = "ui";
// override des materials par index de mesh
//std::unordered_map<uint32_t, CosmicCore::CMaterial2D*> materialOverrides;
// si true, recharge même si déjà en cache
//bool forceReload = false;
};
/** /**
* @brief Class allowing to load models from obj files. * @brief Class allowing to load models from obj files.
*/ */
@@ -51,6 +62,10 @@ private:
static CMaterial* processMaterial(aiMaterial* mat, const std::string& directory, const ModelLoadConfig& config); static CMaterial* processMaterial(aiMaterial* mat, const std::string& directory, const ModelLoadConfig& config);
static CModel* cloneWithOverrides(CModel* original, const std::string& originalKey, const ModelLoadConfig& config); static CModel* cloneWithOverrides(CModel* original, const std::string& originalKey, const ModelLoadConfig& config);
static void loadMesh2D(nlohmann::json& mesh, std::string filename, std::vector<CosmicCore::MeshMaterial2D>& meshes, const Model2DLoadConfig& config = {});
static CosmicCore::CMaterial2D* loadMaterial2D(nlohmann::json& material, std::string filename, const Model2DLoadConfig& config = {});
public: public:
/** /**
@@ -60,6 +75,7 @@ public:
* @return A dynamically allocated CModel. * @return A dynamically allocated CModel.
*/ */
static CModel* loadModel(std::string filename, const ModelLoadConfig& config = {}); static CModel* loadModel(std::string filename, const ModelLoadConfig& config = {});
static CosmicCore::CModel2D* loadModel2D(std::string filename, const Model2DLoadConfig& config = {});
}; };
@@ -0,0 +1,76 @@
// CFont.cpp
#include "CFont.hpp"
#include "Core/Systems/Resources/API/CResourceAPI.hpp"
#include <nlohmann/json.hpp>
#include <fstream>
#include <iostream>
namespace CosmicCore {
void CFont::init(const std::string& jsonPath, const std::string& atlasPath) {
// charge l'atlas comme texture
auto& rm = CResourceAPI::resources().textures();
m_atlas = rm.loadTexture(atlasPath);
// parse le JSON
std::ifstream file(jsonPath);
if (!file.good())
throw std::runtime_error("Font JSON not found: " + jsonPath);
nlohmann::json j = nlohmann::json::parse(file);
// métriques globales
if (j.contains("metrics")) {
auto& m = j["metrics"];
m_metrics.emSize = m.value("emSize", 1.0f);
m_metrics.lineHeight = m.value("lineHeight", 1.0f);
m_metrics.ascender = m.value("ascender", 1.0f);
m_metrics.descender = m.value("descender", 0.0f);
}
// dimensions de l'atlas
if (j.contains("atlas")) {
m_atlasWidth = j["atlas"].value("width", 512u);
m_atlasHeight = j["atlas"].value("height", 512u);
}
// glyphes
if (!j.contains("glyphs")) return;
for (auto& g : j["glyphs"]) {
SGlyph glyph{};
glyph.unicode = g.value("unicode", 0u);
glyph.advance = g.value("advance", 0.0f);
if (g.contains("atlasBounds")) {
auto& ab = g["atlasBounds"];
float atlasW = (float)m_atlasWidth;
float atlasH = (float)m_atlasHeight;
glyph.atlasMin = {ab["left"].get<float>() / atlasW,
ab["bottom"].get<float>() / atlasH};
glyph.atlasMax = {ab["right"].get<float>() / atlasW,
ab["top"].get<float>() / atlasH};
}
if (g.contains("planeBounds")) {
auto& pb = g["planeBounds"];
glyph.planeMin = {pb["left"].get<float>(),
pb["bottom"].get<float>()};
glyph.planeMax = {pb["right"].get<float>(),
pb["top"].get<float>()};
}
m_glyphs[glyph.unicode] = glyph;
}
}
const SGlyph* CFont::getGlyph(uint32_t unicode) const {
auto it = m_glyphs.find(unicode);
if (it != m_glyphs.end()) return &it->second;
// fallback sur '?' si le glyphe n'existe pas
auto fallback = m_glyphs.find('?');
if (fallback != m_glyphs.end()) return &fallback->second;
return nullptr;
}
} // namespace CosmicCore
@@ -0,0 +1,57 @@
#ifndef CFONT_HPP
#define CFONT_HPP
#include <string>
#include <unordered_map>
#include <glm/glm.hpp>
#include "../Texture/CTexture.hpp"
namespace CosmicCore {
struct SGlyph {
uint32_t unicode;
float advance; // largeur pour avancer le curseur
// position dans l'atlas (UV)
glm::vec2 atlasMin; // UV coin bas-gauche
glm::vec2 atlasMax; // UV coin haut-droit
// position relative au curseur (plane bounds)
glm::vec2 planeMin; // offset bas-gauche
glm::vec2 planeMax; // offset haut-droit
};
struct SFontMetrics {
float emSize = 1.0f;
float lineHeight = 1.0f;
float ascender = 1.0f;
float descender = 0.0f;
};
class CFont {
std::unordered_map<uint32_t, SGlyph> m_glyphs;
CTexture* m_atlas;
SFontMetrics m_metrics;
uint32_t m_atlasWidth = 0;
uint32_t m_atlasHeight = 0;
public:
CFont() = default;
~CFont() = default;
CFont(const CFont&) = delete;
CFont& operator=(const CFont&) = delete;
CFont(CFont&&) = default;
CFont& operator=(CFont&&) = default;
void init(const std::string& jsonPath, const std::string& atlasPath);
const SGlyph* getGlyph(uint32_t unicode) const;
CTexture* getAtlas() const { return m_atlas; }
SFontMetrics getMetrics() const { return m_metrics; }
uint32_t getAtlasWidth() const { return m_atlasWidth; }
uint32_t getAtlasHeight() const { return m_atlasHeight; }
};
} // namespace CosmicCore
#endif
@@ -1,111 +0,0 @@
/*#include "CTextTexture.hpp"
CTextTexture::CTextTexture(ETextureType type, std::string filePath, std::string text, unsigned int fontSize, glm::vec3 fontColor, glm::bvec4 fontStyle) :
CAbstractTexture(type),
m_fontFilePath(filePath),
m_renderText(text),
m_fontSize(fontSize),
m_fontColor(fontColor),
m_fontStyle(fontStyle) {
}
std::string CTextTexture::getFontFilePath(void) {
return m_fontFilePath;
}
void CTextTexture::setFontFilePath(std::string filePath) {
m_fontFilePath = filePath;
}
std::string CTextTexture::getText(void) {
return m_renderText;
}
void CTextTexture::setText(std::string text) {
m_renderText = text;
}
void CTextTexture::init(void) {
// Read the font file.
TTF_Font* font = TTF_OpenFont(m_fontFilePath.c_str(), m_fontSize);
SDL_Color color;
color.r = m_fontColor.x / 255u;
color.g = m_fontColor.y / 255u;
color.b = m_fontColor.z / 255u;
int style = TTF_STYLE_NORMAL;
if (m_fontStyle.x) {
style |= TTF_STYLE_BOLD;
}
if (m_fontStyle.y) {
style |= TTF_STYLE_ITALIC;
}
if (m_fontStyle.z) {
style |= TTF_STYLE_UNDERLINE;
}
if (m_fontStyle.z) {
style |= TTF_STYLE_STRIKETHROUGH;
}
TTF_SetFontStyle(font, style);
SDL_Surface* sdlSurface = TTF_RenderText_Blended(font, m_renderText.c_str(), color);
if (sdlSurface == NULL) {
throw CLibException(std::string("Can not render the text : ") + std::string(SDL_GetError()));
}
// Create the id.
unsigned int id;
glGenTextures(1, &id);
setId(id);
// Image format.
GLenum internalFormat(0);
GLenum externalFormat(0);
if (sdlSurface->format->BytesPerPixel == 3) {
// We use RGB as internal format.
internalFormat = GL_RGB;
// Choose the external format.
if (sdlSurface->format->Rmask == 0xff)
externalFormat = GL_RGB;
else
externalFormat = GL_BGR;
}
else if (sdlSurface->format->BytesPerPixel == 4) {
// We use RGBA as internal format.
internalFormat = GL_RGBA;
// Choose the external format.
if (sdlSurface->format->Rmask == 0xff)
externalFormat = GL_RGBA;
else
externalFormat = GL_BGRA;
}
else {
SDL_FreeSurface(sdlSurface);
throw CRuntimeException("Unknow image internal format.");
}
// Lock the texture to use it.
glBindTexture(GL_TEXTURE_2D, getId());
// Fill the GL texture.
glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, sdlSurface->w, sdlSurface->h, 0, externalFormat, GL_UNSIGNED_BYTE, sdlSurface->pixels);
// Set filters : the near texture have a linear filter.
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
// The far texture have a nearest filter, meaning no filter.
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
// Unlock the texture.
glBindTexture(GL_TEXTURE_2D, 0);
// Free the font.
TTF_CloseFont(font);
// Free the surface.
SDL_FreeSurface(sdlSurface);
}*/
@@ -1,47 +0,0 @@
/*#ifndef CTEXTTEXTURE_HPP
#define CTEXTTEXTURE_HPP
#include "../../../Controller/Exception/CLibException.hpp"
#include "../../../Controller/Exception/CRuntimeException.hpp"
#include "../../../Controller/Exception/CLogicException.hpp"
#include "CAbstractTexture.hpp"
#include <string>
#include <SDL.h>
#include <glm/glm.hpp>
#include <SDL_ttf.h>
#ifdef WIN32
#include <gl/glew.h>
#else
#include <GL/glew.h>
#endif
class CTextTexture : CAbstractTexture {
private:
// Path of the file.
std::string m_fontFilePath;
// The size of the font.
unsigned int m_fontSize;
// The color of the font.
glm::vec3 m_fontColor;
// The style of the font (x is bold, y is italic, z is underline, w is strikethrough).
glm::bvec4 m_fontStyle;
// The text to render.
std::string m_renderText;
public:
CTextTexture(void) = delete;
CTextTexture(ETextureType type, std::string filePath, std::string text, unsigned int fontSize, glm::vec3 fontColor, glm::bvec4 fontStyle);
~CTextTexture() {};
std::string getFontFilePath(void);
void setFontFilePath(std::string filePath);
std::string getText(void);
void setText(std::string text);
virtual void init(void);
};
#endif*/
@@ -35,7 +35,7 @@ class CLightsBuffer {
public: public:
CLightsBuffer() = default; CLightsBuffer() = default;
~CLightsBuffer() { destroy(); } ~CLightsBuffer() { }//destroy(); }
CLightsBuffer(const CLightsBuffer&) = delete; CLightsBuffer(const CLightsBuffer&) = delete;
CLightsBuffer& operator=(const CLightsBuffer&) = delete; CLightsBuffer& operator=(const CLightsBuffer&) = delete;
@@ -0,0 +1,149 @@
#include "CMaterial2D.hpp"
#include "../../../Resources/API/CResourceAPI.hpp"
#include "../../Shader/Implementations/CShaderImplVulkan.hpp"
#include "Core/Systems/Graphics/API/VulkanImplementation/VulkanImpl.hpp"
#include <glm/gtc/matrix_transform.hpp>
namespace CosmicCore {
void CMaterial2D::build() {
if(isInit)
{
destroy();
}
VulkanImpl* api = dynamic_cast<VulkanImpl*>(GraphicsAPI::getAPI().get());
auto* device= static_cast<vk::raii::Device*>(api->getDevice());
auto shaderStages = shader->getShaderStages(0, vk::ShaderStageFlagBits::eVertex, vk::ShaderStageFlagBits::eFragment);
auto bindingDescription = Vertex2D::getBindingDescription();
auto attributeDescriptions = Vertex2D::getAttributeDescriptions();
vk::PipelineVertexInputStateCreateInfo vertexInputInfo{{}, 1, &bindingDescription, static_cast<uint32_t>(attributeDescriptions.size()), attributeDescriptions.data()};
vk::PipelineInputAssemblyStateCreateInfo inputAssembly{{},vk::PrimitiveTopology::eTriangleList};
vk::PipelineViewportStateCreateInfo viewportState{{},1, {},1};
vk::PipelineRasterizationStateCreateInfo rasterizer{{},vk::False, vk::False, vk::PolygonMode::eFill,vk::CullModeFlagBits::eBack, vk::FrontFace::eCounterClockwise, vk::False, {}, {}, 1.0f, 1.0f};
vk::PipelineMultisampleStateCreateInfo multisampling{{}, vk::SampleCountFlagBits::e1, vk::False};
vk::PipelineColorBlendAttachmentState colorBlendAttachment{vk::False, {}, {}, {}, {}, {}, {}, vk::ColorComponentFlagBits::eR | vk::ColorComponentFlagBits::eG | vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eA};
vk::PipelineColorBlendStateCreateInfo colorBlending{{},vk::False, vk::LogicOp::eCopy, 1, &colorBlendAttachment};
vk::PipelineDepthStencilStateCreateInfo depthStencil{{},
vk::True,
vk::True,
vk::CompareOp::eLess,
vk::False,
vk::False};
std::vector dynamicStates = {
vk::DynamicState::eViewport,
vk::DynamicState::eScissor};
vk::PipelineDynamicStateCreateInfo dynamicState{{}, static_cast<uint32_t>(dynamicStates.size()), dynamicStates.data()};
std::array<vk::DescriptorSetLayout, 3> layouts{
*api->getTransform2DLayout(), // set 0
*api->getMaterial2DLayout(), // set 1
*api->getProjection2DLayout(), // set 2
};
vk::PipelineLayoutCreateInfo pipelineLayoutInfo{{},3,layouts.data(), 0};
pipelineLayout = vk::raii::PipelineLayout(*static_cast<vk::raii::Device*>(api->getDevice()), pipelineLayoutInfo);
vk::StructureChain<vk::GraphicsPipelineCreateInfo, vk::PipelineRenderingCreateInfo> pipelineCreateInfoChain = {
{{},
2,
shaderStages.data(),
&vertexInputInfo,
&inputAssembly,
{},
&viewportState,
&rasterizer,
&multisampling,
&depthStencil,
&colorBlending,
&dynamicState,
pipelineLayout,
nullptr
},
{{},
1,
&api->getSwapChainFormat().format,
api->findDepthFormat()
}
};
pipeline = vk::raii::Pipeline(*static_cast<vk::raii::Device*>(api->getDevice()), nullptr, pipelineCreateInfoChain.get<vk::GraphicsPipelineCreateInfo>());
// descriptor sets du material (set 2)
for (uint32_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
m_descriptorSets[i] = api->getDescriptorPoolManager().allocate(
*api->getMaterial2DLayout()
);
std::vector<vk::WriteDescriptorSet> writes;
// binding 1 : albedo (si présent)
vk::DescriptorImageInfo albedoInfo;
if (m_texture) {
albedoInfo = {
*m_texture->getSampler(),
*m_texture->getImageView(),
vk::ImageLayout::eShaderReadOnlyOptimal
};
writes.push_back({
*m_descriptorSets[i].set,
1, 0, 1,
vk::DescriptorType::eCombinedImageSampler,
&albedoInfo
});
}
else if (m_font) {
albedoInfo = {
*m_font->getAtlas()->getSampler(),
*m_font->getAtlas()->getImageView(),
vk::ImageLayout::eShaderReadOnlyOptimal
};
writes.push_back({
*m_descriptorSets[i].set,
1, 0, 1,
vk::DescriptorType::eCombinedImageSampler,
&albedoInfo
});
}
else {
albedoInfo = {
api->getDefaultTexture()->getSampler(),
api->getDefaultTexture()->getImageView(),
vk::ImageLayout::eShaderReadOnlyOptimal
};
writes.push_back({
*m_descriptorSets[i].set,
1, 0, 1,
vk::DescriptorType::eCombinedImageSampler,
&albedoInfo
});
}
if (!writes.empty())
device->updateDescriptorSets(writes, {});
}
isInit = true;
}
void CMaterial2D::destroy() {
VulkanImpl* api = dynamic_cast<VulkanImpl*>(GraphicsAPI::getAPI().get());
api->destroyPipeline(pipeline, pipelineLayout);
// descriptor sets
for (uint32_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
api->destroyDescriptorSet(m_descriptorSets[i], i);
}
}
} // namespace CosmicCore
@@ -0,0 +1,48 @@
#ifndef CUIPIPELINE_HPP
#define CUIPIPELINE_HPP
#include "Core/Systems/Graphics/API/VulkanImplementation/Constants.hpp"
#include "Core/Systems/Graphics/API/VulkanImplementation/ManagedDescriptorSet.hpp"
#include "Core/Systems/Graphics/Data/Font/CFont.hpp"
#include "Core/Systems/Graphics/Data/Texture/CTexture.hpp"
#include "Core/Systems/Graphics/Shader/Implementations/CShaderImplVulkan.hpp"
#include <vulkan/vulkan_raii.hpp>
namespace CosmicCore {
class CMaterial2D {
private:
public:
glm::vec4 m_color = {1, 1, 1, 1};
CTexture* m_texture = nullptr;
CFont* m_font = nullptr;
bool m_alphaBlend = true;
bool isInit = false;
CTexture* texture = nullptr;
CShaderImplVulkan* shader;
vk::raii::PipelineLayout pipelineLayout = nullptr;
vk::raii::Pipeline pipeline = nullptr;
std::array<ManagedDescriptorSet, MAX_FRAMES_IN_FLIGHT> m_descriptorSets;
void build();
void destroy();
vk::raii::Pipeline& getPipeline() { return pipeline; }
vk::raii::PipelineLayout& getPipelineLayout() { return pipelineLayout; }
vk::raii::DescriptorSet& getDescriptorSet(uint32_t frameIndex) {
return m_descriptorSets[frameIndex].set;
}
CMaterial2D() = default;
~CMaterial2D() { destroy(); }
CMaterial2D(CMaterial2D&&) = default;
CMaterial2D& operator=(CMaterial2D&&) = default;
CMaterial2D(const CMaterial2D&) = delete;
CMaterial2D& operator=(const CMaterial2D&) = delete;
};
}
#endif
@@ -14,8 +14,6 @@ void CMesh::destroy()
{ {
VulkanImpl* api = dynamic_cast<VulkanImpl*>(GraphicsAPI::getAPI().get()); VulkanImpl* api = dynamic_cast<VulkanImpl*>(GraphicsAPI::getAPI().get());
api->destroyBuffer(vertexIndexBuffer, api->getCurrentFrameIndex()); api->destroyBuffer(vertexIndexBuffer, api->getCurrentFrameIndex());
/*if (api && vertexIndexBuffer.buffer != VK_NULL_HANDLE)
vmaDestroyBuffer(api->getAllocator(), vertexIndexBuffer.buffer, vertexIndexBuffer.allocation);*/
} }
std::vector<SVertex>& CMesh::getVertices(void) { std::vector<SVertex>& CMesh::getVertices(void) {
return m_vertexes; return m_vertexes;
@@ -34,22 +32,6 @@ std::vector<uint32_t>& CMesh::getIndexes(void){
return m_indexes; return m_indexes;
} }
/*void CMesh::load(void) {
vk::BufferCreateInfo bufferInfo{{},sizeof(m_vertexes[0]) * m_vertexes.size(), vk::BufferUsageFlagBits::eVertexBuffer, vk::SharingMode::eExclusive};
VulkanImpl* api = dynamic_cast<VulkanImpl*>(GraphicsAPI::getAPI().get());
vertexBuffer = vk::raii::Buffer(*static_cast<vk::raii::Device*>(api->getDevice()), bufferInfo);
vk::MemoryRequirements memRequirements = vertexBuffer.getMemoryRequirements();
vk::MemoryAllocateInfo memoryAllocateInfo{memRequirements.size, api->findMemoryType(memRequirements.memoryTypeBits, vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent)};
vertexBufferMemory = vk::raii::DeviceMemory(*static_cast<vk::raii::Device*>(api->getDevice()), memoryAllocateInfo);
vertexBuffer.bindMemory(*vertexBufferMemory, 0);
void *data = vertexBufferMemory.mapMemory(0, bufferInfo.size);
memcpy(data, m_vertexes.data(), bufferInfo.size);
vertexBufferMemory.unmapMemory();
}*/
void CMesh::load(void) { void CMesh::load(void) {
VulkanImpl* api = dynamic_cast<VulkanImpl*>(GraphicsAPI::getAPI().get()); VulkanImpl* api = dynamic_cast<VulkanImpl*>(GraphicsAPI::getAPI().get());
VmaAllocator allocator = api->getAllocator(); VmaAllocator allocator = api->getAllocator();
@@ -101,7 +83,3 @@ void CMesh::load(void) {
// 5. détruire le staging buffer // 5. détruire le staging buffer
vmaDestroyBuffer(allocator, stagingBuffer.buffer, stagingBuffer.allocation); vmaDestroyBuffer(allocator, stagingBuffer.buffer, stagingBuffer.allocation);
} }
/*void CMesh::draw(glm::mat4 model, glm::mat4 view, glm::mat4 projection, glm::vec3 lightPos, float intensity) {
}*/
@@ -21,8 +21,6 @@ private:
VkDeviceSize m_indexOffset = 0; VkDeviceSize m_indexOffset = 0;
uint32_t m_indexCount = 0; uint32_t m_indexCount = 0;
//CMaterial* m_material;
public: public:
CMesh(void); CMesh(void);
@@ -35,13 +33,8 @@ public:
void setVertices(std::vector<SVertex> vertices); void setVertices(std::vector<SVertex> vertices);
void setIndexes(std::vector<uint32_t> indexes); void setIndexes(std::vector<uint32_t> indexes);
//void setMaterial(CMaterial* mat){m_material = mat;};
void load(void); void load(void);
//void draw(glm::mat4 model, glm::mat4 view, glm::mat4 projection, glm::vec3 lightPos, float intensity);
//CMaterial* getMaterial(){return m_material;};
VMABuffer& getVertexIndexBuffer(){return vertexIndexBuffer;}; VMABuffer& getVertexIndexBuffer(){return vertexIndexBuffer;};
VkDeviceSize getVertexOffset(){return m_vertexOffset;} VkDeviceSize getVertexOffset(){return m_vertexOffset;}
VkDeviceSize getIndexOffset(){return m_indexOffset;}; VkDeviceSize getIndexOffset(){return m_indexOffset;};
@@ -0,0 +1,157 @@
#include "CMesh2D.hpp"
#include "../../API/VulkanImplementation/VulkanImpl.hpp"
#include "Core/Systems/Graphics/Data/Mesh/SVertex.hpp"
#include <vulkan/vulkan_core.h>
#include <vulkan/vulkan_raii.hpp>
namespace CosmicCore {
CMesh2D::CMesh2D(void) :
m_vertexes() {
}
CMesh2D::~CMesh2D(void) {
destroy();
}
void CMesh2D::destroy()
{
VulkanImpl* api = dynamic_cast<VulkanImpl*>(GraphicsAPI::getAPI().get());
api->destroyBuffer(vertexIndexBuffer, api->getCurrentFrameIndex());
}
std::vector<Vertex2D>& CMesh2D::getVertices(void) {
return m_vertexes;
}
void CMesh2D::setVertices(std::vector<Vertex2D> vertices)
{
m_vertexes = vertices;
}
void CMesh2D::setIndexes(std::vector<uint32_t> indexes){
m_indexes = indexes;
}
std::vector<uint32_t>& CMesh2D::getIndexes(void){
return m_indexes;
}
void CMesh2D::load(void) {
VulkanImpl* api = dynamic_cast<VulkanImpl*>(GraphicsAPI::getAPI().get());
VmaAllocator allocator = api->getAllocator();
VkDeviceSize vertexSize = sizeof(m_vertexes[0]) * m_vertexes.size();
VkDeviceSize indexSize = sizeof(m_indexes[0]) * m_indexes.size();
VkDeviceSize totalSize = vertexSize + indexSize;
// 1. staging buffer - CPU visible, temporaire
VkBufferCreateInfo stagingBufferInfo{};
stagingBufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
stagingBufferInfo.size = totalSize;
stagingBufferInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
VmaAllocationCreateInfo stagingAllocInfo{};
stagingAllocInfo.usage = VMA_MEMORY_USAGE_CPU_ONLY;
stagingAllocInfo.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT;
VMABuffer stagingBuffer;
VmaAllocationInfo stagingInfo{};
vmaCreateBuffer(allocator, &stagingBufferInfo, &stagingAllocInfo,
&stagingBuffer.buffer, &stagingBuffer.allocation, &stagingInfo);
// 2. copie des données CPU → staging
memcpy(stagingInfo.pMappedData, m_vertexes.data(), vertexSize);
memcpy((char*)stagingInfo.pMappedData + vertexSize, m_indexes.data(), indexSize);
vmaFlushAllocation(allocator, stagingBuffer.allocation, 0, VK_WHOLE_SIZE);
// 3. vertex buffer final - DEVICE_LOCAL, rapide
VkBufferCreateInfo vertexBufferInfo{};
vertexBufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
vertexBufferInfo.size = totalSize;
vertexBufferInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT
| VK_BUFFER_USAGE_INDEX_BUFFER_BIT
| VK_BUFFER_USAGE_TRANSFER_DST_BIT;
VmaAllocationCreateInfo vertexAllocInfo{};
vertexAllocInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
vmaCreateBuffer(allocator, &vertexBufferInfo, &vertexAllocInfo,
&vertexIndexBuffer.buffer, &vertexIndexBuffer.allocation, nullptr);
// 4. copie GPU staging → vertex buffer via command buffer
api->copyBuffer(stagingBuffer.buffer, vertexIndexBuffer.buffer, totalSize);
m_vertexOffset = 0;
m_indexOffset = vertexSize;
m_indexCount = m_indexes.size();
// 5. détruire le staging buffer
vmaDestroyBuffer(allocator, stagingBuffer.buffer, stagingBuffer.allocation);
}
glm::vec2 CMesh2D::buildFromText(CFont* font, const std::string& text)
{
//destroy check before load if text is edited ?
if (!font || text.empty()) {
setVertices({});
setIndexes({});
return {0.0f, 0.0f};
}
std::vector<Vertex2D> vertices;
std::vector<uint32_t> indices;
float scale = font->getMetrics().emSize;
float cursorX = 0.0f;
float cursorY = 0.0f;
float maxWidth = 0.0f;
int lineCount = 1;
for (char c : text) {
if (c == '\n') {
maxWidth = std::max(maxWidth, cursorX);
cursorX = 0.0f;
cursorY += font->getMetrics().lineHeight * scale;
lineCount++;
continue;
}
const SGlyph* glyph = font->getGlyph((uint32_t)c);
if (!glyph) continue;
// positions des coins du quad (espace local au mesh)
glm::vec2 p0 = {
cursorX + glyph->planeMin.x * scale,
cursorY - glyph->planeMax.y * scale
};
glm::vec2 p1 = {
cursorX + glyph->planeMax.x * scale,
cursorY - glyph->planeMin.y * scale
};
// UVs dans l'atlas — flip V pour Vulkan
glm::vec2 uv0 = {glyph->atlasMin.x, 1.0f - glyph->atlasMax.y};
glm::vec2 uv1 = {glyph->atlasMax.x, 1.0f - glyph->atlasMin.y};
uint32_t base = (uint32_t)vertices.size();
vertices.push_back({{p0.x, p0.y}, {uv0.x, uv0.y}, {1, 1, 1, 1}});
vertices.push_back({{p1.x, p0.y}, {uv1.x, uv0.y}, {1, 1, 1, 1}});
vertices.push_back({{p1.x, p1.y}, {uv1.x, uv1.y}, {1, 1, 1, 1}});
vertices.push_back({{p0.x, p1.y}, {uv0.x, uv1.y}, {1, 1, 1, 1}});
indices.insert(indices.end(),
{base, base+1, base+2, base+2, base+3, base});
cursorX += glyph->advance * scale;
}
maxWidth = std::max(maxWidth, cursorX);
float totalHeight = lineCount * font->getMetrics().lineHeight * scale;
setVertices(vertices);
setIndexes(indices);
load(); // upload GPU
return {maxWidth, totalHeight};
}
}
@@ -0,0 +1,43 @@
#ifndef CMESH2D_HPP
#define CMESH2D_HPP
#include "Core/Systems/Graphics/API/VulkanImplementation/VMABuffer.hpp"
#include "Core/Systems/Graphics/Data/Font/CFont.hpp"
#include "Core/Systems/Graphics/Data/Mesh/SVertex.hpp"
namespace CosmicCore {
class CMesh2D
{
private:
std::vector<Vertex2D> m_vertexes;
std::vector<uint32_t> m_indexes;
VMABuffer vertexIndexBuffer;
VkDeviceSize m_vertexOffset = 0;
VkDeviceSize m_indexOffset = 0;
uint32_t m_indexCount = 0;
public:
CMesh2D(void);
~CMesh2D(void);
std::vector<Vertex2D>& getVertices(void);
std::vector<uint32_t>& getIndexes(void);
void setVertices(std::vector<Vertex2D> vertices);
void setIndexes(std::vector<uint32_t> indexes);
void load(void);
VMABuffer& getVertexIndexBuffer(){return vertexIndexBuffer;};
VkDeviceSize getVertexOffset(){return m_vertexOffset;}
VkDeviceSize getIndexOffset(){return m_indexOffset;};
uint32_t getIndexCount(){return m_indexCount;};
void destroy();
glm::vec2 buildFromText(CFont* font, const std::string& text);
};
}
#endif
@@ -67,4 +67,30 @@ typedef struct SVertex{
} Vertex; } Vertex;
/**
* @brief the struct Vertex, use to represent vertex and vertex attribute.
*/
typedef struct SVertex2D{
glm::vec2 m_position;
glm::vec2 m_uv;
glm::vec4 m_color;
static vk::VertexInputBindingDescription getBindingDescription() {
return { 0, sizeof(SVertex2D), vk::VertexInputRate::eVertex };
}
static std::array<vk::VertexInputAttributeDescription, 3> getAttributeDescriptions() {
return {{
{0, 0, vk::Format::eR32G32Sfloat, offsetof(SVertex2D, m_position)},
{1, 0, vk::Format::eR32G32Sfloat, offsetof(SVertex2D, m_uv)},
{2, 0, vk::Format::eR32G32B32A32Sfloat, offsetof(SVertex2D, m_color)}
}};
}
} Vertex2D;
#endif #endif
@@ -8,22 +8,6 @@ CModel::CModel(std::vector<MeshMaterial> meshes) :
CModel::~CModel(void) { CModel::~CModel(void) {
} }
/*void CModel::load(void) {
// For each meshes of the model.
for (unsigned int i = 0; i < m_meshes.size(); i++) {
m_meshes[i]->load();
}
m_loaded = true;
}*/
/*void CModel::draw(glm::mat4 model, glm::mat4 view, glm::mat4 projection, glm::vec3 lightPos, float intensity) {
// For each meshes of the model.
for (unsigned int i = 0; i < m_meshes.size(); i++) {
m_meshes[i]->draw(model, view, projection, lightPos, intensity);
}
}*/
std::vector<MeshMaterial>& CModel::getMeshMaterials() std::vector<MeshMaterial>& CModel::getMeshMaterials()
{ {
return m_meshes; return m_meshes;
@@ -0,0 +1,28 @@
#include "CModel2D.hpp"
namespace CosmicCore {
CModel2D::CModel2D(std::vector<MeshMaterial2D> meshes) :
m_meshes(meshes),
m_loaded(false) {
}
CModel2D::~CModel2D(void) {
}
std::vector<MeshMaterial2D>& CModel2D::getMeshMaterials()
{
return m_meshes;
}
void CModel2D::setMeshMaterials(std::vector<MeshMaterial2D> meshes)
{
m_meshes = meshes;
}
bool CModel2D::isLoaded()
{
return m_loaded;
}
}
@@ -0,0 +1,36 @@
#ifndef CMODEL2D_HPP
#define CMODEL2D_HPP
#include "Core/Systems/Graphics/Data/Material/CMaterial2D.hpp"
#include "Core/Systems/Graphics/Data/Mesh/CMesh2D.hpp"
namespace CosmicCore {
struct MeshMaterial2D{
CMesh2D* mesh = nullptr;
CMaterial2D* material = nullptr;
};
class CModel2D {
private:
std::vector<MeshMaterial2D> m_meshes;
bool m_loaded;
public:
CModel2D(void) = delete;
CModel2D(std::vector<MeshMaterial2D> meshes);
~CModel2D(void);
std::vector<MeshMaterial2D>& getMeshMaterials(void);
void setMeshMaterials(std::vector<MeshMaterial2D> meshes);
bool isLoaded(void);
};
}
#endif
@@ -1,6 +1,7 @@
#include "CTexture.hpp" #include "CTexture.hpp"
#include "../../API/VulkanImplementation/VulkanImpl.hpp" #include "../../API/VulkanImplementation/VulkanImpl.hpp"
#include <iostream>
CTexture::CTexture(std::string filePath) : CTexture::CTexture(std::string filePath) :
m_filePath(filePath) { m_filePath(filePath) {
@@ -20,9 +21,8 @@ void CTexture::init(void) {
// Read the image file. // Read the image file.
SDL_Surface* sdlSurface = IMG_Load(m_filePath.c_str()); SDL_Surface* sdlSurface = IMG_Load(m_filePath.c_str());
if(sdlSurface == nullptr) if (!sdlSurface) {
{ throw std::runtime_error("Failed to load: " + m_filePath);
//error here
} }
SDL_PixelFormat sdlFormat = sdlSurface->format; SDL_PixelFormat sdlFormat = sdlSurface->format;
@@ -50,7 +50,7 @@ void CTexture::init(void) {
m_height = converted->h; m_height = converted->h;
VkDeviceSize imageSize = m_width * m_height * 4; VkDeviceSize imageSize = m_width * m_height * 4;
// 2. staging buffer // staging buffer
VkBufferCreateInfo stagingBufferInfo{}; VkBufferCreateInfo stagingBufferInfo{};
stagingBufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; stagingBufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
stagingBufferInfo.size = imageSize; stagingBufferInfo.size = imageSize;
@@ -69,7 +69,7 @@ void CTexture::init(void) {
// Free the surface. // Free the surface.
SDL_DestroySurface(converted); SDL_DestroySurface(converted);
// 3. crée l'image GPU // crée l'image GPU
api->createImage( api->createImage(
m_width, m_height, m_width, m_height,
m_format, m_format,
@@ -80,7 +80,7 @@ void CTexture::init(void) {
m_textureImageMemory m_textureImageMemory
); );
// 4. transitions et copie // transitions et copie
api->transitionImageLayout(m_textureImage, api->transitionImageLayout(m_textureImage,
vk::ImageLayout::eUndefined, vk::ImageLayout::eUndefined,
vk::ImageLayout::eTransferDstOptimal); vk::ImageLayout::eTransferDstOptimal);
@@ -108,10 +108,10 @@ void CTexture::init(void) {
vmaDestroyBuffer(api->getAllocator(), stagingBuffer.buffer, stagingBuffer.allocation); vmaDestroyBuffer(api->getAllocator(), stagingBuffer.buffer, stagingBuffer.allocation);
// 5. image view // image view
m_imageView = api->createImageView(m_textureImage, m_format, vk::ImageAspectFlagBits::eColor); m_imageView = api->createImageView(m_textureImage, m_format, vk::ImageAspectFlagBits::eColor);
// 6. sampler // sampler
vk::SamplerCreateInfo samplerInfo{}; vk::SamplerCreateInfo samplerInfo{};
samplerInfo.magFilter = vk::Filter::eLinear; samplerInfo.magFilter = vk::Filter::eLinear;
samplerInfo.minFilter = vk::Filter::eLinear; samplerInfo.minFilter = vk::Filter::eLinear;
@@ -134,7 +134,7 @@ void CTexture::initDefaultTexture()
VulkanImpl* api = dynamic_cast<VulkanImpl*>(GraphicsAPI::getAPI().get()); VulkanImpl* api = dynamic_cast<VulkanImpl*>(GraphicsAPI::getAPI().get());
auto* device= static_cast<vk::raii::Device*>(api->getDevice()); auto* device= static_cast<vk::raii::Device*>(api->getDevice());
// pixel blanc 1x1 RGBA // pixel rouge RGBA
uint32_t whitePixel = 0x00000ff0; uint32_t whitePixel = 0x00000ff0;
uint32_t width = 1; uint32_t width = 1;
uint32_t height = 1; uint32_t height = 1;
@@ -0,0 +1 @@
//TODO ???????
@@ -2,6 +2,8 @@
#include "../../Scene/CScene.hpp" #include "../../Scene/CScene.hpp"
#include "../../Component/Input/CInputManager.hpp" #include "../../Component/Input/CInputManager.hpp"
#include "Core/Systems/Input/API/CInputAPI.hpp" #include "Core/Systems/Input/API/CInputAPI.hpp"
#include <SDL3/SDL_events.h>
#include <SDL3/SDL_mouse.h>
#include <fstream> #include <fstream>
namespace CosmicCore { namespace CosmicCore {
@@ -21,6 +23,10 @@ namespace CosmicCore {
// reset souris relative après dispatch // reset souris relative après dispatch
m_mouseRelative = {0, 0}; m_mouseRelative = {0, 0};
genericLeftMouseButtonJustClicked = false;
genericLeftMouseButtonJustReleased = false;
genericRightMouseButtonJustClicked = false;
genericRightMouseButtonJustReleased = false;
} }
void CInputDispatcher::processEvent(const SDL_Event& event) void CInputDispatcher::processEvent(const SDL_Event& event)
@@ -46,6 +52,25 @@ namespace CosmicCore {
} }
break; break;
} }
case SDL_EVENT_MOUSE_BUTTON_DOWN: {
switch (event.button.button) {
case SDL_BUTTON_LEFT: genericLeftMouseButtonJustClicked = true; genericLeftMouseButtonJustReleased = false; break;
case SDL_BUTTON_RIGHT: genericRightMouseButtonJustClicked = true; genericRightMouseButtonJustReleased = false; break;
default: break;
}
break;
}
case SDL_EVENT_MOUSE_BUTTON_UP: {
switch (event.button.button) {
case SDL_BUTTON_LEFT: genericLeftMouseButtonJustReleased = true; genericLeftMouseButtonJustClicked = false; break;
case SDL_BUTTON_RIGHT: genericRightMouseButtonJustReleased = true; genericRightMouseButtonJustClicked = false; break;
default: break;
}
break;
}
case SDL_EVENT_MOUSE_MOTION: { case SDL_EVENT_MOUSE_MOTION: {
m_mouseRelative = {event.motion.xrel, event.motion.yrel}; m_mouseRelative = {event.motion.xrel, event.motion.yrel};
m_mousePosition = {event.motion.x, event.motion.y}; m_mousePosition = {event.motion.x, event.motion.y};
@@ -19,6 +19,12 @@ namespace CosmicCore {
glm::vec2 m_mouseRelative = {0, 0}; glm::vec2 m_mouseRelative = {0, 0};
glm::vec2 m_mousePosition = {0, 0}; glm::vec2 m_mousePosition = {0, 0};
CInputMapping m_mapping; CInputMapping m_mapping;
//Todo left and right click ?
bool genericLeftMouseButtonJustClicked = false;
bool genericLeftMouseButtonJustReleased = false;
bool genericRightMouseButtonJustClicked = false;
bool genericRightMouseButtonJustReleased = false;
public: public:
CInputDispatcher() {} CInputDispatcher() {}
@@ -28,6 +34,11 @@ namespace CosmicCore {
void processEvent(const SDL_Event& event); void processEvent(const SDL_Event& event);
bool isLeftMouseButtonJustClicked() const {return genericLeftMouseButtonJustClicked;};
bool isLeftMouseButtonJustReleased() const {return genericLeftMouseButtonJustReleased;};
bool isRightMouseButtonJustClicked() const {return genericRightMouseButtonJustClicked;};
bool isRightMouseButtonJustReleased() const {return genericRightMouseButtonJustReleased;};
glm::vec2 getMouseRelative() const { return m_mouseRelative; } glm::vec2 getMouseRelative() const { return m_mouseRelative; }
glm::vec2 getMousePosition() const { return m_mousePosition; } glm::vec2 getMousePosition() const { return m_mousePosition; }
float getSensitivity() const { return m_mapping.getMouseSensitivity(); } float getSensitivity() const { return m_mapping.getMouseSensitivity(); }
@@ -7,6 +7,7 @@
#include "Audio/CAudioManager.hpp" #include "Audio/CAudioManager.hpp"
#include "Shader/CShadersManager.hpp" #include "Shader/CShadersManager.hpp"
#include "Texture/CTextureManager.hpp" #include "Texture/CTextureManager.hpp"
#include "Font/CFontManager.hpp"
class CResourceManager{ class CResourceManager{
private: private:
@@ -16,6 +17,10 @@ class CResourceManager{
CTextureManager m_textureManager; CTextureManager m_textureManager;
CAudioManager m_audioManager; CAudioManager m_audioManager;
CShadersManager m_shaderManager; CShadersManager m_shaderManager;
CFontManager m_fontManager;
CModel2DManager m_model2DManager;
CMaterial2DManager m_material2DManager;
CMesh2DManager m_mesh2DManager;
public: public:
CModelManager& models() { return m_modelManager; } CModelManager& models() { return m_modelManager; }
CMeshManager& meshes() { return m_meshManager; } CMeshManager& meshes() { return m_meshManager; }
@@ -23,6 +28,10 @@ class CResourceManager{
CTextureManager& textures() { return m_textureManager; } CTextureManager& textures() { return m_textureManager; }
CAudioManager& sounds() { return m_audioManager; } CAudioManager& sounds() { return m_audioManager; }
CShadersManager& shaders() { return m_shaderManager; } CShadersManager& shaders() { return m_shaderManager; }
CFontManager& fonts() { return m_fontManager; }
CModel2DManager& models2D() {return m_model2DManager;}
CMaterial2DManager& materials2D() {return m_material2DManager;}
CMesh2DManager& meshes2D() { return m_mesh2DManager; }
const CModelManager& models() const { return m_modelManager; } const CModelManager& models() const { return m_modelManager; }
const CMeshManager& meshes() const { return m_meshManager; } const CMeshManager& meshes() const { return m_meshManager; }
@@ -30,6 +39,10 @@ class CResourceManager{
const CTextureManager& textures() const { return m_textureManager; } const CTextureManager& textures() const { return m_textureManager; }
const CAudioManager& sounds() const { return m_audioManager; } const CAudioManager& sounds() const { return m_audioManager; }
const CShadersManager& shaders() const { return m_shaderManager; } const CShadersManager& shaders() const { return m_shaderManager; }
const CFontManager& fonts() const { return m_fontManager; }
const CModel2DManager& models2D() const {return m_model2DManager;}
const CMaterial2DManager& materials2D() const {return m_material2DManager;}
const CMesh2DManager& meshes2D() const { return m_mesh2DManager; }
void cleanup() { void cleanup() {
m_modelManager.clear(); m_modelManager.clear();
@@ -37,6 +50,10 @@ class CResourceManager{
m_meshManager.clear(); m_meshManager.clear();
m_textureManager.clear(); m_textureManager.clear();
m_audioManager.clear(); m_audioManager.clear();
m_fontManager.clear();
m_model2DManager.clear();
m_material2DManager.clear();
m_mesh2DManager.clear();
m_shaderManager.clear(); m_shaderManager.clear();
} }
}; };
@@ -0,0 +1,48 @@
#ifndef CFONTMANAGER_HPP
#define CFONTMANAGER_HPP
#include "../../Graphics/Data/Font/CFont.hpp"
#include "../CAbstractResourceManager.hpp"
#include <filesystem>
#include <optional>
#include <stdexcept>
class CFontManager : public CAbstractResourceManager<CosmicCore::CFont>
{
public:
CosmicCore::CFont* loadFont(const std::string& path) {
auto cached = get(path);
if (cached) return cached.value();
std::optional<std::string> jsonPath = std::nullopt;
std::optional<std::string> pngPath = std::nullopt;
for (const auto& entry : std::filesystem::directory_iterator(path))
{
if(entry.is_regular_file())
{
// Converting the path to const char * in the
// subsequent lines
std::filesystem::path extension = entry.path().extension();
if(extension == ".json")
{
jsonPath = entry.path().string();
}
else if(extension == ".png")
{
pngPath = entry.path().string();
}
}
}
if(!jsonPath || !pngPath)
{
throw std::runtime_error("Font is not a valid folder. Must contain a json and a png");
}
auto font = std::make_unique<CosmicCore::CFont>();
font->init(*jsonPath, *pngPath);
return add(path, std::move(font));
}
};
#endif
@@ -2,8 +2,10 @@
#define CMATERIALMANAGER_HPP #define CMATERIALMANAGER_HPP
#include "../../Graphics/Data/Material/CMaterial.hpp" #include "../../Graphics/Data/Material/CMaterial.hpp"
#include "../../Graphics/Data/Material/CMaterial2D.hpp"
#include "../CAbstractResourceManager.hpp" #include "../CAbstractResourceManager.hpp"
#include "Core/Systems/Graphics/Data/Texture/CTexture.hpp"
class CMaterialManager : public CAbstractResourceManager<CMaterial> class CMaterialManager : public CAbstractResourceManager<CMaterial>
{ {
@@ -21,5 +23,75 @@ class CMaterialManager : public CAbstractResourceManager<CMaterial>
return add(key, std::move(mat)); return add(key, std::move(mat));
} }
}; };
using namespace CosmicCore;
class CMaterial2DManager : public CAbstractResourceManager<CMaterial2D>
{
public:
/*CMaterial2D* createRectMaterial(const std::string& key,
glm::vec4 color,
CShaderImplVulkan* shader)
{
auto mat = std::make_unique<CosmicCore::CMaterial2D>();
mat->m_shapeType = E2DShapeType::Rect;
mat->shader = shader;
mat->m_color = color;
mat->build();
return add(key, std::move(mat));
}
CMaterial2D* createCircleMaterial(const std::string& key,
glm::vec4 color,
CShaderImplVulkan* shader)
{
auto mat = std::make_unique<CosmicCore::CMaterial2D>();
mat->m_shapeType = E2DShapeType::Circle;
mat->shader = shader;
mat->m_color = color;
mat->build();
return add(key, std::move(mat));
}
CMaterial2D* createRoundedRectMaterial(const std::string& key,
glm::vec4 color,
float radius,
CShaderImplVulkan* shader)
{
auto mat = std::make_unique<CosmicCore::CMaterial2D>();
mat->m_shapeType = E2DShapeType::RoundedRect;
mat->shader = shader;
mat->m_color = color;
mat->m_cornerRadius = radius;
mat->build();
return add(key, std::move(mat));
}
CMaterial2D* createTextureMaterial(const std::string& key,
glm::vec4 color,
CTexture* texture,
CShaderImplVulkan* shader)
{
auto mat = std::make_unique<CosmicCore::CMaterial2D>();
mat->m_shapeType = E2DShapeType::Rect;
mat->shader = shader;
mat->m_color = color;
mat->m_texture = texture;
mat->build();
return add(key, std::move(mat));
}
CMaterial2D* createText(const std::string& key,
glm::vec4 color,
CFont* font,
CShaderImplVulkan* shader)
{
auto mat = std::make_unique<CMaterial2D>();
mat->m_shapeType = E2DShapeType::Rect;
mat->shader = shader;
mat->m_color = color;
mat->m_font = font;
mat->build();
return add(key, std::move(mat));
}*/
};
#endif #endif
@@ -2,10 +2,16 @@
#define CMESHMANAGER_HPP #define CMESHMANAGER_HPP
#include "../../Graphics/Data/Mesh/CMesh.hpp" #include "../../Graphics/Data/Mesh/CMesh.hpp"
#include "../../Graphics/Data/Mesh/CMesh2D.hpp"
#include "../CAbstractResourceManager.hpp" #include "../CAbstractResourceManager.hpp"
class CMeshManager : public CAbstractResourceManager<CMesh> class CMeshManager : public CAbstractResourceManager<CMesh>
{ {
};
class CMesh2DManager : public CAbstractResourceManager<CosmicCore::CMesh2D>
{
}; };
#endif #endif
@@ -2,10 +2,16 @@
#define CMODELMANAGER_HPP #define CMODELMANAGER_HPP
#include "../../Graphics/Data//Model/CModel.hpp" #include "../../Graphics/Data//Model/CModel.hpp"
#include "../../Graphics/Data//Model/CModel2D.hpp"
#include "../CAbstractResourceManager.hpp" #include "../CAbstractResourceManager.hpp"
class CModelManager : public CAbstractResourceManager<CModel> class CModelManager : public CAbstractResourceManager<CModel>
{ {
};
class CModel2DManager : public CAbstractResourceManager<CosmicCore::CModel2D>
{
}; };
#endif #endif
@@ -1,5 +1,6 @@
#include "CScriptAPI.hpp" #include "CScriptAPI.hpp"
#include <dlfcn.h> #include <dlfcn.h>
#include <iostream>
namespace CosmicCore { namespace CosmicCore {
CScriptRegistry CScriptAPI::scriptRegistry; CScriptRegistry CScriptAPI::scriptRegistry;
@@ -11,6 +12,10 @@ namespace CosmicCore {
auto registerFunc = (void(*)(CScriptRegistry* reg))dlsym(lib, "registerAllScripts"); auto registerFunc = (void(*)(CScriptRegistry* reg))dlsym(lib, "registerAllScripts");
registerFunc(&CScriptAPI::scripts()); // Passer l'API à la lib registerFunc(&CScriptAPI::scripts()); // Passer l'API à la lib
} }
else {
std::cout << "dlopen failed: " << dlerror() << std::endl;
throw std::runtime_error("Failed to load script module");
}
} }
} }
@@ -60,6 +60,41 @@ CEntity create(CScene* scene, EntityConfig& config) {
return entity; return entity;
} }
CEntity create(CScene* scene, Entity2DConfig& config) {
auto entity = scene->createEntity();
ComponentFactory::addMetaData(entity, config.name, config.description);
auto& transform = config.transformConfig;
auto& camera = config.cameraConfig;
auto& collider = config.colliderConfig;
auto& renderer = config.rendererConfig;
auto& script = config.scriptConfig;
if(transform.has_value())
{
ComponentFactory::addTransform2D(entity, *transform);
}
if(renderer.has_value())
{
ComponentFactory::addRenderer2D(entity, *renderer);
}
if(collider.has_value())
{
ComponentFactory::addCollider2D(entity, *collider);
}
if(camera.has_value())
{
ComponentFactory::addCamera2D(entity, *camera);
}
if(script.has_value())
{
ComponentFactory::addScript(entity, *script);
}
return entity;
}
/*CEntity* CEntityFactory::createCylinder(CScene* e, const EntityConfig& config) { /*CEntity* CEntityFactory::createCylinder(CScene* e, const EntityConfig& config) {
std::string name = "Cylindre" + std::to_string(CEntity::entityNumber); std::string name = "Cylindre" + std::to_string(CEntity::entityNumber);
CEntity* cylindre = new CEntity(name, glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f), glm::vec3(0.0f, 0.0f, 0.0f)); CEntity* cylindre = new CEntity(name, glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f), glm::vec3(0.0f, 0.0f, 0.0f));
@@ -23,7 +23,18 @@ namespace CosmicUtils {
std::optional<RelationshipConfig> relationshipConfig = std::nullopt; std::optional<RelationshipConfig> relationshipConfig = std::nullopt;
}; };
struct Entity2DConfig {
std::string name = "Entity";
std::string description = "";
std::optional<Transform2DConfig> transformConfig = std::nullopt;
std::optional<Camera2DConfig> cameraConfig = std::nullopt;
std::optional<Renderer2DConfig> rendererConfig = std::nullopt;
std::optional<Collider2DConfig> colliderConfig = std::nullopt;
std::optional<ScriptConfig> scriptConfig = std::nullopt;
};
CEntity create(CScene* e, EntityConfig& config); CEntity create(CScene* e, EntityConfig& config);
CEntity create(CScene* e, Entity2DConfig& config);
/*CEntity createSphere(CScene* e, const EntityConfig& config); /*CEntity createSphere(CScene* e, const EntityConfig& config);
+57 -1
View File
@@ -1,6 +1,9 @@
#include "ComponentFactory.hpp" #include "ComponentFactory.hpp"
#include "../../Core/Systems/Graphics/Data/CModelLoader.hpp" #include "../../Core/Systems/Graphics/Data/CModelLoader.hpp"
#include "../../Core/Systems/Resources/API/CResourceAPI.hpp" #include "../../Core/Systems/Resources/API/CResourceAPI.hpp"
#include "Core/Component/Camera/CCamera2D.hpp"
#include "Core/Component/Collider/CCollider2D.hpp"
#include "Core/Component/Geometry/CTransform2D.hpp"
#include "Core/Component/Light/CLight.hpp" #include "Core/Component/Light/CLight.hpp"
namespace CosmicUtils { namespace CosmicUtils {
@@ -170,7 +173,6 @@ namespace CosmicUtils {
CLight& addLight(CEntity& entity, LightConfig& lightConfig) CLight& addLight(CEntity& entity, LightConfig& lightConfig)
{ {
auto& rm = CResourceAPI::resources();
auto& reg = entity.getRegistry(); auto& reg = entity.getRegistry();
if (!reg.registry.all_of<CTransform>(*entity)) if (!reg.registry.all_of<CTransform>(*entity))
throw std::runtime_error("addLight requires a CTransform on the entity"); throw std::runtime_error("addLight requires a CTransform on the entity");
@@ -187,6 +189,60 @@ namespace CosmicUtils {
return light; return light;
} }
CCamera2D& addCamera2D(CEntity& entity, Camera2DConfig& cameraConfig)
{
VulkanImpl* api = dynamic_cast<VulkanImpl*>(GraphicsAPI::getAPI().get());
auto& reg = entity.getRegistry();
// CTransform obligatoire pour la caméra
if (!reg.registry.all_of<CTransform2D>(*entity))
throw std::runtime_error("addCamera2D requires a CTransform2D on the entity");
auto& transform = reg.registry.get<CTransform2D>(*entity);
auto& camera = reg.registry.emplace<CCamera2D>(*entity, entity);
camera.initUniformBuffer(api->getAllocator());
camera.updateUniformBuffer(0, transform);
camera.updateUniformBuffer(1, transform);
return camera;
}
CCollider2D& addCollider2D(CEntity& entity, Collider2DConfig& colliderConfig)
{
auto& reg = entity.getRegistry();
auto& collider = reg.registry.emplace<CCollider2D>(*entity, entity, colliderConfig.shape);
return collider;
}
CTransform2D& addTransform2D(CEntity& entity, Transform2DConfig& transformConfig)
{
VulkanImpl* api = dynamic_cast<VulkanImpl*>(GraphicsAPI::getAPI().get());
auto& reg = entity.getRegistry();
auto& transform = reg.registry.emplace<CTransform2D>(*entity, entity);
transform.setSize(transformConfig.m_size);
transform.setPivot(transformConfig.m_pivot);
transform.setPosition(transformConfig.m_position);
transform.setScale(transformConfig.m_scale);
transform.setRotation(transformConfig.m_rotation);
transform.setVisible(transformConfig.m_visible);
transform.setZOrder(transformConfig.m_zOrder);
transform.initUniformBuffer(api->getAllocator());
transform.updateUniformBuffer(0);
transform.updateUniformBuffer(1);
return transform;
}
CRenderer2D& addRenderer2D(CEntity& entity, Renderer2DConfig& rendererConfig)
{
auto& reg = entity.getRegistry();
Model2DLoadConfig config;
config.shaderName = rendererConfig.shader;
CModel2D* model = CModelLoader::loadModel2D(rendererConfig.model, config);
return reg.registry.emplace<CRenderer2D>(*entity, entity, model);
}
} }
} }
@@ -10,6 +10,10 @@
#include "../../Core/Component/Meta/CMetaData.hpp" #include "../../Core/Component/Meta/CMetaData.hpp"
#include "../../Core/Component/Speaker/CSpeaker.hpp" #include "../../Core/Component/Speaker/CSpeaker.hpp"
#include "../../Core/Component/Relationships/CRelationship.hpp" #include "../../Core/Component/Relationships/CRelationship.hpp"
#include "Core/Component/Camera/CCamera2D.hpp"
#include "Core/Component/Collider/CCollider2D.hpp"
#include "Core/Component/Geometry/CTransform2D.hpp"
#include "Core/Component/Graphics/CRenderer2D.hpp"
#include "Core/Component/Light/CLight.hpp" #include "Core/Component/Light/CLight.hpp"
#include "Core/Component/Script/CScriptManager.hpp" #include "Core/Component/Script/CScriptManager.hpp"
#include "glm/ext/vector_float3.hpp" #include "glm/ext/vector_float3.hpp"
@@ -84,6 +88,28 @@ namespace CosmicUtils {
bool castShadow = false; bool castShadow = false;
}; };
struct Camera2DConfig{
float zoom = 1;
};
struct Collider2DConfig{
E2DShape shape = E2DShape::RECTANGLE;
};
struct Transform2DConfig{
glm::vec2 m_position = {0, 0};
glm::vec2 m_size = {100, 100};
glm::vec2 m_scale = {1, 1};
glm::vec2 m_pivot = {0, 0};
float m_rotation = 0.0f;
float m_zOrder = 0.0f;
bool m_visible = true;
};
struct Renderer2DConfig{
std::string model = "";
std::string shader = "ui";
};
// crée et initialise un CTransform sur une entité existante // crée et initialise un CTransform sur une entité existante
CTransform& addTransform(CEntity& entity, TransformConfig& transformConfig); CTransform& addTransform(CEntity& entity, TransformConfig& transformConfig);
@@ -109,6 +135,15 @@ namespace CosmicUtils {
CScriptManager& addScript(CEntity& entity, ScriptConfig& scriptConfig); CScriptManager& addScript(CEntity& entity, ScriptConfig& scriptConfig);
CLight& addLight(CEntity& entity, LightConfig& lightConfig); CLight& addLight(CEntity& entity, LightConfig& lightConfig);
CCamera2D& addCamera2D(CEntity& entity, Camera2DConfig& cameraConfig);
CCollider2D& addCollider2D(CEntity& entity, Collider2DConfig& colliderConfig);
CTransform2D& addTransform2D(CEntity& entity, Transform2DConfig& transformConfig);
CRenderer2D& addRenderer2D(CEntity& entity, Renderer2DConfig& rendererConfig);
}; };
} }
#endif #endif
+36 -1
View File
@@ -77,7 +77,42 @@ namespace CosmicUtils {
Light_Attenuation = 3075, Light_Attenuation = 3075,
Light_InnerAngle = 3076, Light_InnerAngle = 3076,
Light_OuterAngle = 3077, Light_OuterAngle = 3077,
Light_CastShadow = 3078 Light_CastShadow = 3078,
//2D
Scene_Entities2D = 104,
// Entity
Entity2D_Ref = 207,
Entity2D_Name = 208,
Entity2D_Description = 209,
Entity2D_Components = 210,
//ComponentList
Component_Transform2D= 2069,
Component_Renderer2D = 2070,
Component_Camera2D = 2071,
Component_Collider2D = 2072,
// Transform
Transform_Position2D = 4011,
Transform_Rotation2D = 4012,
Transform_Scale2D = 4013,
Transform_Size2D = 4014,
Transform_Pivot2D = 4015,
Transform_zOrder2D = 4016,
Transform_Visible2D = 4017,
// Renderer
Renderer_Model2D = 4021,
Renderer_Shader2D = 4022,
//Camera
Camera_Zoom2D = 4031,
// Collider
Collider_Shape2D = 4041
}; };
@@ -34,7 +34,7 @@ void CExampleScript::onCreate()
.forward({0, 0, 0.05f}); .forward({0, 0, 0.05f});
}); });
input.onMouseMove([](CEntity& e, glm::vec2 delta) { input.addOnMouseMove([](CEntity& e, glm::vec2 delta) {
auto& tr = e.getRegistry().registry.get<CTransform>(e.getHandle()); auto& tr = e.getRegistry().registry.get<CTransform>(e.getHandle());
float sensitivity = 0.1f; float sensitivity = 0.1f;
glm::quat yaw = glm::angleAxis( glm::quat yaw = glm::angleAxis(