387 lines
11 KiB
C++
387 lines
11 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "MuCOE/CustomizableObjectDetails.h"
|
|
|
|
#include "DetailLayoutBuilder.h"
|
|
#include "DetailWidgetRow.h"
|
|
#include "IDetailsView.h"
|
|
#include "MuCO/CustomizableObject.h"
|
|
#include "MuCO/CustomizableObjectPrivate.h"
|
|
#include "MuCOE/GraphTraversal.h"
|
|
#include "MuCOE/Nodes/CustomizableObjectNodeObject.h"
|
|
#include "MuR/Model.h"
|
|
#include "MuR/Parameters.h"
|
|
#include "MuR/Ptr.h"
|
|
|
|
class ITableRow;
|
|
|
|
|
|
#define LOCTEXT_NAMESPACE "CustomizableObjectDetails"
|
|
|
|
TSharedRef<IDetailCustomization> FCustomizableObjectDetails::MakeInstance()
|
|
{
|
|
return MakeShareable( new FCustomizableObjectDetails );
|
|
}
|
|
|
|
|
|
class FStateDetailsNode
|
|
{
|
|
public:
|
|
|
|
FStateDetailsNode()
|
|
{
|
|
StateIndex = -1;
|
|
ParameterIndex = -1;
|
|
}
|
|
|
|
TSharedPtr<mu::FModel, ESPMode::ThreadSafe> Model;
|
|
int StateIndex;
|
|
int ParameterIndex;
|
|
|
|
TSharedPtr<FString> GetName()
|
|
{
|
|
FString res;
|
|
|
|
if (ParameterIndex<0)
|
|
{
|
|
res = Model->GetStateName( StateIndex );
|
|
}
|
|
else
|
|
{
|
|
TSharedPtr<mu::FParameters> TempParams = mu::FModel::NewParameters(Model);
|
|
res = TempParams->GetName( ParameterIndex );
|
|
}
|
|
|
|
return MakeShareable( new FString( res ) );
|
|
}
|
|
|
|
|
|
TArray<TSharedPtr<FStateDetailsNode>> GetChildrenList()
|
|
{
|
|
TArray<TSharedPtr<FStateDetailsNode>> ChildrenList;
|
|
|
|
// Is it a state node?
|
|
if (ParameterIndex<0)
|
|
{
|
|
int ParameterCount = Model->GetStateParameterCount( StateIndex );
|
|
for ( int i=0; i<ParameterCount; ++i )
|
|
{
|
|
TSharedPtr<FStateDetailsNode> SlateDetailsNode = MakeShareable( new FStateDetailsNode );
|
|
|
|
SlateDetailsNode->Model = Model;
|
|
SlateDetailsNode->StateIndex = StateIndex;
|
|
SlateDetailsNode->ParameterIndex = Model->GetStateParameterIndex( StateIndex, i );
|
|
|
|
ChildrenList.Add( SlateDetailsNode );
|
|
}
|
|
}
|
|
|
|
return ChildrenList;
|
|
}
|
|
};
|
|
|
|
|
|
void FCustomizableObjectDetails::CustomizeDetails( IDetailLayoutBuilder& DetailBuilder )
|
|
{
|
|
TSharedPtr<const IDetailsView> DetailsView = DetailBuilder.GetDetailsViewSharedPtr();
|
|
if (DetailsView && DetailsView->GetSelectedObjects().Num())
|
|
{
|
|
CustomizableObject = Cast<UCustomizableObject>(DetailsView->GetSelectedObjects()[0].Get());
|
|
}
|
|
|
|
IDetailCategoryBuilder& CustomizableObjectCategory = DetailBuilder.EditCategory("CustomizableObject");
|
|
IDetailCategoryBuilder& StatesCategory = DetailBuilder.EditCategory( "States" );
|
|
IDetailCategoryBuilder& VersioningCategory = DetailBuilder.EditCategory( "Versioning" );
|
|
//StatesCategory.CategoryIcon( "ActorClassIcon.CustomizableObject" );
|
|
|
|
DetailBuilder.HideProperty("States");
|
|
DetailBuilder.HideProperty("CustomizableObjectClassTags");
|
|
DetailBuilder.HideProperty("PopulationClassTags");
|
|
|
|
// Make the tree get automatically updated each time we compile the host CO
|
|
if (CustomizableObject && !CustomizableObject->GetPrivate()->PostCompileDelegate.IsBoundToObject(this))
|
|
{
|
|
CustomizableObject->GetPrivate()->PostCompileDelegate.AddSP(this, &FCustomizableObjectDetails::UpdateTree);
|
|
}
|
|
|
|
// Cache the states defined in the CO
|
|
UpdateTree();
|
|
|
|
StatesCategory.AddCustomRow( LOCTEXT("FCustomizableObjectDetails States", "States") )
|
|
[
|
|
SNew( SVerticalBox )
|
|
+ SVerticalBox::Slot()
|
|
.Padding( 2.0f )
|
|
[
|
|
SAssignNew(StatesTree, STreeView<TSharedPtr<FStateDetailsNode>>)
|
|
.SelectionMode(ESelectionMode::Single)
|
|
.TreeItemsSource( &RootTreeItems )
|
|
// Called to child items for any given parent item
|
|
.OnGetChildren( this, &FCustomizableObjectDetails::OnGetChildrenForStateTree )
|
|
// Generates the actual widget for a tree item
|
|
.OnGenerateRow( this, &FCustomizableObjectDetails::OnGenerateRowForStateTree )
|
|
.HeaderRow
|
|
(
|
|
SNew(SHeaderRow)
|
|
.Visibility(EVisibility::Collapsed)
|
|
+ SHeaderRow::Column(TEXT("State"))
|
|
.DefaultLabel(NSLOCTEXT("CustomizableObjectDetails","State","State"))
|
|
)
|
|
]
|
|
];
|
|
|
|
StatesTree->SetIsRightClickScrollingEnabled(false);
|
|
|
|
TSharedRef<IPropertyHandle> VersionBridgeProperty = DetailBuilder.GetProperty("VersionBridge");
|
|
|
|
if (VersionBridgeProperty->IsValidHandle() && CustomizableObject)
|
|
{
|
|
if (CustomizableObject->IsChildObject())
|
|
{
|
|
VersionBridgeProperty->MarkHiddenByCustomization();
|
|
}
|
|
else
|
|
{
|
|
VersionBridgeProperty->MarkResetToDefaultCustomized();
|
|
}
|
|
}
|
|
|
|
TSharedRef<IPropertyHandle> VersionStructProperty = DetailBuilder.GetProperty("VersionStruct");
|
|
|
|
if (VersionStructProperty->IsValidHandle() && CustomizableObject)
|
|
{
|
|
if (CustomizableObject->IsChildObject())
|
|
{
|
|
VersionStructProperty->MarkResetToDefaultCustomized();
|
|
}
|
|
else
|
|
{
|
|
VersionStructProperty->MarkHiddenByCustomization();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void FCustomizableObjectDetails::UpdateTree()
|
|
{
|
|
UCustomizableObject* RootObject = GraphTraversal::GetRootObject(CustomizableObject);
|
|
|
|
if (RootObject && RootObject->GetPrivate()->GetModel() )
|
|
{
|
|
RootTreeItems.SetNumUninitialized(0);
|
|
const uint32 NumElements = RootObject->GetPrivate()->GetModel()->GetStateCount();
|
|
for ( uint32 i=0; i<NumElements; ++i )
|
|
{
|
|
TSharedPtr<FStateDetailsNode> SlateDetailsNode = MakeShareable( new FStateDetailsNode );
|
|
|
|
SlateDetailsNode->Model = RootObject->GetPrivate()->GetModel();
|
|
SlateDetailsNode->StateIndex = i;
|
|
|
|
RootTreeItems.Add( SlateDetailsNode );
|
|
}
|
|
}
|
|
|
|
if (StatesTree)
|
|
{
|
|
StatesTree->RequestTreeRefresh();
|
|
}
|
|
}
|
|
|
|
|
|
/** The item used for visualizing the class in the tree. */
|
|
class SStateItem : public STableRow< TSharedPtr<FString> >
|
|
{
|
|
public:
|
|
|
|
SLATE_BEGIN_ARGS( SStateItem )
|
|
: _StateName()
|
|
, _OwnerTableView()
|
|
, _HighlightText(NULL)
|
|
, _TextColor(FLinearColor(1.0f, 1.0f, 1.0f, 1.0f))
|
|
{}
|
|
|
|
/** The classname this item contains. */
|
|
SLATE_ARGUMENT( TSharedPtr<FString>, StateName )
|
|
/** The table that owns this item. */
|
|
SLATE_ARGUMENT( TSharedPtr<STableViewBase>, OwnerTableView )
|
|
/** The text this item should highlight, if any. */
|
|
SLATE_ARGUMENT( const FString*, HighlightText )
|
|
/** The color text this item will use. */
|
|
SLATE_ARGUMENT( FSlateColor, TextColor )
|
|
/** The node this item is associated with. */
|
|
SLATE_ARGUMENT( TSharedPtr<FStateDetailsNode>, AssociatedNode)
|
|
|
|
SLATE_END_ARGS()
|
|
|
|
/**
|
|
* Construct the widget
|
|
*
|
|
* @param InArgs A declaration from which to construct the widget
|
|
*/
|
|
void Construct( const FArguments& InArgs )
|
|
{
|
|
StateName = InArgs._StateName;
|
|
AssociatedNode = InArgs._AssociatedNode;
|
|
|
|
FMargin Padding = { 0.0f, 3.0f, 6.0f, 3.0f };
|
|
|
|
if (AssociatedNode->ParameterIndex != INDEX_NONE)
|
|
{
|
|
Padding = { 10.0f, 3.0f, 6.0f, 3.0f };
|
|
}
|
|
|
|
this->ChildSlot
|
|
[
|
|
SNew(SHorizontalBox)
|
|
|
|
+SHorizontalBox::Slot()
|
|
.AutoWidth()
|
|
.VAlign(VAlign_Center)
|
|
.HAlign(HAlign_Right)
|
|
[
|
|
SNew( SExpanderArrow, SharedThis(this) )
|
|
]
|
|
|
|
+SHorizontalBox::Slot()
|
|
.AutoWidth()
|
|
.Padding( Padding )
|
|
.VAlign(VAlign_Center)
|
|
.HAlign(HAlign_Left)
|
|
[
|
|
SNew( STextBlock )
|
|
.Text( FText::FromString(*StateName.Get()) )
|
|
//.HighlightString(*InArgs._HighlightText)
|
|
//.ColorAndOpacity( this, &SClassItem::GetTextColor)
|
|
]
|
|
|
|
//+SHorizontalBox::Slot()
|
|
// .HAlign(HAlign_Right)
|
|
// .VAlign(VAlign_Center)
|
|
// .Padding( 0.0f, 0.0f, 6.0f, 0.0f )
|
|
// [
|
|
// SNew( SComboButton )
|
|
// .ContentPadding(FMargin(2.0f))
|
|
// //.OnGetMenuContent(this, &SClassItem::GenerateDropDown)
|
|
// ]
|
|
];
|
|
|
|
TextColor = InArgs._TextColor;
|
|
|
|
STableRow< TSharedPtr<FString> >::ConstructInternal(
|
|
STableRow::FArguments()
|
|
.ShowSelection(true),
|
|
InArgs._OwnerTableView.ToSharedRef() );
|
|
}
|
|
|
|
private:
|
|
|
|
/**
|
|
* Generates the drop down menu for the item.
|
|
*
|
|
* @return The drop down menu widget.
|
|
*/
|
|
/*
|
|
TSharedRef<SWidget> GenerateDropDown()
|
|
{
|
|
// Empty list of commands.
|
|
TSharedPtr< FUICommandList > Commands;
|
|
|
|
const bool bShouldCloseWindowAfterMenuSelection = true; // Set the menu to automatically close when the user commits to a choice
|
|
FMenuBuilder MenuBuilder( bShouldCloseWindowAfterMenuSelection, Commands);
|
|
{
|
|
if (UClass* Class = AssociatedNode->Class.Get())
|
|
{
|
|
bool bIsBlueprint(false);
|
|
bool bHasBlueprint(false);
|
|
|
|
ClassViewer::Helpers::GetClassInfo(Class, bIsBlueprint, bHasBlueprint);
|
|
|
|
bHasBlueprint = AssociatedNode->Blueprint.IsValid();
|
|
|
|
if (bIsBlueprint)
|
|
{
|
|
FUIAction Action( FExecuteAction::CreateStatic( &ClassViewer::Helpers::CreateBlueprint, Class ) );
|
|
MenuBuilder.AddMenuEntry(TEXT("Create Blueprint..."), TEXT("Creates a new Blueprint from the current one."), NAME_None, Action);
|
|
}
|
|
|
|
if (bHasBlueprint)
|
|
{
|
|
MenuBuilder.AddMenuSeparator();
|
|
|
|
FUIAction Action( FExecuteAction::CreateStatic( &ClassViewer::Helpers::OpenBlueprintTool, ClassViewer::Helpers::GetBlueprint(Class) ) );
|
|
MenuBuilder.AddMenuEntry(TEXT("Open Blueprint Editor"), TEXT("Open the Blueprint in the editor."), NAME_None, Action);
|
|
}
|
|
|
|
if (bHasBlueprint)
|
|
{
|
|
MenuBuilder.AddMenuSeparator();
|
|
|
|
FUIAction Action( FExecuteAction::CreateStatic( &ClassViewer::Helpers::FindInContentBrowser, ClassViewer::Helpers::GetBlueprint(Class), Class ) );
|
|
MenuBuilder.AddMenuEntry(TEXT("Find In Content Browser"), TEXT("Find in Content Browser"), NAME_None, Action);
|
|
}
|
|
}
|
|
}
|
|
|
|
return MenuBuilder.MakeWidget();
|
|
}
|
|
*/
|
|
|
|
/** Returns the text color for the item based on if it is selected or not. */
|
|
FSlateColor GetTextColor() const
|
|
{
|
|
const TSharedPtr< ITypedTableView< TSharedPtr<FString> > > OwnerWidget = OwnerTablePtr.Pin();
|
|
const TSharedPtr<FString>* MyItem = OwnerWidget->Private_ItemFromWidget( this );
|
|
const bool bIsSelected = OwnerWidget->Private_IsItemSelected( *MyItem );
|
|
|
|
if(bIsSelected)
|
|
{
|
|
return FSlateColor::UseForeground();
|
|
}
|
|
|
|
return TextColor;
|
|
}
|
|
|
|
private:
|
|
|
|
/** The class name for which this item is associated with. */
|
|
TSharedPtr<FString> StateName;
|
|
|
|
/** The text color for this item. */
|
|
FSlateColor TextColor;
|
|
|
|
/** The Class Viewer Node this item is associated with. */
|
|
TSharedPtr< FStateDetailsNode > AssociatedNode;
|
|
|
|
};
|
|
|
|
|
|
TSharedRef< ITableRow > FCustomizableObjectDetails::OnGenerateRowForStateTree( TSharedPtr<FStateDetailsNode> Item, const TSharedRef< STableViewBase >& OwnerTable )
|
|
{
|
|
// If the item was accepted by the filter, leave it bright, otherwise dim it.
|
|
float AlphaValue = 1.0f;
|
|
TSharedRef< ITableRow > ReturnRow = SNew(SStateItem)
|
|
.StateName(Item->GetName())
|
|
//.HighlightText(&SearchBox->GetText())
|
|
.TextColor(FLinearColor(1.0f, 1.0f, 1.0f, AlphaValue))
|
|
.AssociatedNode(Item)
|
|
.OwnerTableView( OwnerTable );
|
|
|
|
// Expand the item if needed.
|
|
//bool* bIsExpanded = ExpansionStateMap.Find( Item->GetName() );
|
|
//if( bIsExpanded && *bIsExpanded )
|
|
//{
|
|
// StatesTree->SetItemExpansion( Item, *bIsExpanded );
|
|
//}
|
|
|
|
return ReturnRow;
|
|
}
|
|
|
|
|
|
void FCustomizableObjectDetails::OnGetChildrenForStateTree( TSharedPtr<FStateDetailsNode> InParent, TArray< TSharedPtr< FStateDetailsNode > >& OutChildren )
|
|
{
|
|
// Simply return the children, it's already setup.
|
|
OutChildren = InParent->GetChildrenList();
|
|
}
|
|
|
|
#undef LOCTEXT_NAMESPACE
|