Adds audio component with spatialization

Adds a new audio component with support for loading, playing, pausing, stopping, and controlling audio properties such as volume, pan, pitch, and looping.

Implements spatialization using FMOD, enabling 3D audio effects based on object and camera positions. Includes file selection dialog and UI controls for audio properties.
This commit is contained in:
2025-09-15 23:15:34 +02:00
parent 9a8bfc43eb
commit 4f4151201d
9 changed files with 479 additions and 35 deletions

View File

@@ -6,9 +6,13 @@
<component name="ChangeListManager">
<list default="true" id="e81d6e08-efc7-40a0-909d-ec4943d948e9" name="Changes" comment="">
<change beforePath="$PROJECT_DIR$/.idea/.idea.KhaoticEngineReborn/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/.idea.KhaoticEngineReborn/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/enginecustom/enginecustom.vcxproj" beforeDir="false" afterPath="$PROJECT_DIR$/enginecustom/enginecustom.vcxproj" afterDir="false" />
<change beforePath="$PROJECT_DIR$/enginecustom/enginecustom.vcxproj.filters" beforeDir="false" afterPath="$PROJECT_DIR$/enginecustom/enginecustom.vcxproj.filters" afterDir="false" />
<change beforePath="$PROJECT_DIR$/enginecustom/src/inc/system/camera_class.h" beforeDir="false" afterPath="$PROJECT_DIR$/enginecustom/src/inc/system/camera_class.h" afterDir="false" />
<change beforePath="$PROJECT_DIR$/enginecustom/src/inc/system/ecs/component.h" beforeDir="false" afterPath="$PROJECT_DIR$/enginecustom/src/inc/system/ecs/component.h" afterDir="false" />
<change beforePath="$PROJECT_DIR$/enginecustom/src/inc/system/ecs/components/audio_component.h" beforeDir="false" afterPath="$PROJECT_DIR$/enginecustom/src/inc/system/ecs/components/audio_component.h" afterDir="false" />
<change beforePath="$PROJECT_DIR$/enginecustom/src/inc/system/ecs/components/transform_component.h" beforeDir="false" afterPath="$PROJECT_DIR$/enginecustom/src/inc/system/ecs/components/transform_component.h" afterDir="false" />
<change beforePath="$PROJECT_DIR$/enginecustom/src/inc/system/ecs/entity.h" beforeDir="false" afterPath="$PROJECT_DIR$/enginecustom/src/inc/system/ecs/entity.h" afterDir="false" />
<change beforePath="$PROJECT_DIR$/enginecustom/src/inc/system/ecs/entity_manager.h" beforeDir="false" afterPath="$PROJECT_DIR$/enginecustom/src/inc/system/ecs/entity_manager.h" afterDir="false" />
<change beforePath="$PROJECT_DIR$/enginecustom/src/src/system/application_class.cpp" beforeDir="false" afterPath="$PROJECT_DIR$/enginecustom/src/src/system/application_class.cpp" afterDir="false" />
</list>
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
@@ -38,6 +42,7 @@
<setting file="file://$PROJECT_DIR$/enginecustom/src/inc/system/ecs/entity.h" root0="FORCE_HIGHLIGHTING" />
<setting file="file://$PROJECT_DIR$/enginecustom/src/inc/system/ecs/entity_manager.h" root0="FORCE_HIGHLIGHTING" />
<setting file="file://$PROJECT_DIR$/enginecustom/src/inc/system/ecs/systems/render_system.h" root0="FORCE_HIGHLIGHTING" />
<setting file="file://$PROJECT_DIR$/enginecustom/src/inc/system/ecs/systems/types.h" root0="FORCE_HIGHLIGHTING" />
<setting file="file://$PROJECT_DIR$/../../IDE_VS/VC/Tools/MSVC/14.38.33130/include/type_traits" root0="SKIP_HIGHLIGHTING" />
</component>
<component name="KubernetesApiPersistence">{}</component>
@@ -250,7 +255,11 @@
<workItem from="1757449929378" duration="1107000" />
<workItem from="1757456559331" duration="2094000" />
<workItem from="1757458683204" duration="3628000" />
<workItem from="1757938327874" duration="1257000" />
<workItem from="1757938327874" duration="2045000" />
<workItem from="1757952605657" duration="117000" />
<workItem from="1757952791669" duration="4499000" />
<workItem from="1757959923169" duration="1930000" />
<workItem from="1757961888820" duration="8937000" />
</task>
<task id="LOCAL-00001" summary="Minor update - viewport window tweak">
<option name="closed" value="true" />

