Docs: Add audio module architecture design document
- Add XCEngine音频模块架构设计.md - Design audio system following Unity-style architecture - Include AudioSourceComponent, AudioListenerComponent, AudioClip, AudioMixer - Document DSP effect system (FFT, Reverb, EQ, Compressor) - Document 3D spatial audio with HRTF support - Define IAudioBackend abstraction layer with WASAPI/OpenAL backends - Outline 5-phase implementation priorities
This commit is contained in:
57
engine/include/XCEngine/Components/Component.h
Normal file
57
engine/include/XCEngine/Components/Component.h
Normal file
@@ -0,0 +1,57 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <cstdint>
|
||||
|
||||
namespace XCEngine {
|
||||
namespace Components {
|
||||
|
||||
class GameObject;
|
||||
class TransformComponent;
|
||||
class Scene;
|
||||
|
||||
class Component {
|
||||
public:
|
||||
virtual ~Component() = default;
|
||||
|
||||
virtual void Awake() {}
|
||||
virtual void Start() {}
|
||||
virtual void Update(float deltaTime) {}
|
||||
virtual void FixedUpdate() {}
|
||||
virtual void LateUpdate(float deltaTime) {}
|
||||
virtual void OnEnable() {}
|
||||
virtual void OnDisable() {}
|
||||
virtual void OnDestroy() {}
|
||||
|
||||
virtual std::string GetName() const = 0;
|
||||
|
||||
GameObject* GetGameObject() const { return m_gameObject; }
|
||||
TransformComponent& transform() const;
|
||||
Scene* GetScene() const;
|
||||
|
||||
bool IsEnabled() const { return m_enabled; }
|
||||
void SetEnabled(bool enabled) {
|
||||
if (m_enabled != enabled) {
|
||||
m_enabled = enabled;
|
||||
if (m_enabled) {
|
||||
OnEnable();
|
||||
} else {
|
||||
OnDisable();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
Component() = default;
|
||||
|
||||
private:
|
||||
bool m_enabled = true;
|
||||
|
||||
protected:
|
||||
GameObject* m_gameObject = nullptr;
|
||||
|
||||
friend class GameObject;
|
||||
};
|
||||
|
||||
} // namespace Components
|
||||
} // namespace XCEngine
|
||||
174
engine/include/XCEngine/Components/GameObject.h
Normal file
174
engine/include/XCEngine/Components/GameObject.h
Normal file
@@ -0,0 +1,174 @@
|
||||
#pragma once
|
||||
|
||||
#include "Component.h"
|
||||
#include "TransformComponent.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace XCEngine {
|
||||
namespace Components {
|
||||
|
||||
class Scene;
|
||||
|
||||
class GameObject {
|
||||
public:
|
||||
using ID = uint64_t;
|
||||
static constexpr ID INVALID_ID = 0;
|
||||
|
||||
GameObject();
|
||||
explicit GameObject(const std::string& name);
|
||||
~GameObject();
|
||||
|
||||
ID GetID() const { return m_id; }
|
||||
const std::string& GetName() const { return m_name; }
|
||||
void SetName(const std::string& name) { m_name = name; }
|
||||
|
||||
Scene* GetScene() const { return m_scene; }
|
||||
|
||||
TransformComponent* GetTransform() { return m_transform; }
|
||||
const TransformComponent* GetTransform() const { return m_transform; }
|
||||
|
||||
template<typename T, typename... Args>
|
||||
T* AddComponent(Args&&... args) {
|
||||
auto component = std::make_unique<T>(std::forward<Args>(args)...);
|
||||
component->m_gameObject = this;
|
||||
T* ptr = component.get();
|
||||
m_components.emplace_back(std::move(component));
|
||||
return ptr;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T* GetComponent() {
|
||||
for (auto& comp : m_components) {
|
||||
if (T* casted = dynamic_cast<T*>(comp.get())) {
|
||||
return casted;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
const T* GetComponent() const {
|
||||
for (auto& comp : m_components) {
|
||||
if (T* casted = dynamic_cast<T*>(comp.get())) {
|
||||
return casted;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::vector<T*> GetComponents() {
|
||||
std::vector<T*> result;
|
||||
for (auto& comp : m_components) {
|
||||
if (T* casted = dynamic_cast<T*>(comp.get())) {
|
||||
result.push_back(casted);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::vector<const T*> GetComponents() const {
|
||||
std::vector<const T*> result;
|
||||
for (auto& comp : m_components) {
|
||||
if (const T* casted = dynamic_cast<const T*>(comp.get())) {
|
||||
result.push_back(casted);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T* GetComponentInChildren() {
|
||||
T* comp = GetComponent<T>();
|
||||
if (comp) {
|
||||
return comp;
|
||||
}
|
||||
for (auto* child : m_children) {
|
||||
comp = child->GetComponentInChildren<T>();
|
||||
if (comp) {
|
||||
return comp;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T* GetComponentInParent() {
|
||||
if (m_parent) {
|
||||
T* comp = m_parent->GetComponent<T>();
|
||||
if (comp) {
|
||||
return comp;
|
||||
}
|
||||
return m_parent->GetComponentInParent<T>();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::vector<T*> GetComponentsInChildren() {
|
||||
std::vector<T*> result;
|
||||
std::vector<T*> comps = GetComponents<T>();
|
||||
result.insert(result.end(), comps.begin(), comps.end());
|
||||
|
||||
for (auto* child : m_children) {
|
||||
std::vector<T*> childComps = child->GetComponentsInChildren<T>();
|
||||
result.insert(result.end(), childComps.begin(), childComps.end());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Hierarchy
|
||||
GameObject* GetParent() const { return m_parent; }
|
||||
void SetParent(GameObject* parent);
|
||||
void SetParent(GameObject* parent, bool worldPositionStays);
|
||||
|
||||
size_t GetChildCount() const { return m_children.size(); }
|
||||
GameObject* GetChild(size_t index) const;
|
||||
std::vector<GameObject*> GetChildren() const;
|
||||
void DetachChildren();
|
||||
|
||||
// Active state
|
||||
bool IsActive() const { return m_activeSelf; }
|
||||
void SetActive(bool active);
|
||||
bool IsActiveInHierarchy() const;
|
||||
|
||||
// Static find
|
||||
static GameObject* Find(const std::string& name);
|
||||
static std::vector<GameObject*> FindObjectsOfType();
|
||||
static std::vector<GameObject*> FindGameObjectsWithTag(const std::string& tag);
|
||||
|
||||
// Lifecycle
|
||||
void Awake();
|
||||
void Start();
|
||||
void Update(float deltaTime);
|
||||
void FixedUpdate();
|
||||
void LateUpdate(float deltaTime);
|
||||
void OnDestroy();
|
||||
|
||||
void Destroy();
|
||||
|
||||
private:
|
||||
ID m_id = INVALID_ID;
|
||||
std::string m_name;
|
||||
bool m_activeSelf = true;
|
||||
|
||||
GameObject* m_parent = nullptr;
|
||||
std::vector<GameObject*> m_children;
|
||||
|
||||
Scene* m_scene = nullptr;
|
||||
TransformComponent* m_transform = nullptr;
|
||||
std::vector<std::unique_ptr<Component>> m_components;
|
||||
|
||||
static ID s_nextID;
|
||||
static std::unordered_map<ID, GameObject*>& GetGlobalRegistry();
|
||||
|
||||
friend class Scene;
|
||||
friend class SceneManager;
|
||||
};
|
||||
|
||||
} // namespace Components
|
||||
} // namespace XCEngine
|
||||
114
engine/include/XCEngine/Components/TransformComponent.h
Normal file
114
engine/include/XCEngine/Components/TransformComponent.h
Normal file
@@ -0,0 +1,114 @@
|
||||
#pragma once
|
||||
|
||||
#include "Component.h"
|
||||
#include <XCEngine/Math/Vector3.h>
|
||||
#include <XCEngine/Math/Quaternion.h>
|
||||
#include <XCEngine/Math/Matrix4.h>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
namespace XCEngine {
|
||||
namespace Components {
|
||||
|
||||
class GameObject;
|
||||
class Scene;
|
||||
|
||||
enum class Space {
|
||||
Self,
|
||||
World
|
||||
};
|
||||
|
||||
class TransformComponent : public Component {
|
||||
public:
|
||||
TransformComponent();
|
||||
~TransformComponent() override = default;
|
||||
|
||||
std::string GetName() const override { return "Transform"; }
|
||||
|
||||
// Local space getters/setters
|
||||
const Math::Vector3& GetLocalPosition() const { return m_localPosition; }
|
||||
void SetLocalPosition(const Math::Vector3& position) { m_localPosition = position; SetDirty(); }
|
||||
|
||||
const Math::Quaternion& GetLocalRotation() const { return m_localRotation; }
|
||||
void SetLocalRotation(const Math::Quaternion& rotation) { m_localRotation = rotation; SetDirty(); }
|
||||
|
||||
const Math::Vector3& GetLocalScale() const { return m_localScale; }
|
||||
void SetLocalScale(const Math::Vector3& scale) { m_localScale = scale; SetDirty(); }
|
||||
|
||||
Math::Vector3 GetLocalEulerAngles() const;
|
||||
void SetLocalEulerAngles(const Math::Vector3& eulers);
|
||||
|
||||
// World space getters/setters
|
||||
Math::Vector3 GetPosition() const;
|
||||
void SetPosition(const Math::Vector3& position);
|
||||
|
||||
Math::Quaternion GetRotation() const;
|
||||
void SetRotation(const Math::Quaternion& rotation);
|
||||
|
||||
Math::Vector3 GetScale() const;
|
||||
void SetScale(const Math::Vector3& scale);
|
||||
|
||||
// Direction vectors
|
||||
Math::Vector3 GetForward() const;
|
||||
Math::Vector3 GetRight() const;
|
||||
Math::Vector3 GetUp() const;
|
||||
|
||||
// Matrix operations
|
||||
const Math::Matrix4x4& GetLocalToWorldMatrix() const;
|
||||
Math::Matrix4x4 GetWorldToLocalMatrix() const;
|
||||
|
||||
// Hierarchy - parent
|
||||
TransformComponent* GetParent() const { return m_parent; }
|
||||
void SetParent(TransformComponent* parent, bool worldPositionStays = true);
|
||||
void SetParent(TransformComponent* parent) { SetParent(parent, true); }
|
||||
|
||||
// Hierarchy - children
|
||||
size_t GetChildCount() const { return m_children.size(); }
|
||||
TransformComponent* GetChild(size_t index) const;
|
||||
TransformComponent* Find(const std::string& name) const;
|
||||
void DetachChildren();
|
||||
|
||||
// Hierarchy - sibling
|
||||
int GetSiblingIndex() const { return m_siblingIndex; }
|
||||
void SetSiblingIndex(int index);
|
||||
void SetAsFirstSibling();
|
||||
void SetAsLastSibling();
|
||||
|
||||
// Transform operations
|
||||
void LookAt(const Math::Vector3& target);
|
||||
void LookAt(const Math::Vector3& target, const Math::Vector3& up);
|
||||
void Rotate(const Math::Vector3& eulers, Space relativeTo = Space::Self);
|
||||
void Rotate(const Math::Vector3& axis, float angle, Space relativeTo = Space::Self);
|
||||
void Translate(const Math::Vector3& translation, Space relativeTo = Space::Self);
|
||||
|
||||
// Point/direction transforms
|
||||
Math::Vector3 TransformPoint(const Math::Vector3& point) const;
|
||||
Math::Vector3 InverseTransformPoint(const Math::Vector3& point) const;
|
||||
Math::Vector3 TransformDirection(const Math::Vector3& direction) const;
|
||||
Math::Vector3 InverseTransformDirection(const Math::Vector3& direction) const;
|
||||
|
||||
// Internal
|
||||
void SetDirty();
|
||||
void UpdateWorldTransform() const;
|
||||
void NotifyHierarchyChanged();
|
||||
|
||||
private:
|
||||
Math::Vector3 m_localPosition = Math::Vector3::Zero();
|
||||
Math::Quaternion m_localRotation = Math::Quaternion::Identity();
|
||||
Math::Vector3 m_localScale = Math::Vector3::One();
|
||||
|
||||
TransformComponent* m_parent = nullptr;
|
||||
std::vector<TransformComponent*> m_children;
|
||||
|
||||
mutable Math::Matrix4x4 m_localToWorldMatrix;
|
||||
mutable Math::Vector3 m_worldPosition;
|
||||
mutable Math::Quaternion m_worldRotation;
|
||||
mutable Math::Vector3 m_worldScale;
|
||||
mutable bool m_dirty = true;
|
||||
int m_siblingIndex = 0;
|
||||
|
||||
friend class GameObject;
|
||||
};
|
||||
|
||||
} // namespace Components
|
||||
} // namespace XCEngine
|
||||
113
engine/include/XCEngine/Scene/Scene.h
Normal file
113
engine/include/XCEngine/Scene/Scene.h
Normal file
@@ -0,0 +1,113 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <XCEngine/Core/Event.h>
|
||||
#include <XCEngine/Components/GameObject.h>
|
||||
|
||||
namespace XCEngine {
|
||||
namespace Components {
|
||||
|
||||
class Scene {
|
||||
public:
|
||||
using GameObjectID = uint64_t;
|
||||
static constexpr GameObjectID INVALID_GAMEOBJECT_ID = 0;
|
||||
|
||||
Scene();
|
||||
explicit Scene(const std::string& name);
|
||||
~Scene();
|
||||
|
||||
const std::string& GetName() const { return m_name; }
|
||||
void SetName(const std::string& name) { m_name = name; }
|
||||
|
||||
bool IsActive() const { return m_active; }
|
||||
void SetActive(bool active) { m_active = active; }
|
||||
|
||||
GameObject* CreateGameObject(const std::string& name, GameObject* parent = nullptr);
|
||||
void DestroyGameObject(GameObject* gameObject);
|
||||
|
||||
GameObject* Find(const std::string& name) const;
|
||||
GameObject* FindGameObjectWithTag(const std::string& tag) const;
|
||||
|
||||
template<typename T>
|
||||
T* FindObjectOfType() const {
|
||||
for (auto* go : GetRootGameObjects()) {
|
||||
if (T* comp = go->GetComponent<T>()) {
|
||||
return comp;
|
||||
}
|
||||
if (T* comp = FindInChildren<T>(go)) {
|
||||
return comp;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::vector<T*> FindObjectsOfType() const {
|
||||
std::vector<T*> results;
|
||||
for (auto* go : GetRootGameObjects()) {
|
||||
if (T* comp = go->GetComponent<T>()) {
|
||||
results.push_back(comp);
|
||||
}
|
||||
FindInChildren<T>(go, results);
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
std::vector<GameObject*> GetRootGameObjects() const;
|
||||
|
||||
void Update(float deltaTime);
|
||||
void FixedUpdate(float fixedDeltaTime);
|
||||
void LateUpdate(float deltaTime);
|
||||
|
||||
void Load(const std::string& filePath);
|
||||
void Save(const std::string& filePath);
|
||||
|
||||
Core::Event<GameObject*>& OnGameObjectCreated() { return m_onGameObjectCreated; }
|
||||
Core::Event<GameObject*>& OnGameObjectDestroyed() { return m_onGameObjectDestroyed; }
|
||||
|
||||
private:
|
||||
GameObject* FindInChildren(GameObject* parent, const std::string& name) const;
|
||||
|
||||
template<typename T>
|
||||
T* FindInChildren(GameObject* parent) const {
|
||||
for (size_t i = 0; i < parent->GetChildCount(); ++i) {
|
||||
GameObject* child = parent->GetChild(i);
|
||||
if (T* comp = child->GetComponent<T>()) {
|
||||
return comp;
|
||||
}
|
||||
if (T* comp = FindInChildren<T>(child)) {
|
||||
return comp;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void FindInChildren(GameObject* parent, std::vector<T*>& results) const {
|
||||
for (size_t i = 0; i < parent->GetChildCount(); ++i) {
|
||||
GameObject* child = parent->GetChild(i);
|
||||
if (T* comp = child->GetComponent<T>()) {
|
||||
results.push_back(comp);
|
||||
}
|
||||
FindInChildren<T>(child, results);
|
||||
}
|
||||
}
|
||||
|
||||
std::string m_name;
|
||||
bool m_active = true;
|
||||
std::unordered_map<GameObjectID, std::unique_ptr<GameObject>> m_gameObjects;
|
||||
std::vector<GameObjectID> m_rootGameObjects;
|
||||
std::unordered_set<GameObjectID> m_gameObjectIDs;
|
||||
|
||||
Core::Event<GameObject*> m_onGameObjectCreated;
|
||||
Core::Event<GameObject*> m_onGameObjectDestroyed;
|
||||
|
||||
friend class GameObject;
|
||||
friend class SceneManager;
|
||||
};
|
||||
|
||||
} // namespace Components
|
||||
} // namespace XCEngine
|
||||
48
engine/include/XCEngine/Scene/SceneManager.h
Normal file
48
engine/include/XCEngine/Scene/SceneManager.h
Normal file
@@ -0,0 +1,48 @@
|
||||
#pragma once
|
||||
|
||||
#include "Scene.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
#include <functional>
|
||||
|
||||
namespace XCEngine {
|
||||
namespace Components {
|
||||
|
||||
class SceneManager {
|
||||
public:
|
||||
static SceneManager& Get();
|
||||
|
||||
Scene* CreateScene(const std::string& name);
|
||||
void LoadScene(const std::string& filePath);
|
||||
void LoadSceneAsync(const std::string& filePath, std::function<void(Scene*)> callback);
|
||||
void UnloadScene(Scene* scene);
|
||||
void UnloadScene(const std::string& sceneName);
|
||||
|
||||
void SetActiveScene(Scene* scene);
|
||||
void SetActiveScene(const std::string& sceneName);
|
||||
Scene* GetActiveScene() const { return m_activeScene; }
|
||||
|
||||
Scene* GetScene(const std::string& name) const;
|
||||
std::vector<Scene*> GetAllScenes() const;
|
||||
|
||||
Core::Event<Scene*>& OnSceneLoaded() { return m_onSceneLoaded; }
|
||||
Core::Event<Scene*>& OnSceneUnloaded() { return m_onSceneUnloaded; }
|
||||
Core::Event<Scene*>& OnActiveSceneChanged() { return m_onActiveSceneChanged; }
|
||||
|
||||
private:
|
||||
SceneManager() = default;
|
||||
~SceneManager() = default;
|
||||
SceneManager(const SceneManager&) = delete;
|
||||
SceneManager& operator=(const SceneManager&) = delete;
|
||||
|
||||
Scene* m_activeScene = nullptr;
|
||||
std::unordered_map<std::string, std::unique_ptr<Scene>> m_scenes;
|
||||
|
||||
Core::Event<Scene*> m_onSceneLoaded;
|
||||
Core::Event<Scene*> m_onSceneUnloaded;
|
||||
Core::Event<Scene*> m_onActiveSceneChanged;
|
||||
};
|
||||
|
||||
} // namespace Components
|
||||
} // namespace XCEngine
|
||||
Reference in New Issue
Block a user