/* * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or * its licensors. * * For complete copyright and license terms please see the LICENSE at the root of this * distribution (the "License"). All use of this software is governed by the License, * or, if provided, by the license below or the license accompanying this file. Do not * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * */ #pragma once #include #include #include #include #include #include #include // Suppresses the following warnings // warning C4251: 'QBrush::d': class 'QScopedPointer' needs to have dll-interface to be used by clients of class 'QBrush' // warning C4251: 'QGradient::m_stops': class 'QVector' needs to have dll-interface to be used by clients of class 'QGradient' // warning C4800: 'uint': forcing value to bool 'true' or 'false' (performance warning) AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") #include #include #include #include #include #include AZ_POP_DISABLE_WARNING class QMenu; namespace AzToolsFramework { class InstanceDataNode; namespace SliceUtilities { using EntityAncestorPair = AZStd::pair>; using IdToEntityMapping = AZStd::unordered_map; using IdToInstanceAddressMapping = AZStd::unordered_map; using WillPushEntityCallback = AZStd::function&)> ; enum class QuickPushMenuOverrideDisplayCount { ShowOverrideCountWhenSingle, ShowOverrideCountOnlyWhenMultiple }; /// Options that can be passed to PupulateQuickPushMenu to affect appearance. struct QuickPushMenuOptions { QuickPushMenuOptions() = default; QuickPushMenuOptions(const AZStd::string& headerText, QuickPushMenuOverrideDisplayCount singleOverrideDisplayOption) : m_headerText(headerText), m_singleOverrideDisplayOption(singleOverrideDisplayOption) { } AZStd::string m_headerText = "Save Slice Overrides"; QuickPushMenuOverrideDisplayCount m_singleOverrideDisplayOption = QuickPushMenuOverrideDisplayCount::ShowOverrideCountWhenSingle; }; /** * Displays slice push UI for the specified set of entities. * \param parent - the parent application window * \param entities - the list of entity Ids to include in the push request. * \param serializeContext - desired serialize context. Specify nullptr to use application's serialize context. */ void PushEntitiesModal(QWidget* parent, const EntityIdList& entities, AZ::SerializeContext* serializeContext = nullptr); /** * Creates a new slice asset containing the specified entities. * If the asset already exists, entities will instead be pushed to the asset to preserve relationships. * \param entities - the set of entities to include in the new slice. * \param targetDirectory - the preferred directory path. * \param inheritSlices - if true, entities already part of slice instances will be added by cascading from their corresponding slices. * \param setAsDynamic - if true, the slice is setup as a dynamic slice on creation * \param acceptDefaultPath - Whether to prompt the user for a path save location or to proceed with the generated one. Defaults to false * \param defaultMoveExternalRefs - Whether to prompt the user on if external entity references found in added entities get added to the created slice or do this automatically. Defaults to false * \param defaultGenerateSharedRoot - Whether to generate a shared root if one or more added entities do not share the same root. Defaults to false * \param silenceWarningPopups - Disables QT warning popups from being generated, can still rely on the return value for error handling. Defaults to false * \return true if slice was created successfully. */ bool MakeNewSlice(const AzToolsFramework::EntityIdSet& entities, const char* targetDirectory, bool inheritSlices, bool setAsDynamic, bool acceptDefaultPath = false, bool defaultMoveExternalRefs = false, bool defaultGenerateSharedRoot = false, bool silenceWarningPopups = false, AZ::SerializeContext* serializeContext = nullptr); /** * Utility function to gather all referenced entities given a set of entities. * This flood searches entity id references, so if you pass in Entity1 that references * Entity2, and Entity2 references Entity3, Entity3 is also visited and added to output as * a referenced entity. * \param entitiesWithReferences - input/output set containing all referenced entities. * \param serializeContext - serialize context to use to traverse reflected data. */ void GatherAllReferencedEntities(AzToolsFramework::EntityIdSet& entitiesWithReferences, AZ::SerializeContext& serializeContext); /** * Utility function to gather all referenced entities given a set of entities and determine * if there are references not in original set. * This flood searches entity id references, so if you pass in Entity1 that references * Entity2, and Entity2 references Entity3, Entity3 is also visited and added to output as * a referenced entity. * \param entities - input set containing all original entities to search. * \param entitiesAndReferencedEntities - input/output set containing all referenced entities. * \param hasExternalReferences output true if there are referenced entities not in original entities set * \param serializeContext - serialize context to use to traverse reflected data. */ void GatherAllReferencedEntitiesAndCompare(const AzToolsFramework::EntityIdSet& entities, AzToolsFramework::EntityIdSet& entitiesAndReferencedEntities, bool& hasExternalReferences, AZ::SerializeContext& serializeContext); /** * Clones a slice-owned entity for the purpose of comparison against a live entity. * The key aspect of this utility is the resulting clone has Ids remapped to that of the instance, * so entity references don't appear as changes/deltas due to Id remapping during slice instantiation. */ AZStd::unique_ptr CloneSliceEntityForComparison(const AZ::Entity& sourceEntity, const AZ::SliceComponent::SliceInstance& instance, AZ::SerializeContext& serializeContext); /** * Determines if adding instanceToAdd slice to targetInstanceToAddTo slice is safe to do with regard * to whether it would create a cyclic asset dependency. Slices cannot contain themselves. * \param instanceToAdd - the slice instance wanting to be added * \param targetInstanceToAddTo - the slice instance wanting to have instanceToAdd added to * \return true if safe to add. false if the slice addition would create a cyclic asset dependency (invalid). */ bool CheckSliceAdditionCyclicDependencySafe(const AZ::SliceComponent::SliceInstanceAddress& instanceToAdd, const AZ::SliceComponent::SliceInstanceAddress& targetInstanceToAddTo); /** * Push a set of entities to a given slice asset. * It is assumed that all provided entities belong to an instance of the provided slice, otherwise AZ::Failure will be returned. * \param entityIdList list of live entity Ids whose overrides will be pushed to the slice. Live entities must belong to instances of the specified slice. * \param sliceAsset the target slice asset. * \param preSaveCallback the callback to use prior to the save to check that it is valid * \return AZ::Success if push is completed successfully, otherwise AZ::Failure with an AZStd::string payload. */ AZ::Outcome PushEntitiesBackToSlice(const AzToolsFramework::EntityIdList& entityIdList, const AZ::Data::Asset& sliceAsset, SliceTransaction::PreSaveCallback preSaveCallback); /** * Push a set of entities including addition and subtraction to a given slice asset. * \param sliceAsset the target slice asset. * \param entitiesToUpdate list of entities whose overrides will be pushed to the slice. * \param entitiesToAdd list of entities to add to the slice. * \param entitiesToRemove list of entities to remove from the slice. * \param preSaveCallback the callback to use prior to the save to check that it is valid * \return AZ::Success if push is completed successfully, otherwise AZ::Failure with an AZStd::string payload. */ AZ::Outcome PushEntitiesIncludingAdditionAndSubtractionBackToSlice( const AZ::Data::Asset& sliceAsset, const AZStd::unordered_set& entitiesToUpdate, const AZStd::unordered_set& entitiesToAdd, const AZStd::unordered_set& entitiesToRemove, SliceTransaction::PreSaveCallback preSaveCallback, SliceTransaction::PostSaveCallback postSaveCallback); /** * Push an individual entity field back to a given slice asset. * It is assumed that the provided entity belongs to an instance of the provided slice, otherwise AZ::Failure will be returned. * \param entityId live entity Id whose instance of the provided field will be pushed back to the slice. * \param sliceAsset the target slice asset. * \param fieldNodeAddress InstanceDataHierarchy address of the field to be pushed back to the slice. * \param preSaveCallback the callback to use prior to the save to check that it is valid * \return AZ::Success if push is completed successfully, otherwise AZ::Failure with an AZStd::string payload. */ AZ::Outcome PushEntityFieldBackToSlice(AZ::EntityId entityId, const AZ::Data::Asset& sliceAsset, const InstanceDataNode::Address& fieldAddress, SliceTransaction::PreSaveCallback preSaveCallback); /** * PreSaveCallback for SliceTransaction::Commits with default world entity rules. * Rules include verifying there's a single root entity, making sure root entities have * no translation and clearing out cached world transforms of all entities. * * If needing custom logic for a PreSaveCallback for world entities, make sure to include this with your own callback: * * auto myPreSaveCallback = [&](SliceTransaction::TransactionPtr transaction, const char* fullPath, SliceTransaction::SliceAssetPtr& asset) -> SliceTransaction::Result { * // * auto result = SliceUtilities::SlicePreSaveCallbackForWorldEntities(transaction, fullPath, asset); * if (!result) * return result; * // * return AZ::Success(); * } */ SliceTransaction::Result SlicePreSaveCallbackForWorldEntities(SliceTransaction::TransactionPtr transaction, const char* fullPath, SliceTransaction::SliceAssetPtr& asset); void SlicePostPushCallback(SliceTransaction::TransactionPtr transaction, const char* fullSourcePath, const SliceTransaction::SliceAssetPtr& asset); void SlicePostSaveCallbackForNewSlice(SliceTransaction::TransactionPtr transaction, const char* fullPath, const SliceTransaction::SliceAssetPtr& transactionAsset); /** * Returns true if the entity has no transform parent. */ bool IsRootEntity(const AZ::Entity& entity); /** * \brief Determines whether the provided entity id is the root of a slice or subslice * \param id The entity id to check */ bool IsSliceOrSubsliceRootEntity(const AZ::EntityId& id); /** * Retrieves the \ref AZ::Edit::Attributes::SliceFlags assigned to a given data node. * \param editData - The specific element data to check for slice flags (can be nullptr) * \param classData - The class data to check for slice flags (some flags can cascade from class to all elements, can also be nullptr) * return ref AZ::Edit::SliceFlags */ AZ::u32 GetSliceFlags(const AZ::Edit::ElementData* editData, const AZ::Edit::ClassData* classData); /** * Retrieves the \ref AZ::Edit::Attributes::SliceFlags assigned to a given data node. * \param node - instance data hierarchy node * return ref AZ::Edit::SliceFlags */ AZ::u32 GetNodeSliceFlags(const InstanceDataNode& node); /** * Returns true if the specified node is slice-pushable. * \param node instance data node to evaluate. * \param isRootEntity (optional) specifies whether the parent entity is a transform root. */ bool IsNodePushable(const InstanceDataNode& node, bool isRootEntity = false); /** * Displays "Save As" QFileDialog to user, generating suggested full slice path based on * suggestedName and last place user saved a slice of this type to. Does error checking on * user-chosen name like making sure it's ASCII only/it's not taken by slices in other gems * \param suggestedName - initial suggested name of the slice * \param initialTargetDirectory - default directory to suggest saving in (gets overridden by user settings if present) * \param sliceUserSettingsId - CRC id for the SliceUserSettings for a given type of slice, used by "last saved in" logic * \param activeWindow - active QWidget for parenting dialog windows to * \param outSliceName - [out] name of the slice chosen by user/error checked * \param outSliceFilePath - [out] full directory/filename path chosen by user/error checked * \return true if valid name chosen, false if not or if cancelled by user */ bool QueryUserForSliceFilename(const AZStd::string& suggestedName, const char* initialTargetDirectory, AZ::u32 sliceUserSettingsId, QWidget* activeWindow, AZStd::string& outSliceName, AZStd::string& outSliceFilePath); /** * Populates a QMenu with sub-menus to expose slice override push operations for a provided set of entities. * \param outerMenu QMenu to which sub menus will be added. * \param inputEntities a set of entities for which quick push options will be determined. Typically callers will pass the selected entity set. * \param options optional settings to affect the appearance of the push menu, i.e. title and whether to display a change count if it's singular. */ void PopulateQuickPushMenu(QMenu& outerMenu, const AzToolsFramework::EntityIdList& inputEntities, const QuickPushMenuOptions& options = QuickPushMenuOptions()); /** * Populates a QMenu with sub-menus to expose slice override push operations for a specific entity and data field. * \param outerMenu QMenu to which sub menus will be added. * \param entityId a specific live entity for which the specified field should be pushed. * \param fieldAddress address for the specific field to be pushed. * \param options optional settings to affect the appearance of the push menu, i.e. title and whether to display a change count if it's singular. */ void PopulateQuickPushMenu(QMenu& outerMenu, AZ::EntityId entityId, const InstanceDataNode::Address& fieldAddress, const QuickPushMenuOptions& options = QuickPushMenuOptions()); /** * Get pushable new child entity Ids * \param entityIdList input entities * \param unpushableEntityIdsPerAsset [out] unpushable new child entity Ids for each potential ancestor * \param sliceAncestryMapping [out] mappings from the entity id to the slice ancestry to push to * \param newChildEntityIdAncestorPairs [out] Pairs of new child entity Id and the entity ancestor list * \param newEntityIds [out] Set of all added newly entityIds, whether pushable or not */ AZStd::unordered_set GetPushableNewChildEntityIds( const AzToolsFramework::EntityIdList& entityIdList, AZStd::unordered_map& unpushableEntityIdsPerAsset, AZStd::unordered_map& sliceAncestryMapping, AZStd::vector>& newChildEntityIdAncestorPairs, EntityIdSet& newEntityIds); /** * Get unique removed entities * \param sliceInstances slice instances which contain select entities * \param assetEntityIdtoAssetEntityMappings [out] mappings from asset entity Id to asset entity * \param assetEntityIdtoInstanceAddressMappings [out] mappings from asset entity Id to instance address */ AZStd::unordered_set GetUniqueRemovedEntities( const AZStd::vector& sliceInstances, IdToEntityMapping& assetEntityIdtoAssetEntityMapping, IdToInstanceAddressMapping& assetEntityIdtoInstanceAddressMapping); /** * Defines a callback for PopulateFindSliceMenu. This assists in bridging module boundaries. If the AssetBrowser isn't open when PopulateFindSliceMenu * is called, then it should be opened. This can only be done from a Sandbox module. PopulateFindSliceMenu is in AzToolsFramework and not Sandbox so it can * share logic with similar menus, like the quick push menu. */ typedef void(*SliceSelectedCallback)(); /** * Populates two QMenus: one with sub-menu to select slices associated to the passed in entity list in the asset browser and one with a list of parents of the current entity. * \param outerMenu The menu used as the parent for the go to slice menu. * \param selectedEntity The Entity to use to populate menus with. If this has more than one entry, no menus will be created. * \param sliceSelectedCallback Callback for when a slice is selected, run before the asset selection. This allows this functionality to bridge module * boundaries. SliceUtilities is in AzToolsFramework, but the AssetBrowser largely exists in Sandbox. */ void PopulateSliceSubMenus(QMenu& outerMenu, const AzToolsFramework::EntityIdList& inputEntities, SliceSelectedCallback sliceSelectedCallback, SliceSelectedCallback sliceRelationshipViewCallback); /** * Creates and popluates a menu item associted with the passed in entity. * \param selectedEntity The Entity to use to populate the go to slice menu with. * \param ancestor slice root ancestor to associate with this item * \param menu pointer to menu to add this menu item to. * \param indentation amount of whitespace to place in front of this item. * \param icon image to display for this menu item. * \param tooltip text to display when hovering over item * \param sliceAssetId [out] sliceAssetId of the passed in ancestor. */ QWidgetAction* MakeSliceMenuItem(const AZ::EntityId& selectedEntity, const AZ::SliceComponent::Ancestor& ancestor, QMenu* menu, int indentation, const QPixmap icon, QString tooltip, AZ::Data::AssetId& sliceAssetId); /** * Populates a QMenu with a sub-menu to select slices associated to the passed in entity list in the asset browser. * \param outerMenu The menu used as the parent for the go to slice menu. * \param selectedEntity The Entity to use to populate the go to slice menu with. * \param sliceSelectedCallback Callback for when a slice is selected, run before the asset selection. This allows this functionality to bridge module * boundaries. SliceUtilities is in AzToolsFramework, but the AssetBrowser largely exists in Sandbox. */ void PopulateFindSliceMenu(QMenu& outerMenu, const AZ::EntityId& selectedEntity, const AZ::SliceComponent::EntityAncestorList& ancestors, SliceSelectedCallback sliceSelectedCallback); /** * Populates a QMenu with a sub-menu to select slices associated to the passed in entity list in the slice relationship view. * \param outerMenu The menu used as the parent for the go to slice menu. * \param selectedEntity The Entity to use to populate the go to slice menu with. * \param sliceSelectedCallback Callback for when a slice is selected, run before the asset selection. This allows this functionality to bridge module * boundaries. SliceUtilities is in AzToolsFramework, but the AssetBrowser largely exists in Sandbox. */ void PopulateSliceRelationshipViewMenu(QMenu& outerMenu, const AZ::EntityId& selectedEntity, const AZ::SliceComponent::EntityAncestorList& ancestors, SliceSelectedCallback sliceSelectedCallback); /** * Populates a QMenu with a sub-menu to reassign a slices root ancestor to a new base, this operation directly affects the slice asset file * \param outerMenu The menu used as the parent for the go to slice menu. * \param selectedEntities The entities selected and used to populate the menu * \param selectedTransformHierarchyEntities The selected entities and all of their children * \param headerText Optional header text */ void PopulateDetachMenu(QMenu& outerMenu, const AzToolsFramework::EntityIdList& selectedEntities, const AzToolsFramework::EntityIdSet& selectedTransformHierarchyEntities, const AZStd::string& headerText = "Detach"); /** * Save slice overrides using the hot key. * \param inputEntities list of entities whose overrides need to be pushed. * \param numEntitiesToAdd [out] number of new entities to add. * \param numEntitiesToRemove [out] number of entities to remove. * \param numEntitiesToUpdate [out] number of entities to update. * \param QuickPushToFirstLevel true if users press the hot key to save overrides to the first level. Otherwise save overrides to the root level. */ bool SaveSlice( const AzToolsFramework::EntityIdList& inputEntities, int& numEntitiesToAdd, int& numEntitiesToRemove, int& numEntitiesToUpdate, const bool& QuickPushToFirstLevel); /** * Returns true if any of the given entities have slice overrides for their immediate slice ancestor (may be slow on a large group of entities). * \param inputEntities The entities to test. If any are not in a slice instance they are ignored. */ bool DoEntitiesHaveOverrides(const AzToolsFramework::EntityIdList& inputEntities); /** * Check to see if a pending reparent request is non-trivial e.g. requires full or partial clones * * [A] | Clones should occur under the following scenarios: * | | A -> | | | | | | | | | | | | * |---- | B -> | | | | | F | G | H | I | J | K | | * | | | C -> | | | | | | | | | | | | * | |----[C] | D -> | | | | | | | | | | | | * | | | | E -> | | | | | | | | | | | | * | | |---- D | F -> | | C | D | E | | | | | | K | | * | | | G -> A | B | C | D | E | | | | | | K | L | * | |---- E | H -> A | B | C | D | E | F | | | | J | K | L | * | | I -> A | B | C | D | E | F | | | | J | K | L | * |----{F} | J -> | | | | | | | | | | | | * | | | K -> | | C | D | E | F | G | H | I | J | | | * | |----{G} | L -> | | | | | | | | | | | | * | | | * | |---- | * | | | * | |---- | * | | |-------------------------------- * | |---- J | Legend: * | | [] - slice root * |----{K} | {} - sub slice root * | | <> - slice entity * |---- L | - loose entity * * \param entityId The target entity to reparent * \param newParentId The target parent entity */ bool IsReparentNonTrivial(const AZ::EntityId& entityId, const AZ::EntityId& newParentId); /** * Performs the necessary detach operations on orphaned slice and subslice entities while reparenting existing loose entities and slices. * \param entityId The target entity to reparent * \param newParentId The target parent entity */ void ReparentNonTrivialSliceInstanceHierarchy(const AZ::EntityId& entityId, const AZ::EntityId& newParentId); /** * Reflects slice tools related structures for serialization/editing. */ void Reflect(AZ::ReflectContext* context); /** * Gets the path to the icon used for representing slices. */ QString GetSliceItemIconPath(); /** * Gets the path to the icon used for representing modified slices. */ QString GetSliceItemChangedIconPath(); /** * Gets the path to the L shape icon. */ QString GetLShapeIconPath(); /** * Gets the path to the blue 3d box shape icon. */ QString GetSliceEntityIconPath(); /** * Gets the path to the warning icon. */ QString GetWarningIconPath(); /** * Gets the height to use for rows that represent slices. */ AZ::u32 GetSliceItemHeight(); /** * Gets the size to use for icons representing slices. */ QSize GetSliceItemIconSize(); /** * Gets the size of the L shape icon. */ QSize GetLShapeIconSize(); /** * Gets the size of the warning icon. */ QSize GetWarningIconSize(); /** * Gets the minimum width of the warning label. */ int GetWarningLabelMinimumWidth(); /** * Gets the depth to indent slices per level of that slice's hierarchy. */ AZ::u32 GetSliceHierarchyMenuIdentationPerLevel(); /** * Gets the font size to make the slice submenu look like the parent menu */ int GetSliceSelectFontSize(); /** * Structure for saving/retrieving user settings related to slice workflows. */ class SliceUserSettings : public AZ::UserSettings { public: AZ_CLASS_ALLOCATOR(SliceUserSettings, AZ::SystemAllocator, 0); AZ_RTTI(SliceUserSettings, "{56EC1A8F-1ADB-4CC7-A3C3-3F462750C31F}", AZ::UserSettings); AZStd::string m_saveLocation; bool m_autoNumber = false; //!< Should the name of the slice file be automatically numbered. e.g SliceName_001.slice vs SliceName.slice. SliceUserSettings() = default; static void Reflect(AZ::ReflectContext* context); }; class DetachMenuActionWidget : public QWidget { public: DetachMenuActionWidget(QWidget* parent, const int& indentation, const AZStd::string& sliceAssetName, const bool& isLastAncestor); void enterEvent(QEvent* event) override; void leaveEvent(QEvent* event) override; private: void setsliceLabelTextColor(QString color); QLabel* m_sliceLabel; QLabel* m_toLabel; }; class MoveToSliceLevelConfirmation : public QDialog { public: MoveToSliceLevelConfirmation(QWidget* parent, const AZStd::string& currentSlice, const AZStd::string& destinationSlice); }; /// InvalidSliceReferencesWarningResult is used to contain the result /// on calls to DisplayInvalidSliceReferencesWarning. enum class InvalidSliceReferencesWarningResult { Save, ///< The user has chosen continue with the save operation. Cancel, ///< The user has chosen to cancel the current operation. Details ///< The user has chosen to open the advanced slice push dialog. }; /** * Displays a message warning the user that the push they are attempting will remove missing invalid references. * \param parent The widget to parent the window to. * \param invalidSliceCount The number of slices to be saved with invalid references. * \param invalidReferenceCount The number of references that will be cleared. * \param showDetailsButton True to show a details button to be used to open the advanced slice push window. */ InvalidSliceReferencesWarningResult DisplayInvalidSliceReferencesWarning( QWidget* parent, size_t invalidSliceCount, size_t invalidReferenceCount, bool showDetailsButton); /** * Calculates the number of changes in a list of slices to be used in push/revert menu options * \param inputEntities List of entities to produce information for * \param entitiesToRemove [out] List of entities that have been removed * \param numRelevantEntitiesInSlices [out] Number of entities that have changes * \param pushableChangesPerAsset [out] List of the number of changes for each entitiy in list * \param sliceDisplayOrder [out] List of changes slices in display order * \param assetEntityAncestorMap [out] List of ancestors of affected entities * \param unpushableEntityIds [out] Set of unpushable entity Ids * \return True if there are changes */ bool CountPushableChangesToSlice(const AzToolsFramework::EntityIdList& inputEntities, const InstanceDataNode::Address* fieldAddress, AZStd::unordered_map& entitiesToAddPerAsset, AZStd::unordered_set& entitiesToRemove, size_t& numRelevantEntitiesInSlices, AZStd::unordered_map& numPushableChangesPerAsset, AZStd::vector& sliceDisplayOrder, AZStd::unordered_map>& assetEntityAncestorMap, AZStd::unordered_map < AZ::Data::AssetId, AZStd::unordered_set>& pushableEntityIdsPerAsset, AZStd::unordered_map&unpushableEntityIdsPerAsset); /** * Returns the file extension (including .) used for slices. */ AZStd::string GetSliceFileExtension(); //! Returns whether or not a given asset is a dynamic slice or not bool IsDynamic(const AZ::Data::AssetId& assetId); //! Toggles if a slice asset is dynamic and re-saves the slice void SetIsDynamic(const AZ::Data::AssetId& assetId, bool isDynamic); /** * Creates the right click context menu for slices in the asset browser. * \param menu The menu to parent this to. * \param fullFilePath The full file path of the slice. */ void CreateSliceAssetContextMenu(QMenu* menu, const AZStd::string& fullFilePath); /** * Retrieves the desired save format for slices. * \return The slice save format. */ AZ::DataStream::StreamType GetSliceStreamFormat(); /** * Prunes child order array entries that won't be in a pushed slice. * \param originalOrderArray Child array with all entities in * \param prunedOrderArray [out] Child array after removing unneeded entities. * \param targetSlice Slice that the children are being pushed to. * \param willPushEntityCallback Callback routine that is called per entity in the array and returns true if the entity will be pushed. */ void RemoveInvalidChildOrderArrayEntries(const AZStd::vector& originalOrderArray, AZStd::vector& prunedOrderArray, const AZ::Data::Asset& targetSlice, WillPushEntityCallback willPushEntityCallback); static const char* splitterColor = "black"; static const char* detachMenuItemHoverColor = "#4285F4"; static const char* detachMenuItemDefaultColor = "#ffffff"; static const char* detailWidgetBackgroundColor = "#303030"; static const char* unsavableChangesTextColor = "#ff3f3f"; static const char* conflictedChangesTextColor = "red"; } // namespace SliceUtilities } // AzToolsFramework