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:
151
engine/src/Scene/Scene.cpp
Normal file
151
engine/src/Scene/Scene.cpp
Normal file
@@ -0,0 +1,151 @@
|
||||
#include "Scene/Scene.h"
|
||||
#include "Components/GameObject.h"
|
||||
|
||||
namespace XCEngine {
|
||||
namespace Components {
|
||||
|
||||
Scene::Scene()
|
||||
: m_name("Untitled") {
|
||||
}
|
||||
|
||||
Scene::Scene(const std::string& name)
|
||||
: m_name(name) {
|
||||
}
|
||||
|
||||
Scene::~Scene() {
|
||||
m_gameObjects.clear();
|
||||
}
|
||||
|
||||
GameObject* Scene::CreateGameObject(const std::string& name, GameObject* parent) {
|
||||
auto gameObject = std::make_unique<GameObject>(name);
|
||||
GameObject* ptr = gameObject.get();
|
||||
|
||||
m_gameObjectIDs.insert(ptr->m_id);
|
||||
m_gameObjects.emplace(ptr->m_id, std::move(gameObject));
|
||||
|
||||
if (parent) {
|
||||
ptr->SetParent(parent);
|
||||
} else {
|
||||
m_rootGameObjects.push_back(ptr->m_id);
|
||||
}
|
||||
|
||||
ptr->m_scene = this;
|
||||
ptr->Awake();
|
||||
|
||||
m_onGameObjectCreated.Invoke(ptr);
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void Scene::DestroyGameObject(GameObject* gameObject) {
|
||||
if (!gameObject || gameObject->m_scene != this) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto* child : gameObject->GetChildren()) {
|
||||
DestroyGameObject(child);
|
||||
}
|
||||
|
||||
if (gameObject->m_parent) {
|
||||
auto& siblings = gameObject->m_parent->m_children;
|
||||
siblings.erase(std::remove(siblings.begin(), siblings.end(), gameObject), siblings.end());
|
||||
} else {
|
||||
m_rootGameObjects.erase(
|
||||
std::remove(m_rootGameObjects.begin(), m_rootGameObjects.end(), gameObject->m_id),
|
||||
m_rootGameObjects.end()
|
||||
);
|
||||
}
|
||||
|
||||
m_onGameObjectDestroyed.Invoke(gameObject);
|
||||
|
||||
gameObject->OnDestroy();
|
||||
|
||||
m_gameObjectIDs.erase(gameObject->m_id);
|
||||
m_gameObjects.erase(gameObject->m_id);
|
||||
}
|
||||
|
||||
GameObject* Scene::Find(const std::string& name) const {
|
||||
for (auto* go : GetRootGameObjects()) {
|
||||
if (go->GetName() == name) {
|
||||
return go;
|
||||
}
|
||||
GameObject* found = FindInChildren(go, name);
|
||||
if (found) {
|
||||
return found;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
GameObject* Scene::FindInChildren(GameObject* parent, const std::string& name) const {
|
||||
for (size_t i = 0; i < parent->GetChildCount(); ++i) {
|
||||
GameObject* child = parent->GetChild(i);
|
||||
if (child->GetName() == name) {
|
||||
return child;
|
||||
}
|
||||
GameObject* found = FindInChildren(child, name);
|
||||
if (found) {
|
||||
return found;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
GameObject* Scene::FindGameObjectWithTag(const std::string& tag) const {
|
||||
for (auto* go : GetRootGameObjects()) {
|
||||
if (go->GetName() == tag) {
|
||||
return go;
|
||||
}
|
||||
GameObject* found = FindInChildren(go, tag);
|
||||
if (found) {
|
||||
return found;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::vector<GameObject*> Scene::GetRootGameObjects() const {
|
||||
std::vector<GameObject*> result;
|
||||
for (auto id : m_rootGameObjects) {
|
||||
auto it = m_gameObjects.find(id);
|
||||
if (it != m_gameObjects.end()) {
|
||||
result.push_back(it->second.get());
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void Scene::Update(float deltaTime) {
|
||||
for (auto* go : GetRootGameObjects()) {
|
||||
if (go->IsActiveInHierarchy()) {
|
||||
go->Update(deltaTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Scene::FixedUpdate(float fixedDeltaTime) {
|
||||
for (auto* go : GetRootGameObjects()) {
|
||||
if (go->IsActiveInHierarchy()) {
|
||||
go->FixedUpdate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Scene::LateUpdate(float deltaTime) {
|
||||
for (auto* go : GetRootGameObjects()) {
|
||||
if (go->IsActiveInHierarchy()) {
|
||||
go->LateUpdate(deltaTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Scene::Load(const std::string& filePath) {
|
||||
m_gameObjects.clear();
|
||||
m_rootGameObjects.clear();
|
||||
}
|
||||
|
||||
void Scene::Save(const std::string& filePath) {
|
||||
}
|
||||
|
||||
} // namespace Components
|
||||
} // namespace XCEngine
|
||||
116
engine/src/Scene/SceneManager.cpp
Normal file
116
engine/src/Scene/SceneManager.cpp
Normal file
@@ -0,0 +1,116 @@
|
||||
#include "Scene/SceneManager.h"
|
||||
|
||||
namespace XCEngine {
|
||||
namespace Components {
|
||||
|
||||
SceneManager& SceneManager::Get() {
|
||||
static SceneManager instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
Scene* SceneManager::CreateScene(const std::string& name) {
|
||||
auto scene = std::make_unique<Scene>(name);
|
||||
Scene* ptr = scene.get();
|
||||
m_scenes[name] = std::move(scene);
|
||||
|
||||
if (!m_activeScene) {
|
||||
m_activeScene = ptr;
|
||||
}
|
||||
|
||||
m_onSceneLoaded.Invoke(ptr);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void SceneManager::LoadScene(const std::string& filePath) {
|
||||
auto scene = std::make_unique<Scene>();
|
||||
scene->Load(filePath);
|
||||
Scene* ptr = scene.get();
|
||||
|
||||
std::string name = filePath;
|
||||
size_t pos = name.find_last_of("/\\");
|
||||
if (pos != std::string::npos) {
|
||||
name = name.substr(pos + 1);
|
||||
}
|
||||
pos = name.find_last_of('.');
|
||||
if (pos != std::string::npos) {
|
||||
name = name.substr(0, pos);
|
||||
}
|
||||
|
||||
m_scenes[name] = std::move(scene);
|
||||
m_onSceneLoaded.Invoke(ptr);
|
||||
}
|
||||
|
||||
void SceneManager::LoadSceneAsync(const std::string& filePath, std::function<void(Scene*)> callback) {
|
||||
LoadScene(filePath);
|
||||
if (callback) {
|
||||
Scene* scene = GetScene(filePath);
|
||||
callback(scene);
|
||||
}
|
||||
}
|
||||
|
||||
void SceneManager::UnloadScene(Scene* scene) {
|
||||
if (!scene) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_activeScene == scene) {
|
||||
m_activeScene = nullptr;
|
||||
}
|
||||
|
||||
auto it = m_scenes.begin();
|
||||
while (it != m_scenes.end()) {
|
||||
if (it->second.get() == scene) {
|
||||
m_onSceneUnloaded.Invoke(scene);
|
||||
it = m_scenes.erase(it);
|
||||
break;
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_activeScene == nullptr && !m_scenes.empty()) {
|
||||
m_activeScene = m_scenes.begin()->second.get();
|
||||
m_onActiveSceneChanged.Invoke(m_activeScene);
|
||||
}
|
||||
}
|
||||
|
||||
void SceneManager::UnloadScene(const std::string& sceneName) {
|
||||
auto it = m_scenes.find(sceneName);
|
||||
if (it != m_scenes.end()) {
|
||||
UnloadScene(it->second.get());
|
||||
}
|
||||
}
|
||||
|
||||
void SceneManager::SetActiveScene(Scene* scene) {
|
||||
if (m_activeScene == scene) {
|
||||
return;
|
||||
}
|
||||
m_activeScene = scene;
|
||||
m_onActiveSceneChanged.Invoke(scene);
|
||||
}
|
||||
|
||||
void SceneManager::SetActiveScene(const std::string& sceneName) {
|
||||
auto it = m_scenes.find(sceneName);
|
||||
if (it != m_scenes.end()) {
|
||||
SetActiveScene(it->second.get());
|
||||
}
|
||||
}
|
||||
|
||||
Scene* SceneManager::GetScene(const std::string& name) const {
|
||||
auto it = m_scenes.find(name);
|
||||
if (it != m_scenes.end()) {
|
||||
return it->second.get();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::vector<Scene*> SceneManager::GetAllScenes() const {
|
||||
std::vector<Scene*> result;
|
||||
for (auto& pair : m_scenes) {
|
||||
result.push_back(pair.second.get());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace Components
|
||||
} // namespace XCEngine
|
||||
Reference in New Issue
Block a user