View File

@@ -0,0 +1,73 @@
[Window][DockSpace]
Pos=0,0
Size=1584,861
Collapsed=0
[Window][Debug##Default]
Pos=60,60
Size=400,400
Collapsed=0
[Window][Khaotic Engine]
Pos=1267,19
Size=317,842
Collapsed=0
DockId=0x00000005,0
[Window][render Stats]
Pos=0,630
Size=1584,231
Collapsed=0
DockId=0x00000009,0
[Window][Objects]
Pos=0,19
Size=234,842
Collapsed=0
DockId=0x0000000B,0
[Window][Terrain]
Pos=0,19
Size=266,842
Collapsed=0
DockId=0x00000007,0
[Window][Log Window]
Pos=0,630
Size=1584,231
Collapsed=0
DockId=0x0000000A,0
[Window][Light]
Pos=0,19
Size=234,609
Collapsed=0
DockId=0x0000000B,0
[Window][Engine Settings]
Pos=1267,462
Size=317,166
Collapsed=0
DockId=0x00000006,0
[Window][Inspector]
Pos=1267,19
Size=317,842
Collapsed=0
DockId=0x00000005,1
[Docking][Data]
DockSpace ID=0xCCBD8CF7 Window=0x3DA2F1DE Pos=0,19 Size=1584,842 Split=Y
DockNode ID=0x00000003 Parent=0xCCBD8CF7 SizeRef=1584,609 Split=X
DockNode ID=0x0000000B Parent=0x00000003 SizeRef=234,842 Selected=0x031DC75C
DockNode ID=0x0000000C Parent=0x00000003 SizeRef=1348,842 Split=X
DockNode ID=0x00000007 Parent=0x0000000C SizeRef=266,842 Selected=0x393905AB
DockNode ID=0x00000008 Parent=0x0000000C SizeRef=1316,842 Split=X
DockNode ID=0x00000001 Parent=0x00000008 SizeRef=1265,842 CentralNode=1
DockNode ID=0x00000002 Parent=0x00000008 SizeRef=317,842 Split=Y Selected=0x9F035453
DockNode ID=0x00000005 Parent=0x00000002 SizeRef=317,441 Selected=0x36DC96AB
DockNode ID=0x00000006 Parent=0x00000002 SizeRef=317,166 Selected=0x0B098C4B
DockNode ID=0x00000004 Parent=0xCCBD8CF7 SizeRef=1584,231 Split=X Selected=0xF5D1BB37
DockNode ID=0x00000009 Parent=0x00000004 SizeRef=792,231 Selected=0xF5D1BB37
DockNode ID=0x0000000A Parent=0x00000004 SizeRef=790,231 Selected=0xAB74BEE9

View File

@@ -82,6 +82,36 @@ public:
*/
void get_reflection_view_matrix(XMMATRIX&) const;
XMFLOAT3 get_forward() const {
float pitch = XMConvertToRadians(rotation_x_);
float yaw = XMConvertToRadians(rotation_y_);
XMMATRIX rotMatrix = XMMatrixRotationRollPitchYaw(pitch, yaw, 0.0f);
XMVECTOR forward = -rotMatrix.r[2];
forward = XMVector3Normalize(forward);
XMFLOAT3 forwardVec;
XMStoreFloat3(&forwardVec, forward);
return forwardVec;
}
XMFLOAT3 get_up() const {
// Construire matrice rotation <20> partir des angles
XMMATRIX rot = XMMatrixRotationRollPitchYaw(
XMConvertToRadians(rotation_x_),
XMConvertToRadians(rotation_y_),
XMConvertToRadians(rotation_z_));
// Extraire le vecteur up, 2e colonne
XMVECTOR up = rot.r[1]; // colonne up
up = XMVector3Normalize(up);
XMFLOAT3 upF;
XMStoreFloat3(&upF, up);
return upF;
}
private:
float position_x_, position_y_, position_z_;
float rotation_x_, rotation_y_, rotation_z_;

View File

@@ -3,11 +3,13 @@
#include <typeindex>
#include <typeinfo>
#include <imgui.h>
#include "entity.h"
/**
* namespace for the Entity-Component-System (ECS)
*/
namespace ecs {
class Entity;
// Classe de base pour tous les composants
class Component {
@@ -31,6 +33,7 @@ public:
/**
* Virtual function to update the component.
* @param deltaTime Time since the last update.
* @param entity The entity this component is attached to.
*/
virtual void Update(float deltaTime) {}
@@ -52,6 +55,21 @@ public:
* This can be overridden by derived components to provide custom UI.
*/
virtual void OnImGuiRender() { /* Default implementation does nothing */ }
/**
* Set the parent entity of this component.
* @param parent A shared pointer to the parent entity.
*/
void SetParent(std::shared_ptr<Entity> parent) { m_parent = parent; }
/**
* Get the parent entity of this component.
* @return A shared pointer to the parent entity, or nullptr if it has been destroyed.
*/
std::shared_ptr<Entity> GetParent() const { return m_parent.lock(); }
private:
std::weak_ptr<Entity> m_parent;
};

View File

@@ -4,6 +4,14 @@
#include <Fmod/core/inc/fmod.hpp>
#include <string>
#include <filesystem>
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <Shlwapi.h>
#pragma comment(lib, "Shlwapi.lib")
#include <commdlg.h> // Pour GetOpenFileName
#include "camera_class.h"
#include "transform_component.h"
namespace ecs {
class AudioComponent : public Component {
@@ -25,38 +33,51 @@ public:
return;
}
result = m_system->init(512, FMOD_INIT_NORMAL, nullptr);
result = m_system->init(512, FMOD_INIT_NORMAL | FMOD_INIT_3D_RIGHTHANDED, nullptr);
if (result != FMOD_OK) {
m_lastError = "<EFBFBD>chec de l'initialisation du syst<73>me FMOD: " + std::to_string(result);
m_system->release();
m_system = nullptr;
}
}
auto parent = GetParent();
if (parent && parent->GetCamera())
{
SetCamera(parent->GetCamera());
}
}
bool Load(const std::string& path) {
if (!m_system) {
Initialize();
if (!m_system) return false; // L'erreur est d<>j<EFBFBD> d<>finie dans Initialize()
if (!m_system) return false;
}
m_soundPath = path;
// V<>rifier si le fichier existe
if (!std::filesystem::exists(path)) {
m_lastError = "Fichier non trouv<75>: " + path;
return false;
}
// Lib<69>rer le son pr<70>c<EFBFBD>dent s'il existe
if (m_sound) {
m_sound->release();
m_sound = nullptr;
}
// Essayer de charger avec le chemin absolu
FMOD_MODE mode = FMOD_DEFAULT;
if (m_spatialized)
mode |= FMOD_3D;
if (m_looping)
mode |= FMOD_LOOP_NORMAL;
else
mode |= FMOD_LOOP_OFF;
std::filesystem::path absolutePath = std::filesystem::absolute(path);
FMOD_RESULT result = m_system->createSound(absolutePath.string().c_str(), FMOD_DEFAULT, nullptr, &m_sound);
FMOD_RESULT result = m_system->createSound(absolutePath.string().c_str(), mode, nullptr, &m_sound);
if (result != FMOD_OK) {
m_lastError = "<EFBFBD>chec du chargement du son: " + std::to_string(result) +
" (chemin: " + absolutePath.string() + ")";
@@ -67,8 +88,41 @@ public:
}
void Play() {
if (m_system && m_sound)
if (m_system && m_sound) {
bool isPlaying = false;
if (m_channel) {
m_channel->isPlaying(&isPlaying);
}
if (isPlaying) {
m_channel->stop();
}
m_system->playSound(m_sound, nullptr, false, &m_channel);
if (m_channel) {
m_channel->setVolume(m_volume);
m_channel->setPan(m_pan);
m_channel->setPitch(m_pitch);
m_channel->setMute(m_muted);
m_channel->setPriority(m_priority);
m_channel->setPaused(m_paused);
}
}
}
void Pause() {
if (m_channel) {
m_paused = true;
m_channel->setPaused(true);
}
}
void Resume() {
if (m_channel) {
m_paused = false;
m_channel->setPaused(false);
}
}
void Stop() {
@@ -76,49 +130,288 @@ public:
m_channel->stop();
}
void OnImGuiRender() override {
// Afficher le r<>pertoire de travail actuel
std::string currentDir = std::filesystem::current_path().string();
ImGui::Text("R<EFBFBD>pertoire actuel: %s", currentDir.c_str());
void SetCamera(camera_class* camera) {m_camera = camera; }
if (m_sound) {
ImGui::Text("Son charg<72>: %s", m_soundPath.c_str());
if (ImGui::Button("Jouer")) {
void Update(float deltaTime) override {
if (!m_spatialized) return;
if (!m_system || !m_camera) return;
auto parent = GetParent();
if (!parent) return;
auto transform = parent->GetComponent<TransformComponent>();
if (!transform) return;
XMVECTOR pos = transform->GetPosition();
m_position.x = XMVectorGetX(pos);
m_position.y = XMVectorGetY(pos);
m_position.z = XMVectorGetZ(pos);
if (m_channel) {
FMOD_VECTOR velocity = { 0.f, 0.f, 0.f }; // <20> am<61>liorer si possible - calculer depuis d<>placement temps+position ?
m_channel->set3DAttributes(&m_position, &velocity);
}
// Mise <20> jour du listener FMOD
XMFLOAT3 camPos = m_camera->get_position();
XMFLOAT3 camForward = m_camera->get_forward();
XMFLOAT3 camUp = m_camera->get_up();
FMOD_VECTOR listenerPos = { camPos.x, camPos.y, camPos.z };
FMOD_VECTOR forward = { camForward.x, camForward.y, camForward.z };
FMOD_VECTOR up = { camUp.x, camUp.y, camUp.z };
FMOD_VECTOR listenerVel = { 0.f, 0.f, 0.f };
if (m_use_velocity)
{
static XMFLOAT3 lastCamPos = camPos;
XMFLOAT3 currentCamPos = camPos;
float deltaTimeSec = deltaTime > 0.0001f ? deltaTime : 0.016f; // <20>viter division par z<>ro
XMFLOAT3 listenerVelocity = {
(currentCamPos.x - lastCamPos.x) / deltaTimeSec,
(currentCamPos.y - lastCamPos.y) / deltaTimeSec,
(currentCamPos.z - lastCamPos.z) / deltaTimeSec
};
lastCamPos = currentCamPos;
listenerVel = { listenerVelocity.x, listenerVelocity.y, listenerVelocity.z };
}
m_system->set3DListenerAttributes(0, &listenerPos, &listenerVel, &forward, &up);
m_system->update();
}
void OnImGuiRender() override {
if (!m_sound) {
ImGui::Text("No audio file loaded");
if (ImGui::Button("Load audio file")) {
OPENFILENAME ofn;
wchar_t szFile[MAX_PATH] = L"";
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = NULL; // Renseigner si possible avec handle de la fen<65>tre
ofn.lpstrFile = szFile;
ofn.nMaxFile = MAX_PATH;
ofn.lpstrFilter = L"Audio Files\0*.mp3;*.wav;*.ogg;*.flac\0All Files\0*.*\0";
ofn.nFilterIndex = 1;
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
if (GetOpenFileName(&ofn)) {
wchar_t exePath[MAX_PATH];
GetModuleFileName(NULL, exePath, MAX_PATH);
PathRemoveFileSpec(exePath);
std::wstring targetDir = std::wstring(exePath) + L"\\assets\\sounds";
DWORD ftyp = GetFileAttributes(targetDir.c_str());
if (ftyp == INVALID_FILE_ATTRIBUTES) {
CreateDirectory((std::wstring(exePath) + L"\\assets").c_str(), NULL);
CreateDirectory(targetDir.c_str(), NULL);
}
const wchar_t* filename = wcsrchr(szFile, L'\\');
std::wstring fileNameStr = filename ? (filename + 1) : szFile;
std::wstring targetPath = targetDir + L"\\" + fileNameStr;
if (!CopyFile(szFile, targetPath.c_str(), FALSE)) {
MessageBox(NULL, L"Erreur lors de la copie du fichier audio.", L"Erreur", MB_OK | MB_ICONERROR);
} else {
int utf8size = WideCharToMultiByte(CP_UTF8, 0, targetPath.c_str(), -1, NULL, 0, NULL, NULL);
std::string pathStr(utf8size, 0);
WideCharToMultiByte(CP_UTF8, 0, targetPath.c_str(), -1, &pathStr[0], utf8size, NULL, NULL);
pathStr.resize(utf8size - 1);
if (!Load(pathStr)) {
// erreur dans m_lastError
}
}
}
}
if (!m_lastError.empty()) {
ImGui::TextColored(ImVec4(1, 0, 0, 1), "Error: %s", m_lastError.c_str());
}
} else {
ImGui::Text("Loaded: %s", m_soundPath.c_str());
if (ImGui::Button("Change audio")) {
OPENFILENAME ofn;
wchar_t szFile[MAX_PATH] = L"";
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = NULL;
ofn.lpstrFile = szFile;
ofn.nMaxFile = MAX_PATH;
ofn.lpstrFilter = L"Audio Files\0*.mp3;*.wav;*.ogg;*.flac\0All Files\0*.*\0";
ofn.nFilterIndex = 1;
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
if (GetOpenFileName(&ofn)) {
wchar_t exePath[MAX_PATH];
GetModuleFileName(NULL, exePath, MAX_PATH);
PathRemoveFileSpec(exePath);
std::wstring targetDir = std::wstring(exePath) + L"\\assets\\sounds";
DWORD ftyp = GetFileAttributes(targetDir.c_str());
if (ftyp == INVALID_FILE_ATTRIBUTES) {
CreateDirectory((std::wstring(exePath) + L"\\assets").c_str(), NULL);
CreateDirectory(targetDir.c_str(), NULL);
}
const wchar_t* filename = wcsrchr(szFile, L'\\');
std::wstring fileNameStr = filename ? (filename + 1) : szFile;
std::wstring targetPath = targetDir + L"\\" + fileNameStr;
if (!CopyFile(szFile, targetPath.c_str(), FALSE)) {
MessageBox(NULL, L"Erreur lors de la copie du fichier audio.", L"Erreur", MB_OK | MB_ICONERROR);
} else {
int utf8size = WideCharToMultiByte(CP_UTF8, 0, targetPath.c_str(), -1, NULL, 0, NULL, NULL);
std::string pathStr(utf8size, 0);
WideCharToMultiByte(CP_UTF8, 0, targetPath.c_str(), -1, &pathStr[0], utf8size, NULL, NULL);
pathStr.resize(utf8size - 1);
if (!Load(pathStr)) {
// erreur dans m_lastError
}
}
}
}
ImGui::SameLine();
if (ImGui::Button("Remove audio")) {
Stop();
if (m_sound) m_sound->release();
m_sound = nullptr;
m_soundPath.clear();
}
ImGui::Separator();
if (ImGui::Button("Play")) {
Play();
}
ImGui::SameLine();
if (ImGui::Button("Arr<EFBFBD>ter")) {
if (ImGui::Button(m_paused ? "Resume" : "Pause")) {
if (m_paused) Resume();
else Pause();
}
ImGui::SameLine();
if (ImGui::Button("Stop")) {
Stop();
}
} else {
ImGui::Text("Aucun son charg<72>");
// Montrer l'erreur s'il y en a une
if (!m_lastError.empty()) {
ImGui::TextColored(ImVec4(1.0f, 0.0f, 0.0f, 1.0f), "Erreur: %s", m_lastError.c_str());
ImGui::Separator();
if (ImGui::SliderFloat("Volume", &m_volume, 0.0f, 1.0f)) {
if (m_channel) m_channel->setVolume(m_volume);
}
// exe path + assets/sounds/default.mp3
std::filesystem::path defaultSoundPath = std::filesystem::current_path() / "assets" / "sounds" / "default.mp3";
std::string defaultSoundPathStr = defaultSoundPath.string();// Input text with default path
char path[260];
strncpy_s(path, m_soundPath.empty() ? defaultSoundPathStr.c_str() : m_soundPath.c_str(), sizeof(path));
path[sizeof(path) - 1] = '\0'; // Assurer la termination nulle
ImGui::InputText("Chemin du fichier", path, sizeof(path));
if (ImGui::Button("Charger le son")) {
if (!Load(path)) {
// L'erreur est d<>j<EFBFBD> d<>finie dans Load()
if (ImGui::SliderFloat("Pan", &m_pan, -1.0f, 1.0f)) {
if (m_channel) m_channel->setPan(m_pan);
}
if (ImGui::SliderFloat("Pitch", &m_pitch, 0.5f, 2.0f)) {
if (m_channel) m_channel->setPitch(m_pitch);
}
if (ImGui::Checkbox("Looping", &m_looping)) {
// Recharger le son pour appliquer le mode loop
Load(m_soundPath);
}
if (ImGui::Checkbox("Spatialization 3D", &m_spatialized)) {
if (!m_soundPath.empty()) {
Load(m_soundPath); // Recharger le son avec ou sans 3D selon le choix
}
}
// check box to use velocity for doppler effect (only if spatialized)
if (m_spatialized) {
ImGui::SameLine();
ImGui::Checkbox("Use Velocity for Doppler", &m_use_velocity);
}
if (ImGui::Checkbox("Mute", &m_muted)) {
if (m_channel) m_channel->setMute(m_muted);
}
if (ImGui::SliderInt("Priority", &m_priority, 0, 256)) {
if (m_channel) m_channel->setPriority(m_priority);
}
ImGui::Separator();
if (m_channel && m_sound) {
unsigned int pos = 0, len = 0;
m_channel->getPosition(&pos, FMOD_TIMEUNIT_MS);
m_sound->getLength(&len, FMOD_TIMEUNIT_MS);
float progress = (len > 0) ? (float)pos / len : 0.0f;
ImGui::ProgressBar(progress, ImVec2(300, 0), nullptr);
auto to_minsec = [](unsigned int ms) {
unsigned int totalSec = ms / 1000;
return std::make_pair(totalSec / 60, totalSec % 60);
};
auto [curMin, curSec] = to_minsec(pos);
auto [lenMin, lenSec] = to_minsec(len);
ImGui::Text("%02u:%02u / %02u:%02u", curMin, curSec, lenMin, lenSec);
}
// afficher la position de l'objet et de la camera ainsi que la rotaion de la camera si spatialis<69>
if (m_spatialized) {
auto parent = GetParent();
if (parent) {
auto transform = parent->GetComponent<TransformComponent>();
if (transform) {
XMVECTOR pos = transform->GetPosition();
ImGui::Text("Object Position: (%.2f, %.2f, %.2f)", XMVectorGetX(pos), XMVectorGetY(pos), XMVectorGetZ(pos));
}
}
if (m_camera) {
XMFLOAT3 camPos = m_camera->get_position();
XMFLOAT3 camRot = m_camera->get_rotation();
ImGui::Text("Camera Position: (%.2f, %.2f, %.2f)", camPos.x, camPos.y, camPos.z);
ImGui::Text("Camera Rotation: (%.2f, %.2f, %.2f)", camRot.x, camRot.y, camRot.z);
}
}
if (!m_lastError.empty()) {
ImGui::TextColored(ImVec4(1,0,0,1), "Error: %s", m_lastError.c_str());
}
}
}
private:
FMOD::System* m_system;
FMOD::Sound* m_sound;
FMOD::Channel* m_channel;
std::string m_soundPath;
std::string m_lastError;
float m_volume = 1.0f;
float m_pan = 0.0f;
float m_pitch = 1.0f;
bool m_looping = false;
bool m_muted = false;
bool m_paused = false;
int m_priority = 128;
bool m_spatialized = false;
bool m_use_velocity = false;
FMOD_VECTOR m_position = {0.0f, 0.0f, 0.0f};
camera_class* m_camera = nullptr;
};
}

View File

@@ -1,6 +1,7 @@
#pragma once
#include "../component.h"
#include <DirectXMath.h>
#include <sstream>
using namespace DirectX;

View File

@@ -6,13 +6,15 @@
#include <algorithm>
#include <cassert>
#include "camera_class.h"
namespace ecs {
/**
* Type alias for a unique identifier for an entity.
*/
using EntityID = uint32_t;
class Entity {
class Entity : public std::enable_shared_from_this<Entity> {
public:
/**
* Builder for an Entity with a unique ID.
@@ -59,6 +61,9 @@ public:
// Cr<43>er et ajouter le composant
auto component = std::make_shared<T>(std::forward<Args>(args)...);
m_Components[typeID] = component;
component->SetParent(shared_from_this());
// Initialiser le composant
component->Initialize();
@@ -132,6 +137,9 @@ public:
return m_Components;
}
void SetCamera(camera_class* camera) {m_camera = camera; }
camera_class* GetCamera() const { return m_camera; }
private:
/**
@@ -143,6 +151,9 @@ private:
* The key is the type ID of the component, and the value is a shared pointer to the component.
*/
std::unordered_map<ComponentTypeID, ComponentPtr> m_Components;
// camera
camera_class* m_camera = nullptr;
};
} // namespace ecs

View File

@@ -31,6 +31,7 @@ public:
}
auto entity = std::make_shared<Entity>(id);
entity->SetCamera(camera_);
m_Entities[id] = entity;
return entity;
@@ -144,10 +145,14 @@ public:
}
void SetCamera(camera_class* camera) { camera_ = camera; }
camera_class* GetCamera() const { return camera_; }
private:
EntityID m_NextEntityID;
std::unordered_map<EntityID, std::shared_ptr<Entity>> m_Entities;
std::queue<EntityID> m_FreeIDs; // IDs <20> r<>utiliser
camera_class* camera_ = nullptr;
};
} // namespace ecs

View File

@@ -504,6 +504,9 @@ bool application_class::initialize(int screenWidth, int screenHeight, HWND hwnd,
culling_active_ = true;
culling_thread_ = std::thread(&application_class::culling_thread_function, this);
entity_manager_->SetCamera(camera_);
}
catch (const std::exception& e)
{
@@ -858,6 +861,7 @@ bool application_class::frame(input_class* Input)
}
active_camera_->render();
entity_manager_->UpdateEntities(frameTime);
// render the static graphics scene.
result = render(rotation, x, y, z, textureTranslation);