entity_serialize robustness improvements; entity_remove recursive support;
This commit is contained in:
+51
-7
@@ -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
@@ -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
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user