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;
}