f0e6841ca8
The EntityOutlinerListModel was violating the QAbstractItemModel contract in a few cases, as reported by `QAbstractItemModelTester`. The important ones causing issues were: - Entry order was not guaranteed, leading to model indices pointing at invalid data - Parent/child relationships could be temporarily invalid due to a change I made in EditorEntityModel::RemoveEntity to try to avoid an unnecessary reparent operation - as it turned out, the parent/child data was being cached even for recreated entities and not clearing child data could cause issues - `EntityOutlinerListModel::ProcessEntityUpdates` was emitting data changed between two indices that didn't necessarily share a parent, which is [undefined behavior](https://doc.qt.io/qt-5/qabstractitemmodel.html#dataChanged) The other reported issues (that weren't really causing issues with `QTreeView`) were: - The root index had flags other than `Qt::ItemIsDropEnabled` - `rowCount` showed all columns as having children - `parent` showed indices as being parented to a non-0 column This change introduces fixes for the above issues, namely: - Reverts my change to `EditorEntityModel::RemoveEntity` to ensure we don't have invalid parent/child references sitting in the cache - Ensures `EditorEntityModelEntry` child ordering is guaranteed sorted by EntityId, to prevent the `EntityOutlinerListModel` from having indices pointed at invalid data*. - Fixes various model sanity issues, such as `rowCount` being 0 for indices with a non-0 column Two unit tests were added to reproduce the invalid behavior and validate the fix: TestCreateFlatHierarchyUndoAndRedoWorks and TestCreateNestedHierarchyUndoAndRedoWorks This change focuses on correctness over performance. My subjective in-Editor outliner experience is about the same, but it may be worthwhile to expand the test coverage with a benchmarking suite to look into areas for optimization. *As a rough illustration of the previous child ordering behavior, consider the following entity hierarchy: ``` Root (EID 9999) |_ Child1 (EID 2) |_ Child2 (EID 3) |_ Child3 (EID 4) ``` With an representations like the following pseudocode: ``` // EditorEntityModel representation EditorEntityModelEntry root; root.children[0] = 2; root.children[1] = 3; root.children[2] = 4; // EditorOutlinerListModel representation // row, column, user data (64 bit uint) child1 = QModelIndex(0, 0, 2) child2 = QModelIndex(1, 0, 3) child3 = QModelIndex(2, 0, 4) ``` When removing a child, the `EditorEntityModel` used to do roughly the following: ``` // Swap and pop the last child int indexToRemove = 0; swap(root.children[indexToRemove], root.children[root.children.size() - 1]); root.children.resize(root.children.size() - 1); model.notifyRemoved(root, indexToRemove); // model removes the row indicated // Leading to this EditorEntityModel state root.children[0] = 4; root.children[1] = 3; // And this EntityOutlinerListModel state, note that the row indices are swapped from the indices in the backing storage child2 = QModelIndex(0, 0, 3) child3 = QModelIndex(1, 0, 4) ``` A QModelIndex having a row that doesn't match its underlying data is undefined behavior, and was the source of an intermittent crash in our `QSortFilterProxyModel` as subsequent updates to the wrong row led to an invalid proxy state. Signed-off-by: nvsickle <nvsickle@amazon.com>
136 lines
4.8 KiB
CMake
136 lines
4.8 KiB
CMake
#
|
|
# Copyright (c) Contributors to the Open 3D Engine Project.
|
|
# For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
|
#
|
|
# SPDX-License-Identifier: Apache-2.0 OR MIT
|
|
#
|
|
#
|
|
|
|
set(FILES
|
|
Main.cpp
|
|
ArchiveTests.cpp
|
|
AssetFileInfoListComparison.cpp
|
|
AssetSeedManager.cpp
|
|
AssetSystemMocks.h
|
|
BoundsTestComponent.cpp
|
|
BoundsTestComponent.h
|
|
ComponentAdapterTests.cpp
|
|
ComponentAddRemove.cpp
|
|
ComponentModeTestDoubles.cpp
|
|
ComponentModeTestDoubles.h
|
|
ComponentModeTestFixture.cpp
|
|
ComponentModeTestFixture.h
|
|
ComponentModeTests.cpp
|
|
EditorTransformComponentSelectionTests.cpp
|
|
EditorVertexSelectionTests.cpp
|
|
Entity/EditorEntityContextComponentTests.cpp
|
|
Entity/EditorEntityHelpersTests.cpp
|
|
Entity/EditorEntitySearchComponentTests.cpp
|
|
Entity/EditorEntitySelectionTests.cpp
|
|
Entity/EntityUtilityComponentTests.cpp
|
|
EntityIdQLabelTests.cpp
|
|
EntityInspectorTests.cpp
|
|
EntityOwnershipService/EntityOwnershipServiceTestFixture.cpp
|
|
EntityOwnershipService/EntityOwnershipServiceTestFixture.h
|
|
EntityOwnershipService/SliceEditorEntityOwnershipTests.cpp
|
|
EntityOwnershipService/SliceEntityOwnershipTests.cpp
|
|
EntityTestbed.h
|
|
FileFunc.cpp
|
|
FingerprintingTests.cpp
|
|
FocusMode/ContainerEntitySelectionTests.cpp
|
|
FocusMode/ContainerEntityTests.cpp
|
|
FocusMode/EditorFocusModeFixture.cpp
|
|
FocusMode/EditorFocusModeFixture.h
|
|
FocusMode/EditorFocusModeSelectionFixture.h
|
|
FocusMode/EditorFocusModeSelectionTests.cpp
|
|
FocusMode/EditorFocusModeTests.cpp
|
|
GenericComponentWrapperTest.cpp
|
|
InstanceDataHierarchy.cpp
|
|
IntegerPrimtitiveTestConfig.h
|
|
LogLines.cpp
|
|
ManipulatorBoundsTests.cpp
|
|
ManipulatorCoreTests.cpp
|
|
ManipulatorViewTests.cpp
|
|
PerforceComponentTests.cpp
|
|
PlatformAddressedAssetCatalogTests.cpp
|
|
Prefab/Benchmark/PrefabBenchmarkFixture.cpp
|
|
Prefab/Benchmark/PrefabBenchmarkFixture.h
|
|
Prefab/Benchmark/PrefabCreateBenchmarks.cpp
|
|
Prefab/Benchmark/PrefabInstantiateBenchmarks.cpp
|
|
Prefab/Benchmark/PrefabLoadBenchmarks.cpp
|
|
Prefab/Benchmark/PrefabUpdateInstancesBenchmarks.cpp
|
|
Prefab/Benchmark/SpawnableCreateBenchmarks.cpp
|
|
Prefab/PrefabFocus/PrefabFocusTests.cpp
|
|
Prefab/MockPrefabFileIOActionValidator.cpp
|
|
Prefab/MockPrefabFileIOActionValidator.h
|
|
Prefab/PrefabDuplicateTests.cpp
|
|
Prefab/PrefabEntityAliasTests.cpp
|
|
Prefab/PrefabInstanceToTemplatePropagatorTests.cpp
|
|
Prefab/PrefabInstantiateTests.cpp
|
|
Prefab/PrefabInstantiateTests.cpp
|
|
Prefab/PrefabLoadTemplateTests.cpp
|
|
Prefab/PrefabTestComponent.cpp
|
|
Prefab/PrefabTestComponent.h
|
|
Prefab/PrefabTestData.cpp
|
|
Prefab/PrefabTestData.h
|
|
Prefab/PrefabTestDataUtils.cpp
|
|
Prefab/PrefabTestDataUtils.h
|
|
Prefab/PrefabTestDomUtils.cpp
|
|
Prefab/PrefabTestDomUtils.h
|
|
Prefab/PrefabTestFixture.cpp
|
|
Prefab/PrefabTestFixture.h
|
|
Prefab/PrefabTestUndoFixture.cpp
|
|
Prefab/PrefabTestUndoFixture.h
|
|
Prefab/PrefabTestUtils.h
|
|
Prefab/PrefabUndoLinkTests.cpp
|
|
Prefab/PrefabUndoTests.cpp
|
|
Prefab/PrefabUpdateInstancesTests.cpp
|
|
Prefab/PrefabUpdateTemplateTests.cpp
|
|
Prefab/PrefabUpdateWithPatchesTests.cpp
|
|
Prefab/Spawnable/SpawnableMetaDataTests.cpp
|
|
Prefab/SpawnableCreateTests.cpp
|
|
Prefab/SpawnableRemoveEditorInfoTestFixture.cpp
|
|
Prefab/SpawnableRemoveEditorInfoTestFixture.h
|
|
Prefab/SpawnableRemoveEditorInfoTests.cpp
|
|
Prefab/SpawnableSortEntitiesTestFixture.cpp
|
|
Prefab/SpawnableSortEntitiesTestFixture.h
|
|
Prefab/SpawnableSortEntitiesTests.cpp
|
|
Prefab/PrefabScriptingTests.cpp
|
|
Prefab/ProceduralPrefabAssetTests.cpp
|
|
PropertyIntCtrlCommonTests.h
|
|
PropertyIntSliderCtrlTests.cpp
|
|
PropertyIntSpinCtrlTests.cpp
|
|
PropertyTreeEditorTests.cpp
|
|
PythonBindingTests.cpp
|
|
QtWidgetLimitsTests.cpp
|
|
Script/ScriptComponentTests.cpp
|
|
Script/ScriptEntityTests.cpp
|
|
Slice.cpp
|
|
Slices.cpp
|
|
SliceStabilityTests/SliceStabilityCreateTests.cpp
|
|
SliceStabilityTests/SliceStabilityPushTests.cpp
|
|
SliceStabilityTests/SliceStabilityReParentTests.cpp
|
|
SliceStabilityTests/SliceStabilityTestFramework.cpp
|
|
SliceStabilityTests/SliceStabilityTestFramework.h
|
|
SliceUpgradeTests.cpp
|
|
SliceUpgradeTestsData.h
|
|
SpinBoxTests.cpp
|
|
SQLiteConnectionTests.cpp
|
|
ThumbnailerTests.cpp
|
|
ToolsComponents/EditorLayerComponentTests.cpp
|
|
ToolsComponents/EditorTransformComponentTests.cpp
|
|
TransformComponent.cpp
|
|
UI/EntityIdQLineEditTests.cpp
|
|
UI/EntityOutlinerTests.cpp
|
|
UI/EntityPropertyEditorTests.cpp
|
|
UndoStack.cpp
|
|
Viewport/ClusterTests.cpp
|
|
Viewport/ViewportEditorModeTests.cpp
|
|
Viewport/ViewportScreenTests.cpp
|
|
Viewport/ViewportUiClusterTests.cpp
|
|
Viewport/ViewportUiDisplayTests.cpp
|
|
Viewport/ViewportUiManagerTests.cpp
|
|
Viewport/ViewportUiWidgetManagerTests.cpp
|
|
Visibility/EditorVisibilityTests.cpp
|
|
)
|