914 lines
40 KiB
C++
914 lines
40 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#pragma once
|
|
|
|
#include "MuR/ModelPrivate.h"
|
|
#include "MuT/TypeInfo.h"
|
|
#include "UObject/GCObject.h"
|
|
#include "Widgets/SCompoundWidget.h"
|
|
#include "Widgets/Input/SSearchBox.h"
|
|
#include "Engine/Texture.h"
|
|
#include "MuR/Mesh.h"
|
|
#include "UObject/SoftObjectPtr.h"
|
|
|
|
class STableViewBase;
|
|
namespace ESelectInfo { enum Type : int; }
|
|
template <typename ItemType> class STreeView;
|
|
template <typename OptionType> class SComboBox;
|
|
|
|
|
|
class FMutableCodeTreeElement;
|
|
class FMutableOperationElement;
|
|
class FReferenceCollector;
|
|
class ITableRow;
|
|
class SBorder;
|
|
class SMutableBoolViewer;
|
|
class SMutableColorViewer;
|
|
class SMutableConstantsWidget;
|
|
class SMutableCurveViewer;
|
|
class SMutableImageViewer;
|
|
class SMutableIntViewer;
|
|
class SMutableLayoutViewer;
|
|
class SMutableMeshViewer;
|
|
class SMutableInstanceViewer;
|
|
class SMutableParametersWidget;
|
|
class SMutableProjectorViewer;
|
|
class SMutableScalarViewer;
|
|
class SMutableSkeletonViewer;
|
|
class SMutableStringViewer;
|
|
class STextComboBox;
|
|
class SWidget;
|
|
namespace mu { struct FProjector; }
|
|
namespace mu { struct FShape; }
|
|
struct FGeometry;
|
|
|
|
/** This widget shows the internal Mutable Code for debugging purposes.
|
|
* This is not the Unreal source graph in the UCustomizableObject, but the actual Mutable virtual machine graph.
|
|
*/
|
|
class SMutableCodeViewer :
|
|
public SCompoundWidget,
|
|
public FGCObject
|
|
{
|
|
public:
|
|
|
|
SLATE_BEGIN_ARGS(SMutableCodeViewer) {}
|
|
|
|
/** User-visible tag to identify the source of the data shown. */
|
|
SLATE_ARGUMENT(FString, DataTag)
|
|
|
|
SLATE_END_ARGS()
|
|
|
|
void Construct(const FArguments& InArgs, const TSharedPtr<mu::FModel, ESPMode::ThreadSafe>& InMutableModel,
|
|
const TArray<TSoftObjectPtr<const UTexture>>& ReferencedTextures,
|
|
const TArray<TSoftObjectPtr<const UStreamableRenderAsset>>& ReferencedMeshes);
|
|
|
|
// SWidget interface
|
|
virtual void Tick(const FGeometry& AllottedGeometry, const double InCurrentTime, const float InDeltaTime) override;
|
|
|
|
// FGCObject interface
|
|
virtual void AddReferencedObjects(FReferenceCollector& Collector) override;
|
|
virtual FString GetReferencerName() const override;
|
|
|
|
/** Clear the selected operation of the tree view.*/
|
|
void ClearSelectedTreeRow() const;
|
|
|
|
private:
|
|
|
|
/** The Mutable Model that we are showing. */
|
|
TSharedPtr<mu::FModel, ESPMode::ThreadSafe> MutableModel;
|
|
|
|
/** Array of external referenced textures in MutableModel, indexed by id. */
|
|
TArray<TSoftObjectPtr<const UTexture>> ReferencedTextures;
|
|
TArray<TSoftObjectPtr<const UStreamableRenderAsset>> ReferencedMeshes;
|
|
|
|
/** Selected model operation for preview. */
|
|
mu::OP::ADDRESS SelectedOperationAddress = 0;
|
|
|
|
/** Mutable parameters used in the preview. */
|
|
TSharedPtr<mu::FParameters> PreviewParameters;
|
|
|
|
/** Widget showing the parameters that affect the current preview. */
|
|
TSharedPtr<SMutableParametersWidget> ParametersWidget;
|
|
|
|
/** Widget showing the constants found on the mutable Model program */
|
|
TSharedPtr<SMutableConstantsWidget> ConstantsWidget;
|
|
|
|
/** If true, the parameters have changed and we need to update the preview. */
|
|
bool bIsPreviewPendingUpdate = false;
|
|
|
|
/** Widget container where different previews will be created. */
|
|
TSharedPtr<SBorder> PreviewBorder;
|
|
|
|
/*
|
|
* Preview windows for the data types exposed by Mutable
|
|
*/
|
|
|
|
/** Widget used to show the preview of layout operation results. Once created it is reused to preserve the settings. */
|
|
TSharedPtr<SMutableLayoutViewer> PreviewLayoutViewer;
|
|
|
|
/** Widget used to show the preview of image operation results. Once created it is reused to preserve the settings. */
|
|
TSharedPtr<SMutableImageViewer> PreviewImageViewer;
|
|
|
|
/** Widget used to show a preview of an instance. */
|
|
TSharedPtr<SMutableInstanceViewer> PreviewInstanceViewer;
|
|
|
|
/** Widget used to show a preview of a mesh and the metadata it holds */
|
|
TSharedPtr<SMutableMeshViewer> PreviewMeshViewer;
|
|
|
|
/** Widget used to show a preview of a mutable bool value */
|
|
TSharedPtr<SMutableBoolViewer> PreviewBoolViewer;
|
|
|
|
/** Widget used to show a preview of a mutable int value */
|
|
TSharedPtr<SMutableIntViewer> PreviewIntViewer;
|
|
|
|
/** Widget used to show a preview of a mutable float value */
|
|
TSharedPtr<SMutableScalarViewer> PreviewScalarViewer;
|
|
|
|
/** Widget used to show a preview of a mutable string value */
|
|
TSharedPtr<SMutableStringViewer> PreviewStringViewer;
|
|
|
|
/** Widget used to show a preview of a mutable color value */
|
|
TSharedPtr<SMutableColorViewer> PreviewColorViewer;
|
|
|
|
/** Widget used to display the data held on the mutable projector objects */
|
|
TSharedPtr<SMutableProjectorViewer> PreviewProjectorViewer;
|
|
|
|
/** Widget used to display the data held on the mutable skeleton objects */
|
|
TSharedPtr<SMutableSkeletonViewer> PreviewSkeletonViewer;
|
|
|
|
/** Widget used to display the data held on the mutable curve objects */
|
|
TSharedPtr<SMutableCurveViewer> PreviewCurveViewer;
|
|
|
|
/** Tree widget showing the code hierarchically. */
|
|
TSharedPtr<STreeView<TSharedPtr<FMutableCodeTreeElement>>> TreeView;
|
|
|
|
/** Root nodes of the tree widget. */
|
|
TArray<TSharedPtr<FMutableCodeTreeElement>> RootNodes;
|
|
|
|
/** Cache of tree elements matching the operations that have been generated so far.
|
|
* We store both the parent and the operation in the key, because a single operation may appear multiple times if it has different parents.
|
|
*/
|
|
struct FItemCacheKey
|
|
{
|
|
mu::OP::ADDRESS Parent=0;
|
|
mu::OP::ADDRESS Child=0;
|
|
uint32 ChildIndexInParent=0;
|
|
|
|
friend FORCEINLINE bool operator == (const FItemCacheKey& A, const FItemCacheKey& B)
|
|
{
|
|
return A.Parent == B.Parent && A.Child == B.Child && A.ChildIndexInParent == B.ChildIndexInParent;
|
|
}
|
|
|
|
friend FORCEINLINE uint32 GetTypeHash(const FItemCacheKey& Key)
|
|
{
|
|
return HashCombine(Key.Parent, HashCombine(Key.Child, Key.ChildIndexInParent));
|
|
}
|
|
};
|
|
|
|
/*
|
|
* Tree widget objects
|
|
*/
|
|
|
|
/** Map with all the generated elements of the tree. Unique and duplicated elements will be present on this list and
|
|
* also the children of the unique elements.
|
|
* @note The children of duplicated elements will only be present once, as children of the unique element they duplicate.
|
|
* This is to avoid having identical elements on the tree (witch would cause a crash) while also being pointless due to
|
|
* how we manage expansion of duplicated elements.
|
|
*/
|
|
TMap< FItemCacheKey, TSharedPtr<FMutableCodeTreeElement>> ItemCache;
|
|
|
|
/** Main tree item for each op. An op can be represented with multiple tree nodes if it is reachable from different paths. */
|
|
TMap< mu::OP::ADDRESS, TSharedPtr<FMutableCodeTreeElement>> MainItemPerOp;
|
|
|
|
/** List with all the elements related to nodes displayed on the tree. */
|
|
TArray<TSharedPtr<FMutableCodeTreeElement>> TreeElements;
|
|
|
|
/** Array with all the elements that have been manually expanded by the user */
|
|
TMap< mu::OP::ADDRESS, TSharedPtr<FMutableCodeTreeElement>> ExpandedElements;
|
|
|
|
/** Prepare the widget for the given model. */
|
|
void SetCurrentModel(const TSharedPtr<mu::FModel, ESPMode::ThreadSafe>&, const TArray<TSoftObjectPtr<const UTexture>>& ReferencedTextures, const TArray<TSoftObjectPtr<const UStreamableRenderAsset>>& ReferencedMeshes);
|
|
|
|
/** Before any UI operation generate all the elements that may be navigable over the tree. No children of duplicated
|
|
* addresses will be generated.
|
|
*/
|
|
void GenerateAllTreeElements();
|
|
|
|
/** Support GenerateAllTreeElements by generating the elements recursively */
|
|
void GenerateElementRecursive( const int32& InStateIndex, mu::OP::ADDRESS InParentAddress, const mu::FProgram& InProgram);
|
|
|
|
|
|
/** The addresses of the root operations. Cached when this object gets loaded on the Construct method of this slate */
|
|
TArray<mu::OP::ADDRESS> RootNodeAddresses;
|
|
|
|
/** Utility method that provides you with the addresses of the root nodes of the program */
|
|
void CacheRootNodeAddresses();
|
|
|
|
/** Control boolean to know if there are any highlighted elements on the tree */
|
|
bool bIsElementHighlighted = false;
|
|
|
|
/** Operation that is currently being highlighted */
|
|
mu::OP::ADDRESS HighlightedOperation{};
|
|
|
|
/*
|
|
* Operations computational cost reference collections
|
|
*/
|
|
|
|
/** Collection with all very expensive to run operation types */
|
|
const TArray<mu::EOpType> VeryExpensiveOperationTypes
|
|
{
|
|
mu::EOpType::ME_BINDSHAPE,
|
|
mu::EOpType::ME_MASKCLIPMESH,
|
|
mu::EOpType::ME_MASKCLIPUVMASK,
|
|
mu::EOpType::ME_FORMAT,
|
|
mu::EOpType::ME_MASKDIFF,
|
|
mu::EOpType::ME_DIFFERENCE,
|
|
mu::EOpType::ME_EXTRACTLAYOUTBLOCK,
|
|
mu::EOpType::IM_MAKEGROWMAP,
|
|
};
|
|
|
|
/** Collection with all expensive to run operation types */
|
|
const TArray<mu::EOpType> ExpensiveOperationTypes
|
|
{
|
|
mu::EOpType::IM_PIXELFORMAT,
|
|
mu::EOpType::IM_SWIZZLE,
|
|
mu::EOpType::ME_PROJECT,
|
|
mu::EOpType::ME_TRANSFORMWITHMESH,
|
|
};
|
|
|
|
/** Enum designed to be able to notify the row generation of the type of operation being generated */
|
|
enum class EOperationComputationalCost : uint8
|
|
{
|
|
Standard = 0, // All other operation types
|
|
Expensive = 1, // The ones located on ExpensiveOperationTypes
|
|
VeryExpensive = 2 // The ones located on VeryExpensiveOperationTypes
|
|
};
|
|
|
|
/** Array holding the relation between each computational cost category and the color to be used to display elements related
|
|
* with it.
|
|
*/
|
|
const TArray<FSlateColor> ColorPerComputationalCost
|
|
{
|
|
FSlateColor(FLinearColor(1,1,1,1)), // Standard cost color
|
|
FSlateColor(FLinearColor(1,0.4,0.2,1)), // Expensive cost color
|
|
FSlateColor(FLinearColor(1,0.1,0.1,1)) // Very Expensive cost color
|
|
};
|
|
|
|
/** Provided an operation type it returns the category representing how much costs to run an operation of this type
|
|
* @param OperationType The operation type you want to know the computational cost of
|
|
* @return The enum value representing the computational cost of the operation type provided.
|
|
*/
|
|
EOperationComputationalCost GetOperationTypeComputationalCost(mu::EOpType OperationType) const;
|
|
|
|
|
|
/*
|
|
* Navigation : Operation type navigation Type selection object
|
|
*/
|
|
|
|
/** Slate object that provides the user a way of selecting what kind of operation it wants to navigate.*/
|
|
TSharedPtr<SComboBox<TSharedPtr<const FMutableOperationElement>>> TargetedTypeSelector;
|
|
|
|
/** Data backend for the list displayed for the navigation type selection */
|
|
TArray<TSharedPtr<const FMutableOperationElement>> FoundModelOperationTypeElements;
|
|
|
|
/** Navigation operation entry representing the NONE type */
|
|
TSharedPtr<const FMutableOperationElement> NoneOperationEntry;
|
|
|
|
/** Navigation operation entry used to be able to set the UI to show we are performing a constant resource based
|
|
* navigation
|
|
*/
|
|
TSharedPtr<const FMutableOperationElement> ConstantBasedNavigationEntry;
|
|
|
|
/** Currently selected element on the TargetedTypeSelector slate. Actively used by the ui */
|
|
TSharedPtr<const FMutableOperationElement> CurrentlySelectedOperationTypeElement;
|
|
|
|
/** Operation type we are using to search for tree nodes. Driven primarily by the UI */
|
|
mu::EOpType OperationTypeToSearch = mu::EOpType::NONE;
|
|
|
|
/** Operation types present on the currently set mutable model.
|
|
* The value of the TPair represents the amount of times operations using it have been found (not duplicates) */
|
|
TArray< TPair< mu::EOpType,uint32>> ModelOperationTypes;
|
|
|
|
/** Array with all the names for each of the operations available on mutable. Used by the UI */
|
|
TArray<FString> ModelOperationTypeNames;
|
|
|
|
/** Stores a list of strings based on the possible types of operations mutable define to be used by the UI */
|
|
void GenerateNavigationOpTypeStrings();
|
|
|
|
/** Generate a list of elements that will be used as backend for the navigation type selection dropdown */
|
|
void GenerateNavigationDropdownElements();
|
|
|
|
|
|
/** Fills ModelOperationTypes with all the types present on the current model.
|
|
* It also makes sure we have a NONE operation and that the operations are sorted alphabetically.
|
|
* @note Method designed to be called once per model.*/
|
|
void CacheOperationTypesPresentOnModel();
|
|
|
|
|
|
/*
|
|
* Navigation : UI callback methods
|
|
*/
|
|
|
|
/** Generate the text to be used by the navigation operation selector */
|
|
FText GetCurrentNavigationOpTypeText() const;
|
|
|
|
/** Returns the color to be used by the text being currently displayed as selected on the operation selector*/
|
|
FSlateColor GetCurrentNavigationOpTypeColor() const;
|
|
|
|
/** Callback invoked by the ComboBox used for displaying and selecting operation types for navigation. it gets invoked
|
|
* each time the slate object requires to draw a line representing one of the elements set on FoundModelOperationTypeElements
|
|
*/
|
|
TSharedRef<SWidget> OnGenerateOpNavigationDropDownWidget(TSharedPtr<const FMutableOperationElement> MutableOperationElement) const;
|
|
|
|
/** Callback invoked each time the selected operation on our navigation slate changes. It can change due to UI interaction
|
|
* or also due to direct change by invoking the SetSelectedOption on the SComboBox TargetedTypeSelector
|
|
*/
|
|
void OnNavigationSelectedOperationChanged(TSharedPtr<const FMutableOperationElement, ESPMode::ThreadSafe> MutableOperationElement, ESelectInfo::Type Arg);
|
|
|
|
/** Callback used to print on screen the amount of operations found on the tree that share the same operation type that
|
|
* the one currently selected on the navigation system.
|
|
*/
|
|
FText OnPrintNavigableObjectAddressesCount() const;
|
|
|
|
/** Method that tells the UI if the bottom to go to the previous element can be interacted */
|
|
bool CanInteractWithPreviousOperationButton() const;
|
|
|
|
/** Method that tells the UI if the bottom to go to the next element can be interacted */
|
|
bool CanInteractWithNextOperationButton() const;
|
|
|
|
|
|
/** Used by the UI and internally does what is necessary to get to the previous element of the targeted search type.
|
|
* It is designed to work alongside GoToPreviousOperationAfterRefresh(...)
|
|
* @return A reply to tell if the UI action has been handled or not.
|
|
*/
|
|
FReply OnGoToPreviousOperationButtonPressed();
|
|
|
|
/** Used by the UI and internally does what is necessary to get to the next element of the targeted search type.
|
|
* It is designed to work alongside GoToNextOperationAfterRefresh(...)
|
|
* @return A reply to tell if the UI action has been handled or not.
|
|
*/
|
|
FReply OnGoToNextOperationButtonPressed();
|
|
|
|
|
|
/** Callback method used to allow the user to directly set the type of operation to be scanning directly by selecting a
|
|
* operation on the tree and using that operation type as the type to search for
|
|
*/
|
|
void OnSelectedOperationTypeFromTree();
|
|
|
|
/*
|
|
* Navigation : control flags
|
|
*/
|
|
|
|
/** Flag monitoring if we have requested a scroll operation to reach the targeted element */
|
|
bool bWasScrollToTargetRequested = false;
|
|
|
|
/** Flag designed to tell the system when the expansion of unique elements have been performed as part of the navigation operation */
|
|
bool bWasUniqueExpansionInvokedForNavigation = false;
|
|
|
|
/*
|
|
* Navigation : Shared objects between navigation search types
|
|
*/
|
|
|
|
/** Array with all the elements of the type we are looking for (shared type of constant resource). */
|
|
TArray<TSharedPtr<FMutableCodeTreeElement>> NavigationElements;
|
|
|
|
/** Operation types present on the currently set mutable model. */
|
|
int64 NavigationIndex = -1;
|
|
|
|
/** Sort the contents of NavigationElements to follow a sequential pattern using the indices of the elements from 0 to +n*/
|
|
void SortElementsByTreeIndex(TArray<TSharedPtr<FMutableCodeTreeElement>>& InElementsArrayToSort);
|
|
|
|
/** If the focus could not be performed directly then cache the target until it is in view and can therefore be focused.
|
|
* It will be valid if we are trying to focus something (it) and invalid if the focus operation has already been resolved. */
|
|
TSharedPtr<FMutableCodeTreeElement> ToFocusElement;
|
|
|
|
/** Focus the current NavigationElement and places it into view. It also selects it so the previewer for the
|
|
* element gets invoked
|
|
*/
|
|
void FocusViewOnNavigationTarget(TSharedPtr<FMutableCodeTreeElement> InTargetElement);
|
|
|
|
/** Wrapper struct designed to be used as cache for all elements found during the navigation system search for elements
|
|
* of X Type or relation with a targeted constant resource. It is designed to be used and then destroyed once the
|
|
* search operation has been completed */
|
|
struct FElementsSearchCache
|
|
{
|
|
/** Set of addresses that have already been searched for relevant data */
|
|
TSet<mu::OP::ADDRESS> ProcessedAddresses;
|
|
|
|
/** Collection of elements that have been found during the search. They may be related by OP_Type or used constant resource*/
|
|
TArray<TSharedPtr<FMutableCodeTreeElement>> FoundElements;
|
|
|
|
/** Array containing all the next addresses to be processed.
|
|
* The child is the address itself to be later processed
|
|
* The parent is the parent address of the child.
|
|
* The ChildIndexInParent is the index (or child position) o the child address on Child as part of the child set of the parent address.
|
|
*/
|
|
TArray<FItemCacheKey> BatchData;
|
|
|
|
|
|
/** Generates the structures to be able to start the search of elements. It uses the root addresses as the
|
|
* start of the search operation.
|
|
* @param InRootNodeAddresses The addresses of the root operations of the operations tree
|
|
*/
|
|
void SetupRootBatch(const TArray<mu::OP::ADDRESS>& InRootNodeAddresses)
|
|
{
|
|
check (InRootNodeAddresses.Num());
|
|
// This method should only be called once when no data is present on this cache
|
|
check (BatchData.IsEmpty());
|
|
|
|
BatchData.Reserve(InRootNodeAddresses.Num());
|
|
// The child address of each parent operation on it's parent
|
|
for (int32 RootIndex = 0; RootIndex < InRootNodeAddresses.Num(); RootIndex++)
|
|
{
|
|
FItemCacheKey Key;
|
|
{
|
|
Key.Child = InRootNodeAddresses[RootIndex];
|
|
// Store the parent of this object as 0 to have a "virtual" address witch all root addresses are
|
|
// children of
|
|
Key.Parent = 0;
|
|
// And also the index of the parent on it's parent "virtual" structure
|
|
Key.ChildIndexInParent = RootIndex;
|
|
}
|
|
|
|
// Add this new entry point for the search of addresses
|
|
BatchData.Add(Key);
|
|
}
|
|
}
|
|
|
|
/** Method to cache the provided mutable address as one of the addresses that are of the type we are looking for or maybe
|
|
* is related with the constant resource we are looking for operations related with.
|
|
* @param OpAddress The address to save as one related with a operation type or constant resource
|
|
* @param IndexAsChildOfInputAddress The index on BatchData that represents the parent of the provided operation address
|
|
* @param InItemCache Cache with all the elements of the tree. Here is where we search for the element based on
|
|
* the OpAddress and the parent and ChildIndexInParent provided thanks to IndexAsChildOfInputAddress
|
|
*/
|
|
void AddToFoundElements(const mu::OP::ADDRESS OpAddress,const int32 IndexAsChildOfInputAddress,
|
|
const TMap<FItemCacheKey, TSharedPtr<FMutableCodeTreeElement>>& InItemCache)
|
|
{
|
|
FItemCacheKey Key;
|
|
{
|
|
Key.Child = OpAddress;
|
|
// Store the parent address of this object
|
|
Key.Parent = BatchData[IndexAsChildOfInputAddress].Parent;
|
|
// And also the index of the parent on it's parent structure
|
|
Key.ChildIndexInParent = BatchData[IndexAsChildOfInputAddress].ChildIndexInParent;
|
|
}
|
|
// Generate a key for this element in order to search in on the map with all the elements
|
|
|
|
// Find that element on the tree, (check error if not found since all elements should be there)
|
|
const TSharedPtr<FMutableCodeTreeElement>* PtrFoundElement = InItemCache.Find(Key);
|
|
check(PtrFoundElement);
|
|
TSharedPtr<FMutableCodeTreeElement> FoundElement = *PtrFoundElement;
|
|
check(FoundElement);
|
|
|
|
// Store this element on our temp array of elements
|
|
FoundElements.Add(FoundElement);
|
|
}
|
|
|
|
/** Caches the provided parent address to the Search payload so they can be later read and processed on another batch of the
|
|
* method tasked with finding related operations to operation type or constant resource.
|
|
* @param InParentAddress The parent address to search children of.
|
|
* @param InProgram The mutable program that will be used to perform the children search.
|
|
* @param OutFoundChildrenData Array with all the ItemCacheKeys that represent all the children found
|
|
* @note It will not add the children of any provided ParentAddress for the next batch if the parent address provided
|
|
* has already been processed and therefore whose children have already been searched or prepared for searching.
|
|
*/
|
|
void CacheChildrenOfAddressIfNotProcessed(mu::OP::ADDRESS InParentAddress,
|
|
const mu::FProgram& InProgram,
|
|
TArray<FItemCacheKey>& OutFoundChildrenData)
|
|
{
|
|
if (!ProcessedAddresses.Contains(InParentAddress))
|
|
{
|
|
// Cache to avoid processing it again later
|
|
ProcessedAddresses.Add(InParentAddress);
|
|
|
|
// Generic case for unnamed children traversal.
|
|
uint32 ChildIndex = 0;
|
|
mu::ForEachReference(InProgram, InParentAddress, [this, &InParentAddress, &ChildIndex,&OutFoundChildrenData]( mu::OP::ADDRESS ChildAddress)
|
|
{
|
|
// If the parent does have a child then process it
|
|
// Ignoring child address 0 since those can not have children
|
|
if (ChildAddress)
|
|
{
|
|
FItemCacheKey Key;
|
|
{
|
|
Key.Child = ChildAddress;
|
|
Key.Parent = InParentAddress;
|
|
Key.ChildIndexInParent = ChildIndex;
|
|
}
|
|
|
|
// Save it to the output so can later be placed onto BatchData safely
|
|
OutFoundChildrenData.Add(Key);
|
|
}
|
|
ChildIndex++;
|
|
});
|
|
}
|
|
}
|
|
};
|
|
|
|
|
|
/*
|
|
* Navigation : Operation type based navigation
|
|
*/
|
|
|
|
/** Provided an Operation type store as navigation addresses all operations of the targeted navigation Op type
|
|
* @note The operations found get saved on the collection NavigationOPAddresses.
|
|
*/
|
|
void CacheAddressesOfOperationsOfType();
|
|
|
|
/** Fills an array with all the addresses of operations that do have in common the same targeted operation type
|
|
* @param TargetOperationType The operation type used to discriminate what operation addresses we want to retrieve.
|
|
* processing them more than once.
|
|
* @param InSearchPayload A caching structure designed to hold the data that gets passed from one recursive call to
|
|
* the other. It also stores the found elements and other data.
|
|
* @param InProgram The mutable program holding the data to be searched over
|
|
*/
|
|
void GetOperationsOfType(const mu::EOpType& TargetOperationType,
|
|
FElementsSearchCache& InSearchPayload,
|
|
const mu::FProgram& InProgram);
|
|
|
|
/*
|
|
* Navigation : Navigation based on constant resource relation with addresses
|
|
*/
|
|
|
|
public:
|
|
|
|
/**
|
|
* Provided a constant resource data type and index on its constant array this method sets all the operations that
|
|
* make usage of said constant to be navigable by the navigation system.
|
|
* @note The output of this operation will be cached onto NavigationOPAddresses so we can navigate over them.
|
|
* @param ConstantDataType The constant data type to locate operations referencing it: It is required for the
|
|
* system to know what operations should be checked for the usage of the provided constant resource. For example, a
|
|
* type of mu::EDataType::DT_Curve will try to locate operations that we know operate with constant curves.
|
|
* @param IndexOnConstantsArray The index of the constant on its constants array. If it is, for example, a constant mesh
|
|
* this value represents the index of the constant inside constantMeshes array on mu::program.
|
|
*/
|
|
void CacheAddressesRelatedWithConstantResource(const mu::EDataType ConstantDataType, const int32 IndexOnConstantsArray);
|
|
|
|
private:
|
|
|
|
/**
|
|
* Provided a data type and the index of the constant object using said data type locate all operations that do
|
|
* directly make use of said constant resource.
|
|
* @param ConstantDataType The type of the resource we are providing an index of.
|
|
* @param IndexOnConstantsArray The index of the constant resource we want to know what operations are using it.
|
|
* @param InSearchPayload Cache object that will end up containing all the elements related with the provided constant
|
|
* resource
|
|
* @param InProgram The mutable program containing all the operations of the graph.
|
|
*/
|
|
void GetOperationsReferencingConstantResource(const mu::EDataType ConstantDataType,
|
|
const int32 IndexOnConstantsArray,
|
|
FElementsSearchCache& InSearchPayload,
|
|
const mu::FProgram& InProgram);
|
|
|
|
/**
|
|
* Provided an operation address this method tells us if that address is making use of our constant resource or not.
|
|
* It will take into account the datatype of the provided resource to discard or acknowledge the operation type of the
|
|
* provided operation address.
|
|
* @param IndexOnConstantsArray The index onto its respective constants array of the constant resource provided. We do
|
|
* not give a pointer to the constant resource but the index of it onto its hosting array.
|
|
* @param ConstantDataType The type of data we know the constant uses. It is used to check for ones or other operations since
|
|
* not all operations do access the same constant resources.
|
|
* @param OperationAddress The address of the operation currently being scanned for constant resources.
|
|
* @param InProgram The mutable program to use to check the type of operation that corresponds to that operation address.
|
|
* @return True if the operation at OperationAddress does make use of the provided constant resource. False otherwise
|
|
*/
|
|
bool IsConstantResourceUsedByOperation(const int32 IndexOnConstantsArray,
|
|
const mu::EDataType ConstantDataType, const mu::OP::ADDRESS OperationAddress,
|
|
const mu::FProgram& InProgram) const;
|
|
|
|
|
|
/*
|
|
* Navigation : Text based navigation
|
|
*/
|
|
|
|
/** Current text being used to perform a search by name. It gets updated each time the user changes the text in the SearchBox */
|
|
FString SearchString;
|
|
|
|
/** Flag that determines how to interpret the SearchString provided.
|
|
* If true it means it is a regular expression.
|
|
* If not it is just a fragment of text to seek for in the tree of operations. */
|
|
bool bIsSearchStringRegularExpression = false;
|
|
|
|
/** Last search configuration -> Prevents recurrent searches with the same search parameters */
|
|
FString LastSearchedString;
|
|
bool bWasLastSearchRegEx = false;
|
|
TSharedPtr<mu::FModel> LastSearchedModel;
|
|
|
|
/** A collection with all the elements we have found to be related with the SearchString. */
|
|
TArray<TSharedPtr<FMutableCodeTreeElement>> NameBasedNavigationElements;
|
|
|
|
/** Index in the above array. Current navigation index for the navigation over elements related with the SearchString */
|
|
int32 StringNavigationIndex = -1;
|
|
|
|
/** UI Callback that sets the backend flag to mirror the UI toggle.
|
|
* @param CheckBoxState The new state of the checkBox object being updated
|
|
*/
|
|
void OnRegexToggleChanged(ECheckBoxState CheckBoxState);
|
|
|
|
/** Exposes arrows to allow navigation over the found elements and handles the navigation using those.
|
|
* @param SearchDirection The direction (up or down) being used to navigate the collection of tree elements
|
|
*/
|
|
void OnTreeStringSearch(SSearchBox::SearchDirection SearchDirection);
|
|
|
|
/** Invoked each time the user changes the search text in the UI. NewText cached in SearchString variable
|
|
* @param InUpdatedText The new value set by the user for the TextBox used to provide the search string.
|
|
*/
|
|
void OnTreeSearchTextChanged(const FText& InUpdatedText);
|
|
|
|
/** Get the search results for the current search. Used by the Ui to generate some context related elements.
|
|
* @return Data for external search results to be shown in the search box.
|
|
*/
|
|
TOptional<SSearchBox::FSearchResultData> SearchResultsData() const;
|
|
|
|
/** Invoked each time the user commits to the text provided. It also caches the text provided by the user
|
|
* @param InUpdatedText The current text being exposed in the UI textBox to be used for search. It is not being used
|
|
* since we rely in the value cached in the global variable "SearchString"
|
|
* @param TextCommitType Determines how the user did commit the search string.
|
|
*/
|
|
void OnTreeSearchTextCommitted(const FText& InUpdatedText, ETextCommit::Type TextCommitType);
|
|
|
|
/** Move the focus to the next element in the collection of related elements to the cached SearchString. */
|
|
void GoToNextOperation();
|
|
|
|
/** Move the focus to the previous element in the collection of related elements to the cached SearchString. */
|
|
void GoToPreviousOperation();
|
|
|
|
/** Provided an index inside the NameBasedNavigationElements array change the focus to it. */
|
|
void GoToTargetOperation(const int32& InTargetIndex);
|
|
|
|
/** Provided a search string and a search type a series of elements to be navigated over */
|
|
void CacheOperationsMatchingStringPattern();
|
|
|
|
/** Searches the item cache in search of a string pattern that can be treated as a regular string or as a Regular expression.
|
|
* @param InStringPattern The string to be searched over. It will get compared with the "Main Label" of the comparing operations.
|
|
* @param bIsRegularExpression True if the InStringPattern is ought to be treated as a regular expression, false otherwise.
|
|
* @param SearchPayload Structure containing the operations to be used as the origin of the search. This object will also contain the results of the search.
|
|
* @param InProgram MutableProgram used to allow the search of the children of the operations being currently processed.
|
|
*/
|
|
void GetOperationsMatchingStringPattern(const FString& InStringPattern,const bool bIsRegularExpression, FElementsSearchCache& SearchPayload, const mu::FProgram& InProgram);
|
|
|
|
/** Provided a ItemCacheKey this method returns the string that represents it. It will not take in consideration duplicated entries since those are not part
|
|
* of said ItemCache.
|
|
* @param InItemCacheKey The key representing the current operation being searched.
|
|
* @return The MainLabel used to display the provided operation.
|
|
*/
|
|
FString GetOperationDescriptiveText(const FItemCacheKey& InItemCacheKey);
|
|
|
|
|
|
/*
|
|
* Main callbacks from the tree widget standard operation.
|
|
*/
|
|
|
|
/** Callback that generates a new Row object based on a Tree Node*/
|
|
TSharedRef<ITableRow> GenerateRowForNodeTree(TSharedPtr<FMutableCodeTreeElement> InInfo, const TSharedRef<STableViewBase>& OwnerTable);
|
|
|
|
/**
|
|
* Provided an element it is returned a list with all the immediate children it has
|
|
* @param InInfo - The MutableCodeElement whose children objects we are searching
|
|
* @param OutChildren - The children of the provided MutableCodeTreeElement
|
|
*/
|
|
void GetChildrenForInfo(TSharedPtr<FMutableCodeTreeElement> InInfo, TArray< TSharedPtr<FMutableCodeTreeElement> >& OutChildren);
|
|
|
|
/**
|
|
* Callback invoked each time an element of the tree gets expanded or contracted
|
|
* @param InInfo - The MutableCodeElement to be contracted or expanded
|
|
* @param bInExpanded - Determines if the action is of contraction (false) or expansion (true).
|
|
*/
|
|
void OnExpansionChanged(TSharedPtr<FMutableCodeTreeElement> InInfo, bool bInExpanded);
|
|
|
|
|
|
/**
|
|
* Callback invoked each time the selected element changes used to generate the previews depending of the
|
|
* operation selected
|
|
* @param InInfo - The MutableCodeElement that has been selected. Can be null if unselected
|
|
* @param SelectInfo - Way in witch the selection changed
|
|
*/
|
|
void OnSelectionChanged(TSharedPtr<FMutableCodeTreeElement> InInfo, ESelectInfo::Type SelectInfo);
|
|
|
|
/**
|
|
* Callback invoked when a tree row is getting removed
|
|
* @param InTreeRow - The tree row that is being removed from the tree view
|
|
*/
|
|
void OnRowReleased(const TSharedRef<ITableRow>& InTreeRow);
|
|
|
|
/** Callback invoked when whe press the right mouse button. Useful for adding context menu objects */
|
|
TSharedPtr<SWidget> OnTreeContextMenuOpening();
|
|
|
|
void TreeExpandRecursive(TSharedPtr<FMutableCodeTreeElement> Info, bool bExpand );
|
|
|
|
/** Temporal object designed to be used during the recursive operation of TreeExpandElements() and group
|
|
* strongly related data
|
|
*/
|
|
struct FProcessedOperationsBuffer
|
|
{
|
|
/** Array with the operation addresses of all original (not duplicates) expanded operations. */
|
|
TArray<mu::OP::ADDRESS> ExpandedOriginalOperations;
|
|
|
|
/** Array with the operation addresses of all duplicated expanded operations. */
|
|
TArray<mu::OP::ADDRESS> ExpandedDuplicatedOperations;
|
|
};
|
|
|
|
/**
|
|
* Expands the provided elements and all the children they have.
|
|
* @note It performs the operation by going to the deepest children and expanding from then upwards to the origin before
|
|
* proceeding to the next parent. This way we make sure that the expansion of the elements is following the order
|
|
* of left to right and top to bottom in a "Z" like pattern like the way the tree gets read by humans.
|
|
* @param InElementsToExpand - The root info objects where to start the expansion
|
|
* @param bForceExpandDuplicates - (Optional) Determines if the duplicated objects must be expanded.
|
|
* Used for certain situations where we want to expand them. By default they do not get expanded
|
|
* @param FilteringDataType - (Optional) determines what kind of operations should be expanded. By default no
|
|
* filtering is applied
|
|
* @param InExpandedOperationsBuffer (Optional) Object containing all the duplicated and original elements already processed
|
|
* during the subsequent recursive calls to this method.
|
|
*/
|
|
void TreeExpandElements(TArray<TSharedPtr<FMutableCodeTreeElement>>& InElementsToExpand,
|
|
bool bForceExpandDuplicates = false,
|
|
mu::EDataType FilteringDataType = mu::EDataType::None,
|
|
TSharedPtr<FProcessedOperationsBuffer> InExpandedOperationsBuffer = nullptr);
|
|
|
|
|
|
/** Expand only the unique elements (mot duplicates) */
|
|
void TreeExpandUnique();
|
|
|
|
/** Expand only the elements using as operation type Instance */
|
|
void TreeExpandInstance();
|
|
|
|
/** Grabs the selected element and expands all the elements inside the selected branch. Duplicates are ignored */
|
|
void TreeExpandSelected();
|
|
|
|
/**
|
|
* Highlights all tree elements that share the same operation as the element provided
|
|
* @param InTargetElement - The info object to be used as blueprint to search for similar objects and highlight them
|
|
*/
|
|
void HighlightDuplicatesOfEntry(const TSharedPtr<FMutableCodeTreeElement>& InTargetElement);
|
|
|
|
/** Clear all the highlighted elements and set them to their default visual state */
|
|
void ClearHighlightedItems();
|
|
|
|
/** Called when any parameter value has changed, with the parameter index as argument. */
|
|
void OnPreviewParameterValueChanged( int32 ParamIndex );
|
|
|
|
/*
|
|
* Element state recalculation
|
|
*/
|
|
|
|
/** FLag that determines if the expansion of elements should require the computation of the state of it's child elements.
|
|
* Useful to avoid unnecessary calls for state resting of movable branches like the children of operations that are repeated
|
|
* in the tree slate */
|
|
bool bShouldRecalculateStates = false;
|
|
|
|
/** Provided an element of the tree view return all the children of it (direct and indirect). The search will stop (depth)
|
|
* if a children is found to not be expanded. This way we avoid infinite searches (since we do not stop at duplicates).
|
|
* @note It DOES NOT check for visibility by asking the TreeView. It only gets the elements that could be seen in theory.
|
|
* @note This method will return expanded and not expanded children but only the expanded children will get it's children searched and therefore
|
|
* provided by this method. In conclusion, only the elements that could be seen by the view will get provide.
|
|
* @param InInfo The element whose children we want to grab. It can be expanded or not.
|
|
* @param OutChildren A collection of children elements. Only the elements that could be seen in the tree view (expanded and the root element of an
|
|
* unexpanded branch) wll get added to this collection.
|
|
*/
|
|
void GetVisibleChildren(TSharedPtr<FMutableCodeTreeElement> InInfo, TSet<TSharedPtr<FMutableCodeTreeElement>>& OutChildren);
|
|
|
|
|
|
/*
|
|
* Control of "Skip Mips" for image operations.
|
|
*/
|
|
|
|
/** */
|
|
int32 MipsToSkip = 0;
|
|
|
|
/** */
|
|
bool bSelectedOperationIsImage = false;
|
|
|
|
/** Stores a list of strings based on the possible types of operations mutable define to be used by the UI */
|
|
EVisibility IsMipSkipVisible() const;
|
|
|
|
/** Stores a list of strings based on the possible types of operations mutable define to be used by the UI */
|
|
TOptional<int32> GetCurrentMipSkip() const;
|
|
|
|
/** */
|
|
void OnCurrentMipSkipChanged(int32 NewValue);
|
|
|
|
/*
|
|
* Remote previewer invocation methods
|
|
*/
|
|
|
|
public:
|
|
void PreviewMutableImage (TSharedPtr<const mu::FImage> InImagePtr);
|
|
void PreviewMutableMesh (TSharedPtr<const mu::FMesh> InMeshPtr);
|
|
void PreviewMutableLayout(TSharedPtr<const mu::FLayout> Layout);
|
|
void PreviewMutableSkeleton(TSharedPtr<const mu::FSkeleton> Skeleton);
|
|
void PreviewMutablePhysics(TSharedPtr<const mu::FPhysicsBody> Physics);
|
|
void PreviewMutableString(const FString& InString);
|
|
void PreviewMutableProjector(const mu::FProjector* Projector);
|
|
void PreviewMutableMatrix(const FMatrix44f& Mat);
|
|
void PreviewMutableShape(const mu::FShape* Shape);
|
|
void PreviewMutableCurve(const FRichCurve& Curve);
|
|
|
|
private:
|
|
void PrepareStringViewer();
|
|
void PrepareImageViewer();
|
|
void PrepareMeshViewer();
|
|
void PrepareInstanceViewer();
|
|
void PrepareLayoutViewer();
|
|
void PrepareProjectorViewer();
|
|
};
|
|
|
|
/** The data of a row on the operation type dropdown. */
|
|
class FMutableOperationElement : public TSharedFromThis<FMutableOperationElement>
|
|
{
|
|
public:
|
|
FMutableOperationElement(mu::EOpType InOperationType,FText OperationTypeName,uint32 OperationTypeInstanceCount,FSlateColor OperationColor)
|
|
{
|
|
OperationType = InOperationType;
|
|
OperationTextColor = OperationColor;
|
|
|
|
// Show the amount of instances of the operation type is found on model.
|
|
// @note This if block will not be triggered when working with an operation type that is not present on the model
|
|
// but added manually to the list of operation types (currently mu::OP_Type::None is an example of this)
|
|
FText OperationsCountText = FText::GetEmpty();
|
|
if (OperationTypeInstanceCount > 0)
|
|
{
|
|
OperationsCountText = FText::Format(INVTEXT(" - ({0})"), OperationTypeInstanceCount);
|
|
}
|
|
OperationTypeText = FText::Format(INVTEXT("{0}{1}"), OperationTypeName,OperationsCountText);
|
|
}
|
|
|
|
public:
|
|
mu::EOpType OperationType;
|
|
FText OperationTypeText;
|
|
FSlateColor OperationTextColor;
|
|
|
|
/** Get the type of visibility an slate representing this objects should have. */
|
|
EVisibility GetEntryVisibility() const
|
|
{
|
|
return OperationType == mu::EOpType::NONE ? EVisibility::Collapsed : EVisibility::Visible;
|
|
}
|
|
};
|
|
|
|
|
|
|
|
/** An row of the code tree in the SMutableCodeViewer. */
|
|
class FMutableCodeTreeElement : public TSharedFromThis<FMutableCodeTreeElement>
|
|
{
|
|
public:
|
|
FMutableCodeTreeElement(int32 InIndexOnTree, const int32& InMutableStateIndex, const TSharedPtr<mu::FModel, ESPMode::ThreadSafe>& InModel, mu::OP::ADDRESS InOperation, const FString& InCaption, const FSlateColor InLabelColor, const TSharedPtr<FMutableCodeTreeElement>* InDuplicatedOf = nullptr);
|
|
|
|
void SetElementCurrentState(const int32& InStateIndex);
|
|
|
|
void GenerateLabelText();
|
|
|
|
int32 GetStateIndex() const;
|
|
|
|
public:
|
|
|
|
/** Model this operation is part of */
|
|
TSharedPtr<mu::FModel, ESPMode::ThreadSafe> MutableModel;
|
|
|
|
/** Mutable Graph Node represented in this tree row. */
|
|
mu::OP::ADDRESS MutableOperation;
|
|
|
|
/** If this tree element is a duplicated of another op, this is the op. */
|
|
TSharedPtr<FMutableCodeTreeElement> DuplicatedOf;
|
|
|
|
/** The color to be used by the row representing this object */
|
|
FSlateColor LabelColor;
|
|
|
|
/** Label to be used to represent this operation in the tree */
|
|
FString MainLabel;
|
|
|
|
/*
|
|
* Navigation metadata
|
|
*/
|
|
|
|
/** The current position of this element on the tree view. Used for navigation */
|
|
int32 IndexOnTree;
|
|
|
|
/*
|
|
* Dynamic data : Can and will change during the standard operation of the tree view object.
|
|
*/
|
|
|
|
/** If true means that it will not update when a runtime parameter on the state gets updated */
|
|
bool bIsStateConstant = false;
|
|
|
|
/** If true then the mesh or image of this operation may change during the state update */
|
|
bool bIsDynamicResource = false;
|
|
|
|
/** Flag that reflects the expanded state of the element in the tree view. It is used in order to know when an element
|
|
* should or should not has it's set state index updated (and the data that comes with it).
|
|
* @note It does not mean the element can be seen at the moment in the view, just that, in case of expansion of a parent
|
|
* element then this could be part of the view (if inside view space).
|
|
*/
|
|
bool bIsExpanded = false;
|
|
|
|
private:
|
|
/** Represents as part of what state this element is currently part of. Will change for elements that are children
|
|
* of duplicated elements (duplicated) since children of duplicated elements are still unique and therefore they can
|
|
* be present in more than one state (but can just appear in one state at any given time)
|
|
*/
|
|
int32 CurrentMutableStateIndex = -1;
|
|
|
|
/** String representing additional data like the state this operation is from. It may be empty. */
|
|
FString Caption;
|
|
};
|