Editor: UI panels and GameObject updates

This commit is contained in:
2026-03-25 01:23:08 +08:00
parent dc970d215b
commit c9e459c179
21 changed files with 651 additions and 184 deletions

View File

@@ -8,6 +8,7 @@
#include <unordered_map>
#include <istream>
#include <ostream>
#include <random>
namespace XCEngine {
namespace Components {
@@ -24,9 +25,12 @@ public:
~GameObject();
ID GetID() const { return m_id; }
uint64_t GetUUID() const { return m_uuid; }
const std::string& GetName() const { return m_name; }
void SetName(const std::string& name) { m_name = name; }
void DetachFromParent();
Scene* GetScene() const { return m_scene; }
TransformComponent* GetTransform() { return m_transform; }
@@ -83,6 +87,16 @@ public:
return result;
}
template<typename T>
void RemoveComponent() {
for (auto it = m_components.begin(); it != m_components.end(); ++it) {
if (T* casted = dynamic_cast<T*>(it->get())) {
m_components.erase(it);
return;
}
}
}
template<typename T>
T* GetComponentInChildren() {
T* comp = GetComponent<T>();
@@ -154,6 +168,7 @@ public:
private:
ID m_id = INVALID_ID;
uint64_t m_uuid = 0;
std::string m_name;
bool m_activeSelf = true;

View File

@@ -0,0 +1,26 @@
#pragma once
#include <string>
namespace XCEngine {
namespace Core {
class Layer {
public:
Layer(const std::string& name = "Layer") : m_name(name) {}
virtual ~Layer() = default;
virtual void onAttach() {}
virtual void onDetach() {}
virtual void onUpdate(float dt) {}
virtual void onEvent(void* event) {}
virtual void onImGuiRender() {}
const std::string& getName() const { return m_name; }
protected:
std::string m_name;
};
}
}

View File

@@ -0,0 +1,100 @@
#pragma once
#include "Layer.h"
#include <vector>
#include <algorithm>
#include <memory>
namespace XCEngine {
namespace Core {
class LayerStack {
public:
LayerStack() = default;
~LayerStack() = default;
void pushLayer(std::unique_ptr<Layer> layer);
void pushOverlay(std::unique_ptr<Layer> overlay);
void popLayer(Layer* layer);
void popOverlay(Layer* overlay);
void onUpdate(float dt);
void onEvent(void* event);
void onImGuiRender();
void onAttach();
void onDetach();
std::vector<std::unique_ptr<Layer>>::iterator begin() { return m_layers.begin(); }
std::vector<std::unique_ptr<Layer>>::iterator end() { return m_layers.end(); }
std::vector<std::unique_ptr<Layer>>::reverse_iterator rbegin() { return m_layers.rbegin(); }
std::vector<std::unique_ptr<Layer>>::reverse_iterator rend() { return m_layers.rend(); }
std::vector<std::unique_ptr<Layer>>::const_iterator cbegin() const { return m_layers.begin(); }
std::vector<std::unique_ptr<Layer>>::const_iterator cend() const { return m_layers.end(); }
std::vector<std::unique_ptr<Layer>>::const_reverse_iterator crbegin() const { return m_layers.crbegin(); }
std::vector<std::unique_ptr<Layer>>::const_reverse_iterator crend() const { return m_layers.crend(); }
private:
std::vector<std::unique_ptr<Layer>> m_layers;
unsigned int m_layerInsertIndex = 0;
};
inline void LayerStack::pushLayer(std::unique_ptr<Layer> layer) {
m_layers.emplace(m_layers.begin() + m_layerInsertIndex, std::move(layer));
m_layerInsertIndex++;
}
inline void LayerStack::pushOverlay(std::unique_ptr<Layer> overlay) {
m_layers.emplace_back(std::move(overlay));
}
inline void LayerStack::popLayer(Layer* layer) {
auto it = std::find_if(m_layers.begin(), m_layers.begin() + m_layerInsertIndex,
[layer](const std::unique_ptr<Layer>& ptr) { return ptr.get() == layer; });
if (it != m_layers.begin() + m_layerInsertIndex) {
(*it)->onDetach();
m_layers.erase(it);
m_layerInsertIndex--;
}
}
inline void LayerStack::popOverlay(Layer* overlay) {
auto it = std::find_if(m_layers.begin() + m_layerInsertIndex, m_layers.end(),
[overlay](const std::unique_ptr<Layer>& ptr) { return ptr.get() == overlay; });
if (it != m_layers.end()) {
(*it)->onDetach();
m_layers.erase(it);
}
}
inline void LayerStack::onUpdate(float dt) {
for (auto& layer : m_layers) {
layer->onUpdate(dt);
}
}
inline void LayerStack::onEvent(void* event) {
for (auto& layer : m_layers) {
layer->onEvent(event);
}
}
inline void LayerStack::onImGuiRender() {
for (auto& layer : m_layers) {
layer->onImGuiRender();
}
}
inline void LayerStack::onAttach() {
for (auto& layer : m_layers) {
layer->onAttach();
}
}
inline void LayerStack::onDetach() {
for (auto& layer : m_layers) {
layer->onDetach();
}
}
}
}

View File

@@ -10,6 +10,10 @@ GameObject::ID GameObject::s_nextID = 1;
GameObject::GameObject()
: m_name("GameObject") {
m_id = s_nextID++;
static std::random_device rd;
static std::mt19937_64 gen(rd());
static std::uniform_int_distribution<uint64_t> dis(1, UINT64_MAX);
m_uuid = dis(gen);
m_transform = new TransformComponent();
m_transform->m_gameObject = this;
}
@@ -17,6 +21,10 @@ GameObject::GameObject()
GameObject::GameObject(const std::string& name)
: m_name(name) {
m_id = s_nextID++;
static std::random_device rd;
static std::mt19937_64 gen(rd());
static std::uniform_int_distribution<uint64_t> dis(1, UINT64_MAX);
m_uuid = dis(gen);
m_transform = new TransformComponent();
m_transform->m_gameObject = this;
}
@@ -88,6 +96,27 @@ void GameObject::DetachChildren() {
m_children.clear();
}
void GameObject::DetachFromParent() {
if (m_parent) {
Math::Vector3 worldPos = GetTransform()->GetPosition();
Math::Quaternion worldRot = GetTransform()->GetRotation();
Math::Vector3 worldScale = GetTransform()->GetScale();
auto& siblings = m_parent->m_children;
siblings.erase(std::remove(siblings.begin(), siblings.end(), this), siblings.end());
m_parent = nullptr;
if (m_scene) {
m_scene->m_rootGameObjects.push_back(m_id);
}
GetTransform()->SetPosition(worldPos);
GetTransform()->SetRotation(worldRot);
GetTransform()->SetScale(worldScale);
GetTransform()->SetDirty();
}
}
void GameObject::SetActive(bool active) {
if (m_activeSelf != active) {
m_activeSelf = active;