entity_serialize robustness improvements; entity_remove recursive support;

This commit is contained in:
Turánszki János
2022-02-11 00:08:57 +01:00
parent 6408341827
commit 9ebac82454
5 changed files with 123 additions and 32 deletions
+51 -7
View File
@@ -732,7 +732,7 @@ void EditorComponent::Load()
clearButton.Create("Clear World");
clearButton.SetTooltip("Delete every model from the scene");
clearButton.SetTooltip("Delete everything from the scene. This operation is not undoable!");
clearButton.SetColor(wi::Color(255, 173, 43, 180), wi::gui::WIDGETSTATE::IDLE);
clearButton.SetColor(wi::Color(255, 235, 173, 255), wi::gui::WIDGETSTATE::FOCUS);
clearButton.OnClick([&](wi::gui::EventArgs args) {
@@ -757,6 +757,9 @@ void EditorComponent::Load()
nameWnd.SetEntity(INVALID_ENTITY);
RefreshSceneGraphView();
history.clear();
historyPos = -1;
});
GetGUI().AddWidget(&clearButton);
@@ -848,6 +851,19 @@ void EditorComponent::Load()
sceneGraphView.Create("Scene graph view");
sceneGraphView.OnSelect([this](wi::gui::EventArgs args) {
wi::Archive& archive = AdvanceHistory();
archive << HISTORYOP_SELECTION;
// record PREVIOUS selection state...
archive << translator.selected.size();
for (auto& x : translator.selected)
{
archive << x.entity;
archive << x.position;
archive << x.normal;
archive << x.subsetIndex;
archive << x.distance;
}
translator.selected.clear();
for (int i = 0; i < sceneGraphView.GetItemCount(); ++i)
@@ -861,6 +877,17 @@ void EditorComponent::Load()
}
}
// record NEW selection state...
archive << translator.selected.size();
for (auto& x : translator.selected)
{
archive << x.entity;
archive << x.position;
archive << x.normal;
archive << x.subsetIndex;
archive << x.distance;
}
});
sceneGraphView.SetColor(wi::Color(100, 100, 100, 100), wi::gui::IDLE);
GetGUI().AddWidget(&sceneGraphView);
@@ -1443,11 +1470,12 @@ void EditorComponent::Update(float dt)
{
auto prevSel = translator.selected;
EntitySerializer seri;
clipboard.SetReadModeAndResetPos(false);
clipboard << prevSel.size();
for (auto& x : prevSel)
{
scene.Entity_Serialize(clipboard, x.entity);
scene.Entity_Serialize(clipboard, seri, x.entity, Scene::EntitySerializeFlags::RECURSIVE);
}
}
// Paste
@@ -1456,13 +1484,14 @@ void EditorComponent::Update(float dt)
auto prevSel = translator.selected;
translator.selected.clear();
EntitySerializer seri;
clipboard.SetReadModeAndResetPos(true);
size_t count;
clipboard >> count;
for (size_t i = 0; i < count; ++i)
{
wi::scene::PickResult picked;
picked.entity = scene.Entity_Serialize(clipboard);
picked.entity = scene.Entity_Serialize(clipboard, seri, INVALID_ENTITY, Scene::EntitySerializeFlags::RECURSIVE | Scene::EntitySerializeFlags::KEEP_INTERNAL_ENTITY_REFERENCES);
AddSelected(picked);
}
@@ -1485,12 +1514,13 @@ void EditorComponent::Update(float dt)
// Put Instances
if (clipboard.IsOpen() && hovered.subsetIndex >= 0 && wi::input::Down(wi::input::KEYBOARD_BUTTON_LSHIFT) && wi::input::Press(wi::input::MOUSE_BUTTON_LEFT))
{
EntitySerializer seri;
clipboard.SetReadModeAndResetPos(true);
size_t count;
clipboard >> count;
for (size_t i = 0; i < count; ++i)
{
Entity entity = scene.Entity_Serialize(clipboard);
Entity entity = scene.Entity_Serialize(clipboard, seri, INVALID_ENTITY, Scene::EntitySerializeFlags::RECURSIVE | Scene::EntitySerializeFlags::KEEP_INTERNAL_ENTITY_REFERENCES);
TransformComponent* transform = scene.transforms.GetComponent(entity);
if (transform != nullptr)
{
@@ -1532,9 +1562,10 @@ void EditorComponent::Update(float dt)
{
archive << x.entity;
}
EntitySerializer seri;
for (auto& x : translator.selected)
{
scene.Entity_Serialize(archive, x.entity);
scene.Entity_Serialize(archive, seri, x.entity);
}
for (auto& x : translator.selected)
{
@@ -2233,7 +2264,18 @@ void EditorComponent::PushToSceneGraphView(wi::ecs::Entity entity, int level)
item.selected = IsSelected(entity);
item.open = scenegraphview_opened_items.count(entity) != 0;
const NameComponent* name = scene.names.GetComponent(entity);
item.name = name == nullptr ? std::to_string(entity) : name->name;
if (name == nullptr)
{
item.name = "[no_name] " + std::to_string(entity);
}
else if(name->name.empty())
{
item.name = "[name_empty] " + std::to_string(entity);
}
else
{
item.name = name->name;
}
sceneGraphView.AddItem(item);
scenegraphview_added_items.insert(entity);
@@ -2427,9 +2469,11 @@ void EditorComponent::ConsumeHistoryOperation(bool undo)
if (undo)
{
EntitySerializer seri;
seri.allow_remap = false;
for (size_t i = 0; i < count; ++i)
{
scene.Entity_Serialize(archive);
scene.Entity_Serialize(archive, seri);
}
}
else
+27 -10
View File
@@ -1983,14 +1983,31 @@ namespace wi::scene
bounds = AABB::Merge(bounds, other.bounds);
}
void Scene::Entity_Remove(Entity entity)
void Scene::Entity_Remove(Entity entity, bool recursive)
{
Component_Detach(entity); // special case, this will also remove entity from hierarchy but also do more!
if (recursive)
{
wi::vector<Entity> entities_to_remove;
for (size_t i = 0; i < hierarchy.GetCount(); ++i)
{
const HierarchyComponent& hier = hierarchy[i];
if (hier.parentID == entity)
{
Entity child = hierarchy.GetEntity(i);
entities_to_remove.push_back(child);
}
}
for (auto& child : entities_to_remove)
{
Entity_Remove(child);
}
}
names.Remove(entity);
layers.Remove(entity);
transforms.Remove(entity);
prev_transforms.Remove(entity);
hierarchy.Remove(entity);
materials.Remove(entity);
meshes.Remove(entity);
impostors.Remove(entity);
@@ -2030,14 +2047,15 @@ namespace wi::scene
Entity Scene::Entity_Duplicate(Entity entity)
{
wi::Archive archive;
EntitySerializer seri;
// First write the root entity to staging area:
archive.SetReadModeAndResetPos(false);
Entity_Serialize(archive, entity);
Entity_Serialize(archive, seri, entity, EntitySerializeFlags::RECURSIVE);
// Then deserialize root:
archive.SetReadModeAndResetPos(true);
Entity root = Entity_Serialize(archive);
Entity root = Entity_Serialize(archive, seri, INVALID_ENTITY, EntitySerializeFlags::RECURSIVE | EntitySerializeFlags::KEEP_INTERNAL_ENTITY_REFERENCES);
return root;
}
@@ -2410,11 +2428,9 @@ namespace wi::scene
if (channel.path == AnimationComponent::AnimationChannel::Path::WEIGHTS)
{
ObjectComponent* object = objects.GetComponent(channel.target);
assert(object != nullptr);
if (object == nullptr)
continue;
target_mesh = meshes.GetComponent(object->meshID);
assert(target_mesh != nullptr);
if (target_mesh == nullptr)
continue;
animation.morph_weights_temp.resize(target_mesh->targets.size());
@@ -2422,7 +2438,6 @@ namespace wi::scene
else
{
target_transform = transforms.GetComponent(channel.target);
assert(target_transform != nullptr);
if (target_transform == nullptr)
continue;
transform = *target_transform;
@@ -2936,10 +2951,12 @@ namespace wi::scene
int boneIndex = 0;
for (Entity boneEntity : armature.boneCollection)
{
const TransformComponent& bone = *transforms.GetComponent(boneEntity);
const TransformComponent* bone = transforms.GetComponent(boneEntity);
if (bone == nullptr)
continue;
XMMATRIX B = XMLoadFloat4x4(&armature.inverseBindMatrices[boneIndex]);
XMMATRIX W = XMLoadFloat4x4(&bone.world);
XMMATRIX W = XMLoadFloat4x4(&bone->world);
XMMATRIX M = B * W * R;
XMFLOAT4X4 mat;
@@ -2947,7 +2964,7 @@ namespace wi::scene
armature.boneData[boneIndex++].Create(mat);
const float bone_radius = 1;
XMFLOAT3 bonepos = bone.GetPosition();
XMFLOAT3 bonepos = bone->GetPosition();
AABB boneAABB;
boneAABB.createFromHalfWidth(bonepos, XMFLOAT3(bone_radius, bone_radius, bone_radius));
_min = wi::math::Min(_min, boneAABB._min);
+26 -4
View File
@@ -1376,16 +1376,33 @@ namespace wi::scene
// The contents of the other scene will be lost (and moved to this)!
void Merge(Scene& other);
// Removes a specific entity from the scene (if it exists):
void Entity_Remove(wi::ecs::Entity entity);
// Removes (deletes) a specific entity from the scene (if it exists):
// recursive : also removes children if true
void Entity_Remove(wi::ecs::Entity entity, bool recursive = true);
// Finds the first entity by the name (if it exists, otherwise returns INVALID_ENTITY):
wi::ecs::Entity Entity_FindByName(const std::string& name);
// Duplicates all of an entity's components and creates a new entity with them (recursively keeps hierarchy):
wi::ecs::Entity Entity_Duplicate(wi::ecs::Entity entity);
enum class EntitySerializeFlags
{
NONE = 0,
RECURSIVE = 1 << 0, // children entities will be also serialized
KEEP_INTERNAL_ENTITY_REFERENCES = 1 << 1, // entity handles inside components will be kept intact, they won't use remapping of wi::ecs::EntitySerializer
};
// Serializes entity and all of its components to archive:
// archive : archive used for serializing data
// seri : serializer state for entity component system
// entity : if archive is in write mode, this is the entity to serialize. If archive is in read mode, it should be INVALID_ENTITY
// flags : specify options as EntitySerializeFlags bits to control internal behaviour
//
// Returns either the new entity that was read, or the original entity that was written
// This serialization is recursive and serializes entity hierarchy as well
wi::ecs::Entity Entity_Serialize(wi::Archive& archive, wi::ecs::Entity entity = wi::ecs::INVALID_ENTITY);
wi::ecs::Entity Entity_Serialize(
wi::Archive& archive,
wi::ecs::EntitySerializer& seri,
wi::ecs::Entity entity = wi::ecs::INVALID_ENTITY,
EntitySerializeFlags flags = EntitySerializeFlags::RECURSIVE
);
wi::ecs::Entity Entity_CreateMaterial(
const std::string& name
@@ -1538,3 +1555,8 @@ namespace wi::scene
SceneIntersectSphereResult SceneIntersectCapsule(const wi::primitive::Capsule& capsule, uint32_t renderTypeMask = wi::enums::RENDERTYPE_OPAQUE, uint32_t layerMask = ~0, const Scene& scene = GetScene());
}
template<>
struct enable_bitmask_operators<wi::scene::Scene::EntitySerializeFlags> {
static const bool enable = true;
};
+18 -10
View File
@@ -1362,15 +1362,20 @@ namespace wi::scene
wi::backlog::post("Scene serialize took " + std::to_string(timer.elapsed_seconds()) + " sec");
}
Entity Scene::Entity_Serialize(wi::Archive& archive, Entity entity)
Entity Scene::Entity_Serialize(
wi::Archive& archive,
EntitySerializer& seri,
Entity entity,
EntitySerializeFlags flags
)
{
EntitySerializer seri;
SerializeEntity(archive, entity, seri);
// From this point, we will not remap the entities,
// to retain internal entity references inside components:
seri.allow_remap = false;
bool restore_remap = seri.allow_remap;
if (has_flag(flags, EntitySerializeFlags::KEEP_INTERNAL_ENTITY_REFERENCES))
{
seri.allow_remap = false;
}
if (archive.IsReadMode())
{
@@ -1641,14 +1646,15 @@ namespace wi::scene
}
}
if (archive.GetVersion() >= 72)
if (archive.GetVersion() >= 72 && has_flag(flags, EntitySerializeFlags::RECURSIVE))
{
// serialize children:
seri.allow_remap = restore_remap;
size_t childCount = 0;
archive >> childCount;
for (size_t i = 0; i < childCount; ++i)
{
Entity child = Entity_Serialize(archive);
Entity child = Entity_Serialize(archive, seri, INVALID_ENTITY, flags);
if (child != INVALID_ENTITY)
{
HierarchyComponent* hier = hierarchy.GetComponent(child);
@@ -2016,9 +2022,10 @@ namespace wi::scene
}
}
if (archive.GetVersion() >= 72)
if (archive.GetVersion() >= 72 && has_flag(flags, EntitySerializeFlags::RECURSIVE))
{
// Recursive serialization for all children:
seri.allow_remap = restore_remap;
wi::vector<Entity> children;
for (size_t i = 0; i < hierarchy.GetCount(); ++i)
{
@@ -2032,11 +2039,12 @@ namespace wi::scene
archive << children.size();
for (Entity child : children)
{
Entity_Serialize(archive, child);
Entity_Serialize(archive, seri, child, flags);
}
}
}
seri.allow_remap = restore_remap;
return entity;
}
+1 -1
View File
@@ -9,7 +9,7 @@ namespace wi::version
// minor features, major updates, breaking compatibility changes
const int minor = 60;
// minor bug fixes, alterations, refactors, updates
const int revision = 25;
const int revision = 26;
const std::string version_string = std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(revision);