Compare commits
2 Commits
Importer
...
EditorUndo
| Author | SHA1 | Date | |
|---|---|---|---|
| 73064c7257 | |||
| fa78991795 |
@@ -65,6 +65,8 @@ public:
|
||||
iterator end() const;
|
||||
size_t size() const;
|
||||
|
||||
std::size_t MemoryUsage() const;
|
||||
|
||||
//Dumps information about what the pool memory looks like right now
|
||||
//into an output stream (e.g. file/std::cout, anything that has an operator<<)
|
||||
//Interpret the data in the memory as InterpretType.
|
||||
|
||||
@@ -27,6 +27,7 @@ struct EntityWrapper
|
||||
bool HasComponent(const std::string& componentType);
|
||||
void AttachComponent(const char* componentName);
|
||||
EntityWrapper Parent();
|
||||
EntityWrapper BaseParent();
|
||||
EntityWrapper FirstChildByName(const std::string& name);
|
||||
EntityWrapper FirstParentWithComponent(const std::string& componentType);
|
||||
EntityWrapper Clone(EntityWrapper parent = EntityWrapper::Invalid);
|
||||
|
||||
@@ -194,6 +194,11 @@ public:
|
||||
return m_ExtraMemory.size();
|
||||
}
|
||||
|
||||
std::size_t MemoryUsage() const
|
||||
{
|
||||
return size() * m_Stride;
|
||||
}
|
||||
|
||||
//Dumps information about what the pool memory looks like right now
|
||||
//into an output stream (e.g. file/std::cout, anything that has an operator<<)
|
||||
//Interpret the data in the memory as InterpretType.
|
||||
|
||||
@@ -18,7 +18,7 @@ public:
|
||||
World(const World& other);
|
||||
|
||||
// Create empty entity
|
||||
EntityID CreateEntity(EntityID parent = 0);
|
||||
EntityID CreateEntity(EntityID parent = EntityID_Invalid);
|
||||
// Delete entity and all components within
|
||||
void DeleteEntity(EntityID entity);
|
||||
// Check if an entity exists
|
||||
@@ -50,6 +50,9 @@ public:
|
||||
// Get the textual name of an entity
|
||||
std::string GetName(EntityID entity) const;
|
||||
|
||||
// Get an approximate number for component pool memory usage
|
||||
std::size_t MemoryUsage() const;
|
||||
|
||||
private:
|
||||
EventBroker* m_EventBroker = nullptr;
|
||||
EntityID m_CurrentEntityID = 0;
|
||||
|
||||
@@ -91,7 +91,13 @@ public:
|
||||
// Called when the user selects a widget space.
|
||||
typedef std::function<void(WidgetSpace)> OnWidgetSpace_t;
|
||||
void SetWidgetSpaceCallback(OnWidgetSpace_t f) { m_OnWidgetSpace = f; }
|
||||
|
||||
// Called when anything is modified making the world dirty
|
||||
// @param EntityWrapper The entity that was changed and marked as dirty
|
||||
typedef std::function<void(EntityWrapper)> OnDirty_t;
|
||||
void SetDirtyCallback(OnDirty_t f) { m_OnDirty = f; }
|
||||
// Called when the user wishes to undo
|
||||
typedef std::function<void()> OnUndo_t;
|
||||
void SetUndoCallback(OnUndo_t f) { m_OnUndo = f; }
|
||||
private:
|
||||
World* m_World;
|
||||
EventBroker* m_EventBroker;
|
||||
@@ -132,6 +138,8 @@ private:
|
||||
OnWidgetMode_t m_OnWidgetMode = nullptr;
|
||||
OnWidgetSpace_t m_OnWidgetSpace = nullptr;
|
||||
OnEntityPaste_t m_OnEntityPaste = nullptr;
|
||||
OnDirty_t m_OnDirty = nullptr;
|
||||
OnUndo_t m_OnUndo = nullptr;
|
||||
|
||||
// Events
|
||||
EventRelay<EditorGUI, Events::KeyDown> m_EKeyDown;
|
||||
|
||||
@@ -36,6 +36,7 @@ private:
|
||||
EditorCameraInputController<EditorSystem>* m_EditorCameraInputController;
|
||||
EditorGUI* m_EditorGUI;
|
||||
EditorStats* m_EditorStats;
|
||||
std::vector<World> m_UndoLevels;
|
||||
|
||||
// State
|
||||
double m_LastTime = 0.f;
|
||||
@@ -44,6 +45,7 @@ private:
|
||||
EditorGUI::WidgetSpace m_WidgetSpace = EditorGUI::WidgetSpace::Global;
|
||||
EntityWrapper m_Widget = EntityWrapper::Invalid;
|
||||
EntityWrapper m_CurrentSelection = EntityWrapper::Invalid;
|
||||
bool m_SaveUndoLevel = false; // Only save undo state once per update
|
||||
|
||||
// Utility functions
|
||||
EntityWrapper importEntity(EntityWrapper parent, boost::filesystem::path filePath);
|
||||
@@ -60,6 +62,8 @@ private:
|
||||
void OnComponentAttach(EntityWrapper entity, const std::string& componentType);
|
||||
void OnComponentDelete(EntityWrapper entity, const std::string& componentType);
|
||||
void OnWidgetSpace(EditorGUI::WidgetSpace widgetSpace);
|
||||
void OnDirty(EntityWrapper entity);
|
||||
void OnUndo();
|
||||
|
||||
// Events
|
||||
EventRelay<EditorSystem, Events::MousePress> m_EMousePress;
|
||||
|
||||
@@ -5,6 +5,20 @@
|
||||
<c:Transform/>
|
||||
</Components>
|
||||
|
||||
<Children/>
|
||||
<Children>
|
||||
<Entity>
|
||||
<Components>
|
||||
<c:Transform/>
|
||||
</Components>
|
||||
<Children>
|
||||
<Entity>
|
||||
<Components>
|
||||
<c:Transform/>
|
||||
</Components>
|
||||
<Children/>
|
||||
</Entity>
|
||||
</Children>
|
||||
</Entity>
|
||||
</Children>
|
||||
|
||||
</Entity>
|
||||
|
||||
@@ -112,6 +112,11 @@ size_t ComponentPool::size() const
|
||||
return m_Pool.size();
|
||||
}
|
||||
|
||||
std::size_t ComponentPool::MemoryUsage() const
|
||||
{
|
||||
return m_Pool.MemoryUsage();
|
||||
}
|
||||
|
||||
template <typename InterpretType /*= char*/>
|
||||
void ComponentPool::Dump() const
|
||||
{
|
||||
|
||||
@@ -34,6 +34,15 @@ EntityWrapper EntityWrapper::Parent()
|
||||
}
|
||||
}
|
||||
|
||||
EntityWrapper EntityWrapper::BaseParent()
|
||||
{
|
||||
EntityWrapper baseParent = Parent();
|
||||
while (baseParent.Parent().Valid()) {
|
||||
baseParent = baseParent.Parent();
|
||||
}
|
||||
return baseParent;
|
||||
}
|
||||
|
||||
EntityWrapper EntityWrapper::FirstChildByName(const std::string& name)
|
||||
{
|
||||
return firstChildByNameRecursive(name, this->ID);
|
||||
|
||||
@@ -151,6 +151,17 @@ std::string World::GetName(EntityID entity) const
|
||||
}
|
||||
}
|
||||
|
||||
std::size_t World::MemoryUsage() const
|
||||
{
|
||||
std::size_t mem = 0;
|
||||
|
||||
for (auto& kv : m_ComponentPools) {
|
||||
mem += kv.second->MemoryUsage();
|
||||
}
|
||||
|
||||
return mem;
|
||||
}
|
||||
|
||||
EntityID World::generateEntityID()
|
||||
{
|
||||
// TODO: Make EntityID generation smarter
|
||||
|
||||
@@ -602,6 +602,15 @@ bool EditorGUI::OnKeyDown(const Events::KeyDown& e)
|
||||
m_CopyTarget = m_CurrentSelection;
|
||||
}
|
||||
|
||||
if (e.ModCtrl && e.KeyCode == GLFW_KEY_Z) {
|
||||
if (m_OnUndo != nullptr) {
|
||||
m_OnUndo();
|
||||
if (!m_CurrentSelection.Valid()) {
|
||||
SelectEntity(EntityWrapper::Invalid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (e.ModCtrl && e.KeyCode == GLFW_KEY_V) {
|
||||
if (m_OnEntityPaste != nullptr) {
|
||||
EntityWrapper copy = m_OnEntityPaste(m_CopyTarget, m_CurrentSelection);
|
||||
@@ -774,13 +783,13 @@ bool EditorGUI::compareCharArray(const char* c1, const char* c2)
|
||||
|
||||
void EditorGUI::SetDirty(EntityWrapper entity)
|
||||
{
|
||||
EntityWrapper baseParent = entity;
|
||||
while (baseParent.Parent().Valid()) {
|
||||
baseParent = baseParent.Parent();
|
||||
}
|
||||
EntityWrapper baseParent = entity.BaseParent();
|
||||
if (m_EntityFiles.find(baseParent) != m_EntityFiles.end()) {
|
||||
m_EntityFiles.at(baseParent).Dirty = true;
|
||||
}
|
||||
if (m_OnDirty != nullptr) {
|
||||
m_OnDirty(entity);
|
||||
}
|
||||
}
|
||||
|
||||
void EditorGUI::entityImport(World* world)
|
||||
@@ -830,6 +839,7 @@ void EditorGUI::entityCreate(World* world, EntityWrapper parent)
|
||||
parent.World = world;
|
||||
}
|
||||
EntityWrapper newEntity = m_OnEntityCreate(parent);
|
||||
SetDirty(newEntity);
|
||||
SelectEntity(newEntity);
|
||||
}
|
||||
}
|
||||
@@ -845,9 +855,9 @@ void EditorGUI::entityDelete(EntityWrapper entity)
|
||||
if (boost::any_cast<EntityWrapper>(m_ModalData[modalName]) == entity) {
|
||||
EntityWrapper parent = entity.Parent();
|
||||
if (m_OnEntityDelete != nullptr) {
|
||||
SetDirty(entity);
|
||||
m_OnEntityDelete(entity);
|
||||
m_EntityFiles.erase(entity);
|
||||
SetDirty(parent);
|
||||
}
|
||||
if (!m_CurrentSelection.Valid()) {
|
||||
SelectEntity(parent);
|
||||
@@ -864,8 +874,8 @@ void EditorGUI::entityChangeParent(EntityWrapper entity, EntityWrapper parent)
|
||||
}
|
||||
|
||||
if (m_OnEntityChangeParent != nullptr) {
|
||||
SetDirty(entity);
|
||||
m_OnEntityChangeParent(entity, parent);
|
||||
SetDirty(entity);
|
||||
LOG_DEBUG("Changed parent of %i to %i", entity.ID, parent.ID);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,6 +33,8 @@ EditorSystem::EditorSystem(SystemParams params, IRenderer* renderer, RenderFrame
|
||||
m_EditorGUI->SetComponentDeleteCallback(std::bind(&EditorSystem::OnComponentDelete, this, std::placeholders::_1, std::placeholders::_2));
|
||||
m_EditorGUI->SetWidgetModeCallback(std::bind(&EditorSystem::setWidgetMode, this, std::placeholders::_1));
|
||||
m_EditorGUI->SetWidgetSpaceCallback(std::bind(&EditorSystem::OnWidgetSpace, this, std::placeholders::_1));
|
||||
m_EditorGUI->SetDirtyCallback(std::bind(&EditorSystem::OnDirty, this, std::placeholders::_1));
|
||||
m_EditorGUI->SetUndoCallback(std::bind(&EditorSystem::OnUndo, this));
|
||||
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EMousePress, &EditorSystem::OnMousePress);
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EWidgetDelta, &EditorSystem::OnWidgetDelta);
|
||||
@@ -87,6 +89,11 @@ void EditorSystem::Update(double dt)
|
||||
glm::vec3& pos = cameraTransform["Position"];
|
||||
pos += m_EditorCameraInputController->Movement() * glm::inverse(glm::quat(ori)) * (float)actualDelta;
|
||||
}
|
||||
|
||||
if (m_SaveUndoLevel) {
|
||||
m_UndoLevels.push_back(*m_World);
|
||||
m_SaveUndoLevel = false;
|
||||
}
|
||||
}
|
||||
|
||||
void EditorSystem::Enable()
|
||||
@@ -185,6 +192,19 @@ void EditorSystem::OnWidgetSpace(EditorGUI::WidgetSpace widgetSpace)
|
||||
m_WidgetSpace = widgetSpace;
|
||||
}
|
||||
|
||||
void EditorSystem::OnDirty(EntityWrapper entity)
|
||||
{
|
||||
m_SaveUndoLevel = true;
|
||||
}
|
||||
|
||||
void EditorSystem::OnUndo()
|
||||
{
|
||||
// The last "undo level" is always the most recent change
|
||||
if (m_UndoLevels.size() >= 2) {
|
||||
*m_World = m_UndoLevels.at(m_UndoLevels.size() - 2);
|
||||
}
|
||||
}
|
||||
|
||||
bool EditorSystem::OnMousePress(const Events::MousePress& e)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
||||
Reference in New Issue
Block a user