bool UTextProperty::Identical( const void* A, const void* B, uint32 PortFlags ) const
{
	const TCppType ValueA = GetPropertyValue(A);
	if ( B )
	{
		const TCppType ValueB = GetPropertyValue(B);

		if ( ValueA.IsCultureInvariant() != ValueB.IsCultureInvariant() || ValueA.IsTransient() != ValueB.IsTransient() )
		{
			//A culture variant text is never equal to a culture invariant text
			//A transient text is never equal to a non-transient text
			return false;
		}
		
		if ( ValueA.IsCultureInvariant() == ValueB.IsCultureInvariant() || ValueA.IsTransient() == ValueB.IsTransient() )
		{
			//Culture invariant text don't have a namespace/key so we compare the source string
			//Transient text don't have a namespace/key or source so we compare the display string
			return *FTextInspector::GetDisplayString(ValueA) == *FTextInspector::GetDisplayString(ValueB);
		}

#if WITH_EDITOR
		return *FTextInspector::GetSourceString(ValueA) == *FTextInspector::GetSourceString(ValueB);
#else
		return	FTextInspector::GetNamespace(ValueA)	==	FTextInspector::GetNamespace(ValueB) &&
				FTextInspector::GetKey(ValueA)			==	FTextInspector::GetKey(ValueB);
#endif
	}

	return FTextInspector::GetDisplayString(ValueA).IsEmpty();
}
bool UTextProperty::Identical( const void* A, const void* B, uint32 PortFlags ) const
{
	const TCppType ValueA = GetPropertyValue(A);
	if ( B )
	{
		const TCppType ValueB = GetPropertyValue(B);

		if ( ValueA.IsCultureInvariant() != ValueB.IsCultureInvariant() || ValueA.IsTransient() != ValueB.IsTransient() )
		{
			//A culture variant text is never equal to a culture invariant text
			//A transient text is never equal to a non-transient text
			return false;
		}
		
		if ( ValueA.IsCultureInvariant() == ValueB.IsCultureInvariant() || ValueA.IsTransient() == ValueB.IsTransient() )
		{
			//Culture invariant text don't have a namespace/key so we compare the source string
			//Transient text don't have a namespace/key or source so we compare the display string
			return FTextInspector::GetDisplayString(ValueA) == FTextInspector::GetDisplayString(ValueB);
		}

		if (GIsEditor)
		{
			return FTextInspector::GetSourceString(ValueA)->Compare(*FTextInspector::GetSourceString(ValueB), ESearchCase::CaseSensitive) == 0;
		}
		else
		{
			return	FTextInspector::GetNamespace(ValueA)	==	FTextInspector::GetNamespace(ValueB) &&
					FTextInspector::GetKey(ValueA)			==	FTextInspector::GetKey(ValueB);
		}
	}

	return FTextInspector::GetDisplayString(ValueA).IsEmpty();
}
void UTextProperty::SerializeItem( FArchive& Ar, void* Value, int32 MaxReadBytes, void const* Defaults ) const
{
	const TCppType PropertyValue = GetPropertyValue(Value);
	if ( Ar.IsSaving() && Ar.IsPersistent() && PropertyValue.IsTransient() )
	{
		const FText ErrorMessage = FText::Format( FText::SerializationFailureError, FText::FromString( FTextInspector::GetDisplayString(PropertyValue) ) );
		UE_LOG( LogProperty, Warning, TEXT("%s"), *ErrorMessage.ToString());
		SetPropertyValue(Value, ErrorMessage);
	}

	Ar << *GetPropertyValuePtr(Value);
}