void FReplaceVectorWithLinearColorBuilder::GeneratePropertyContent(const TSharedRef<IPropertyHandle>& Handle, IDetailChildrenBuilder& ChildrenBuilder) { // Add to the current builder, depending on the property type. uint32 NumChildren = 0; ensure(Handle->GetNumChildren(NumChildren) == FPropertyAccess::Success); bool bHasChildren = (NumChildren > 0); bool bIsArray = Handle->AsArray().IsValid(); if (bIsArray) { // Arrays need special handling and will create an array builder TSharedRef<FDetailArrayBuilder> ArrayBuilder = MakeShareable(new FDetailArrayBuilder(Handle)); ArrayBuilder->OnGenerateArrayElementWidget(FOnGenerateArrayElementWidget::CreateSP(this, &FReplaceVectorWithLinearColorBuilder::OnGenerateArrayElementWidget)); ChildrenBuilder.AddChildCustomBuilder(ArrayBuilder); } else if (bHasChildren) { // If there are children, we invoke a new instance of our custom builder for recursive handling // Note, if this is an FVector, it will be handled specially by the implementation of the IDetailCustomNodeBuilder interface. TSharedRef<FReplaceVectorWithLinearColorBuilder> StructBuilder = MakeShareable(new FReplaceVectorWithLinearColorBuilder(Handle)); ChildrenBuilder.AddChildCustomBuilder(StructBuilder); } else { // No children - just add the property. ChildrenBuilder.AddChildProperty(Handle); } }
void SheetEquipmentCustomization::CustomizeDetails(IDetailLayoutBuilder& DetailBuilder) { IDetailCategoryBuilder& Category = DetailBuilder.EditCategory("Slots", FText::GetEmpty(), ECategoryPriority::Important); //You can get properties using the detailbuilder TSharedRef<IPropertyHandle> BaseHandle = DetailBuilder.GetProperty("Equipment"); if (!BaseHandle->IsValidHandle()) { Category.AddCustomRow(LOCTEXT("Fail", "Fail")) .NameContent() [ SNew(STextBlock) .Text(LOCTEXT("Fail", "Fail")) .Font(IDetailLayoutBuilder::GetDetailFont()) ]; return; } BaseHandle->MarkHiddenByCustomization(); uint32 num; BaseHandle->AsArray()->GetNumElements(num); for (uint32 i = 0; i < num; i++) { FText text = StatEnums::EquipSlots()->GetEnumText(i); Category.AddCustomRow(text) .NameContent() [ SNew(STextBlock) .Text(text) .Font(IDetailLayoutBuilder::GetDetailFont()) ] .ValueContent().MinDesiredWidth(500) [ SNew(SHorizontalBox) + SHorizontalBox::Slot() [ SNew(SProperty, BaseHandle->AsArray()->GetElement(i)->GetChildHandle("Item")) .ShouldDisplayName(false) ]]; } }
void ConditionTranslationMetadata( TSharedRef<FLocMetadataValue> MetadataValue ) { switch( MetadataValue->Type ) { case ELocMetadataType::String: { TSharedPtr<FLocMetadataValue> MetadataValuePtr = MetadataValue; TSharedPtr<FLocMetadataValueString> MetadataString = StaticCastSharedPtr<FLocMetadataValueString>( MetadataValuePtr ); MetadataString->SetString( TEXT("") ); } break; case ELocMetadataType::Array: { TArray< TSharedPtr< FLocMetadataValue > > MetadataArray = MetadataValue->AsArray(); for( auto ArrayIter = MetadataArray.CreateIterator(); ArrayIter; ++ArrayIter ) { TSharedPtr<FLocMetadataValue>& Item = *ArrayIter; if( Item.IsValid() ) { ConditionTranslationMetadata( Item.ToSharedRef() ); } } } break; case ELocMetadataType::Object: { TSharedPtr< FLocMetadataObject > MetadataObject = MetadataValue->AsObject(); for( auto ValueIter = MetadataObject->Values.CreateConstIterator(); ValueIter; ++ValueIter ) { const FString Name = (*ValueIter).Key; TSharedPtr< FLocMetadataValue > Value = (*ValueIter).Value; if( Value.IsValid() ) { if( Value->Type == ELocMetadataType::String ) { MetadataObject->SetStringField( Name, TEXT("") ); } else { ConditionTranslationMetadata( Value.ToSharedRef() ); } } } } default: break; } }
TSharedPtr<FJsonValue> LocMetaDataValueToJsonValue( const TSharedRef< FLocMetadataValue > MetadataValue ) { switch( MetadataValue->Type ) { case ELocMetadataType::Boolean: { return MakeShareable( new FJsonValueBoolean( MetadataValue->AsBool() ) ); } break; case ELocMetadataType::String: { return MakeShareable( new FJsonValueString( MetadataValue->AsString() ) ); } break; case ELocMetadataType::Array: { TArray< TSharedPtr<FJsonValue> > JsonArrayVals; TArray< TSharedPtr< FLocMetadataValue > > MetaDataArray = MetadataValue->AsArray(); MetaDataArray.Sort( FCompareLocMetadataValue() ); for( auto ArrayIter = MetaDataArray.CreateConstIterator(); ArrayIter; ++ArrayIter ) { const TSharedPtr<FLocMetadataValue>& Item = *ArrayIter; if( Item.IsValid() ) { TSharedPtr<FJsonValue> Entry = LocMetaDataValueToJsonValue( Item.ToSharedRef() ); if( Entry.IsValid() ) { JsonArrayVals.Add( Entry ); } } } if( JsonArrayVals.Num() > 0 ) { return MakeShareable( new FJsonValueArray( JsonArrayVals ) ); } } break; case ELocMetadataType::Object: { TSharedPtr< FJsonObject > JsonSubObject = MakeShareable( new FJsonObject ); TSharedPtr< FLocMetadataObject > MetaDataObject = MetadataValue->AsObject(); for( auto ValueIter = MetaDataObject->Values.CreateConstIterator(); ValueIter; ++ValueIter ) { const FString Name = (*ValueIter).Key; TSharedPtr< FLocMetadataValue > Value = (*ValueIter).Value; if( Value.IsValid() ) { TSharedPtr< FJsonValue > JsonValue = LocMetaDataValueToJsonValue( Value.ToSharedRef() ); if( JsonValue.IsValid() ) { JsonSubObject->SetField( Name, JsonValue ); } } } // Sorting by key is probably sufficient for now but ideally we would sort the resulting json object using // the same logic that is in the FLocMetadata < operator JsonSubObject->Values.KeySort( TLess<FString>() ); return MakeShareable( new FJsonValueObject(JsonSubObject) ); } default: break; } return NULL; }
TSharedPtr<FLocMetadataValue> JSonValueToLocMetaDataValue( const TSharedRef< FJsonValue > JsonValue ) { switch( JsonValue->Type ) { case EJson::Boolean: { return MakeShareable( new FLocMetadataValueBoolean( JsonValue->AsBool() ) ); } break; case EJson::String: { return MakeShareable( new FLocMetadataValueString( JsonValue->AsString() ) ); } break; case EJson::Array: { TArray< TSharedPtr< FLocMetadataValue > > MetadataArray; TArray< TSharedPtr< FJsonValue > > JsonArray = JsonValue->AsArray(); for( auto ArrayIter = JsonArray.CreateConstIterator(); ArrayIter; ++ArrayIter ) { const TSharedPtr< FJsonValue >& Item = *ArrayIter; if( Item.IsValid() ) { TSharedPtr< FLocMetadataValue > Entry = JSonValueToLocMetaDataValue( Item.ToSharedRef() ); if( Entry.IsValid() ) { MetadataArray.Add( Entry ); } } } if( MetadataArray.Num() > 0 ) { return MakeShareable( new FLocMetadataValueArray( MetadataArray ) ); } } break; case EJson::Object: { TSharedPtr< FLocMetadataObject > MetadataSubObject = MakeShareable( new FLocMetadataObject ); TSharedPtr< FJsonObject > JsonObject = JsonValue->AsObject(); for( auto ValueIter = JsonObject->Values.CreateConstIterator(); ValueIter; ++ValueIter ) { const FString Name = (*ValueIter).Key; TSharedPtr< FJsonValue > Value = (*ValueIter).Value; if( Value.IsValid() ) { TSharedPtr< FLocMetadataValue > MetadataValue = JSonValueToLocMetaDataValue( Value.ToSharedRef() ); if( MetadataValue.IsValid() ) { MetadataSubObject->SetField( Name, MetadataValue ); } } } return MakeShareable( new FLocMetadataValueObject(MetadataSubObject) ); } break; default: { // At the moment we do not support all the json types as metadata. In the future these types will be handled in a way that they can be stored in an unprocessed way. } break; } return NULL; }