- 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
190 lines
4.4 KiB
C++
190 lines
4.4 KiB
C++
#include "Components/GameObject.h"
|
|
#include "Components/TransformComponent.h"
|
|
#include "Scene/Scene.h"
|
|
|
|
namespace XCEngine {
|
|
namespace Components {
|
|
|
|
GameObject::ID GameObject::s_nextID = 1;
|
|
|
|
GameObject::GameObject()
|
|
: m_name("GameObject") {
|
|
m_id = s_nextID++;
|
|
m_transform = new TransformComponent();
|
|
m_transform->m_gameObject = this;
|
|
}
|
|
|
|
GameObject::GameObject(const std::string& name)
|
|
: m_name(name) {
|
|
m_id = s_nextID++;
|
|
m_transform = new TransformComponent();
|
|
m_transform->m_gameObject = this;
|
|
}
|
|
|
|
GameObject::~GameObject() {
|
|
if (m_transform) {
|
|
delete m_transform;
|
|
m_transform = nullptr;
|
|
}
|
|
m_components.clear();
|
|
}
|
|
|
|
std::unordered_map<GameObject::ID, GameObject*>& GameObject::GetGlobalRegistry() {
|
|
static std::unordered_map<ID, GameObject*> registry;
|
|
return registry;
|
|
}
|
|
|
|
void GameObject::SetParent(GameObject* parent) {
|
|
SetParent(parent, true);
|
|
}
|
|
|
|
void GameObject::SetParent(GameObject* parent, bool worldPositionStays) {
|
|
if (m_parent == parent) {
|
|
return;
|
|
}
|
|
|
|
Math::Vector3 worldPos = worldPositionStays ? GetTransform()->GetPosition() : GetTransform()->GetLocalPosition();
|
|
Math::Quaternion worldRot = worldPositionStays ? GetTransform()->GetRotation() : GetTransform()->GetLocalRotation();
|
|
Math::Vector3 worldScale = worldPositionStays ? GetTransform()->GetScale() : GetTransform()->GetLocalScale();
|
|
|
|
if (m_parent) {
|
|
auto& siblings = m_parent->m_children;
|
|
siblings.erase(std::remove(siblings.begin(), siblings.end(), this), siblings.end());
|
|
}
|
|
|
|
m_parent = parent;
|
|
|
|
if (m_parent) {
|
|
m_parent->m_children.push_back(this);
|
|
}
|
|
|
|
if (worldPositionStays) {
|
|
GetTransform()->SetPosition(worldPos);
|
|
GetTransform()->SetRotation(worldRot);
|
|
GetTransform()->SetScale(worldScale);
|
|
}
|
|
|
|
GetTransform()->SetDirty();
|
|
}
|
|
|
|
GameObject* GameObject::GetChild(size_t index) const {
|
|
if (index < m_children.size()) {
|
|
return m_children[index];
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
std::vector<GameObject*> GameObject::GetChildren() const {
|
|
return m_children;
|
|
}
|
|
|
|
void GameObject::DetachChildren() {
|
|
for (auto* child : m_children) {
|
|
if (child) {
|
|
child->m_parent = nullptr;
|
|
}
|
|
}
|
|
m_children.clear();
|
|
}
|
|
|
|
void GameObject::SetActive(bool active) {
|
|
if (m_activeSelf != active) {
|
|
m_activeSelf = active;
|
|
if (m_parent == nullptr || m_parent->IsActiveInHierarchy()) {
|
|
}
|
|
}
|
|
}
|
|
|
|
bool GameObject::IsActiveInHierarchy() const {
|
|
if (!m_activeSelf) {
|
|
return false;
|
|
}
|
|
if (m_parent) {
|
|
return m_parent->IsActiveInHierarchy();
|
|
}
|
|
return true;
|
|
}
|
|
|
|
GameObject* GameObject::Find(const std::string& name) {
|
|
auto& registry = GetGlobalRegistry();
|
|
for (auto& pair : registry) {
|
|
if (pair.second->GetName() == name) {
|
|
return pair.second;
|
|
}
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
std::vector<GameObject*> GameObject::FindObjectsOfType() {
|
|
auto& registry = GetGlobalRegistry();
|
|
std::vector<GameObject*> result;
|
|
for (auto& pair : registry) {
|
|
result.push_back(pair.second);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
std::vector<GameObject*> GameObject::FindGameObjectsWithTag(const std::string& tag) {
|
|
auto& registry = GetGlobalRegistry();
|
|
std::vector<GameObject*> result;
|
|
for (auto& pair : registry) {
|
|
if (pair.second->GetName() == tag) {
|
|
result.push_back(pair.second);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
void GameObject::Awake() {
|
|
for (auto& comp : m_components) {
|
|
comp->Awake();
|
|
}
|
|
}
|
|
|
|
void GameObject::Start() {
|
|
for (auto& comp : m_components) {
|
|
if (comp->IsEnabled()) {
|
|
comp->Start();
|
|
}
|
|
}
|
|
}
|
|
|
|
void GameObject::Update(float deltaTime) {
|
|
for (auto& comp : m_components) {
|
|
if (comp->IsEnabled()) {
|
|
comp->Update(deltaTime);
|
|
}
|
|
}
|
|
}
|
|
|
|
void GameObject::FixedUpdate() {
|
|
for (auto& comp : m_components) {
|
|
if (comp->IsEnabled()) {
|
|
comp->FixedUpdate();
|
|
}
|
|
}
|
|
}
|
|
|
|
void GameObject::LateUpdate(float deltaTime) {
|
|
for (auto& comp : m_components) {
|
|
if (comp->IsEnabled()) {
|
|
comp->LateUpdate(deltaTime);
|
|
}
|
|
}
|
|
}
|
|
|
|
void GameObject::OnDestroy() {
|
|
for (auto& comp : m_components) {
|
|
comp->OnDestroy();
|
|
}
|
|
}
|
|
|
|
void GameObject::Destroy() {
|
|
OnDestroy();
|
|
if (m_scene) {
|
|
m_scene->DestroyGameObject(this);
|
|
}
|
|
}
|
|
|
|
} // namespace Components
|
|
} // namespace XCEngine
|