EM_Task/CoreUObject/Private/UObject/PropertyBool.cpp
Boshuang Zhao 5144a49c9b add
2026-02-13 16:18:33 +08:00

388 lines
12 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "CoreMinimal.h"
#include "UObject/ObjectMacros.h"
#include "UObject/UObjectGlobals.h"
#include "UObject/UnrealType.h"
#include "UObject/UnrealTypePrivate.h"
#include "UObject/PropertyHelper.h"
// WARNING: This should always be the last include in any file that needs it (except .generated.h)
#include "UObject/UndefineUPropertyMacros.h"
/*-----------------------------------------------------------------------------
FBoolProperty.
-----------------------------------------------------------------------------*/
IMPLEMENT_FIELD(FBoolProperty)
FBoolProperty::FBoolProperty(FFieldVariant InOwner, const FName& InName, EObjectFlags InObjectFlags)
: FProperty(InOwner, InName, InObjectFlags), FieldSize(0), ByteOffset(0), ByteMask(1), FieldMask(1)
{
SetBoolSize(1, false, 1);
}
FBoolProperty::FBoolProperty(FFieldVariant InOwner, const FName& InName, EObjectFlags InObjectFlags, int32 InOffset, EPropertyFlags InFlags, uint32 InBitMask, uint32 InElementSize, bool bIsNativeBool)
: FProperty(InOwner, InName, InObjectFlags, InOffset, InFlags | CPF_HasGetValueTypeHash), FieldSize(0), ByteOffset(0), ByteMask(1), FieldMask(1)
{
SetBoolSize(InElementSize, bIsNativeBool, InBitMask);
}
#if WITH_EDITORONLY_DATA
FBoolProperty::FBoolProperty(UField* InField)
: FProperty(InField)
{
UBoolProperty* SourceProperty = CastChecked<UBoolProperty>(InField);
FieldSize = SourceProperty->FieldSize;
ByteOffset = SourceProperty->ByteOffset;
ByteMask = SourceProperty->ByteMask;
FieldMask = SourceProperty->FieldMask;
}
#endif // WITH_EDITORONLY_DATA
void FBoolProperty::PostDuplicate(const FField& InField)
{
const FBoolProperty& Source = static_cast<const FBoolProperty&>(InField);
FieldSize = Source.FieldSize;
ByteOffset = Source.ByteOffset;
ByteMask = Source.ByteMask;
FieldMask = Source.FieldMask;
Super::PostDuplicate(InField);
}
void FBoolProperty::SetBoolSize(const uint32 InSize, const bool bIsNativeBool, const uint32 InBitMask /*= 0*/)
{
if (bIsNativeBool)
{
PropertyFlags |= (CPF_IsPlainOldData | CPF_NoDestructor | CPF_ZeroConstructor);
}
else
{
PropertyFlags &= ~(CPF_IsPlainOldData | CPF_ZeroConstructor);
PropertyFlags |= CPF_NoDestructor;
}
uint32 TestBitmask = InBitMask ? InBitMask : 1;
ElementSize = InSize;
FieldSize = (uint8)ElementSize;
ByteOffset = 0;
if (bIsNativeBool)
{
ByteMask = true;
FieldMask = 255;
}
else
{
// Calculate ByteOffset and get ByteMask.
for (ByteOffset = 0; ByteOffset < InSize && ((ByteMask = *((uint8*)&TestBitmask + ByteOffset)) == 0); ByteOffset++)
;
FieldMask = ByteMask;
}
check((int32)FieldSize == ElementSize);
check(ElementSize != 0);
check(FieldMask != 0);
check(ByteMask != 0);
}
int32 FBoolProperty::GetMinAlignment() const
{
int32 Alignment = 0;
switch (ElementSize)
{
case sizeof(uint8):
Alignment = alignof(uint8);
break;
case sizeof(uint16):
Alignment = alignof(uint16);
break;
case sizeof(uint32):
Alignment = alignof(uint32);
break;
case sizeof(uint64):
Alignment = alignof(uint64);
break;
default:
UE_LOG(LogProperty, Fatal, TEXT("Unsupported FBoolProperty %s size %d."), *GetName(), (int32)ElementSize);
}
return Alignment;
}
void FBoolProperty::LinkInternal(FArchive& Ar)
{
check(FieldSize != 0);
ElementSize = FieldSize;
if (IsNativeBool())
{
PropertyFlags |= (CPF_IsPlainOldData | CPF_NoDestructor | CPF_ZeroConstructor);
}
else
{
PropertyFlags &= ~(CPF_IsPlainOldData | CPF_ZeroConstructor);
PropertyFlags |= CPF_NoDestructor;
}
}
void FBoolProperty::Serialize(FArchive& Ar)
{
Super::Serialize(Ar);
Ar << FieldSize;
Ar << ByteOffset;
Ar << ByteMask;
Ar << FieldMask;
// Serialize additional flags which will help to identify this FBoolProperty type and size.
uint8 BoolSize = (uint8)ElementSize;
Ar << BoolSize;
uint8 NativeBool = false;
if (Ar.IsLoading())
{
Ar << NativeBool;
// if (!IsPendingKill())
{
SetBoolSize(BoolSize, !!NativeBool);
}
}
else
{
NativeBool = Ar.IsSaving() ? (IsNativeBool() ? 1 : 0) : 0;
Ar << NativeBool;
}
}
FString FBoolProperty::GetCPPType(FString* ExtendedTypeText /*=NULL*/, uint32 CPPExportFlags /*=0*/) const
{
check(FieldSize != 0);
if (IsNativeBool() || ((CPPExportFlags & (CPPF_Implementation | CPPF_ArgumentOrReturnValue)) == (CPPF_Implementation | CPPF_ArgumentOrReturnValue)) || ((CPPExportFlags & CPPF_BlueprintCppBackend) != 0))
{
// Export as bool if this is actually a bool or it's being exported as a return value of C++ function definition.
return TEXT("bool");
}
else
{
// Bitfields
switch (ElementSize)
{
case sizeof(uint64):
return TEXT("uint64");
case sizeof(uint32):
return TEXT("uint32");
case sizeof(uint16):
return TEXT("uint16");
case sizeof(uint8):
return TEXT("uint8");
default:
UE_LOG(LogProperty, Fatal, TEXT("Unsupported FBoolProperty %s size %d."), *GetName(), ElementSize);
break;
}
}
return TEXT("uint32");
}
FString FBoolProperty::GetCPPTypeForwardDeclaration() const
{
return FString();
}
FString FBoolProperty::GetCPPMacroType(FString& ExtendedTypeText) const
{
check(FieldSize != 0);
if (IsNativeBool())
{
return TEXT("UBOOL");
}
else
{
switch (ElementSize)
{
case sizeof(uint64):
return TEXT("UBOOL64");
case sizeof(uint32):
return TEXT("UBOOL32");
case sizeof(uint16):
return TEXT("UBOOL16");
case sizeof(uint8):
return TEXT("UBOOL8");
default:
UE_LOG(LogProperty, Fatal, TEXT("Unsupported FBoolProperty %s size %d."), *GetName(), ElementSize);
break;
}
}
return TEXT("UBOOL32");
}
template <typename T>
void LoadFromType(FBoolProperty* Property, const FPropertyTag& Tag, FStructuredArchive::FSlot Slot, uint8* Data)
{
T IntValue;
Slot << IntValue;
if (IntValue != 0)
{
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
if (IntValue != 1)
{
UE_LOG(LogClass, Log, TEXT("Loading %s property (%s) that is now a bool - value '%d', expecting 0 or 1. Value set to true."), *Tag.Type.ToString(), *Property->GetPathName(), IntValue);
}
#endif
Property->SetPropertyValue_InContainer(Data, true, Tag.ArrayIndex);
}
else
{
Property->SetPropertyValue_InContainer(Data, false, Tag.ArrayIndex);
}
}
EConvertFromTypeResult FBoolProperty::ConvertFromType(const FPropertyTag& Tag, FStructuredArchive::FSlot Slot, uint8* Data, UStruct* DefaultsStruct)
{
if (Tag.Type == NAME_IntProperty)
{
LoadFromType<int32>(this, Tag, Slot, Data);
}
else if (Tag.Type == NAME_Int8Property)
{
LoadFromType<int8>(this, Tag, Slot, Data);
}
else if (Tag.Type == NAME_Int16Property)
{
LoadFromType<int16>(this, Tag, Slot, Data);
}
else if (Tag.Type == NAME_Int64Property)
{
LoadFromType<int64>(this, Tag, Slot, Data);
}
else if (Tag.Type == NAME_ByteProperty)
{
// if the byte property was an enum we won't allow a conversion to bool
if (Tag.EnumName == NAME_None)
{
// If we're a nested property the EnumName tag got lost, don't allow this
if (GetOwner<FProperty>())
{
return EConvertFromTypeResult::UseSerializeItem;
}
LoadFromType<uint8>(this, Tag, Slot, Data);
}
else
{
return EConvertFromTypeResult::UseSerializeItem;
}
}
else if (Tag.Type == NAME_UInt16Property)
{
LoadFromType<uint16>(this, Tag, Slot, Data);
}
else if (Tag.Type == NAME_UInt32Property)
{
LoadFromType<uint32>(this, Tag, Slot, Data);
}
else if (Tag.Type == NAME_UInt64Property)
{
LoadFromType<uint64>(this, Tag, Slot, Data);
}
else
{
return EConvertFromTypeResult::UseSerializeItem;
}
return EConvertFromTypeResult::Converted;
}
void FBoolProperty::ExportTextItem(FString& ValueStr, const void* PropertyValue, const void* DefaultValue, UObject* Parent, int32 PortFlags, UObject* ExportRootScope) const
{
check(FieldSize != 0);
const uint8* ByteValue = (uint8*)PropertyValue + ByteOffset;
const bool bValue = 0 != ((*ByteValue) & FieldMask);
const TCHAR* Temp = nullptr;
if (0 != (PortFlags & PPF_ExportCpp))
{
Temp = (bValue ? TEXT("true") : TEXT("false"));
}
else
{
Temp = (bValue ? TEXT("True") : TEXT("False"));
}
ValueStr += FString::Printf(TEXT("%s"), Temp);
}
const TCHAR* FBoolProperty::ImportText_Internal(const TCHAR* Buffer, void* Data, int32 PortFlags, UObject* Parent, FOutputDevice* ErrorText) const
{
FString Temp;
Buffer = FPropertyHelpers::ReadToken(Buffer, Temp);
if (!Buffer)
{
return NULL;
}
check(FieldSize != 0);
uint8* ByteValue = (uint8*)Data + ByteOffset;
const FCoreTexts& CoreTexts = FCoreTexts::Get();
if (Temp == TEXT("1") || Temp == TEXT("True") || Temp == *CoreTexts.True.ToString() || Temp == TEXT("Yes") || Temp == *CoreTexts.Yes.ToString())
{
*ByteValue |= ByteMask;
}
else if (Temp == TEXT("0") || Temp == TEXT("False") || Temp == *CoreTexts.False.ToString() || Temp == TEXT("No") || Temp == *CoreTexts.No.ToString())
{
*ByteValue &= ~FieldMask;
}
else
{
// UE_LOG(LogProperty, Log, "Import: Failed to get bool" );
return NULL;
}
return Buffer;
}
bool FBoolProperty::Identical(const void* A, const void* B, uint32 PortFlags) const
{
check(FieldSize != 0);
const uint8* ByteValueA = (const uint8*)A + ByteOffset;
const uint8* ByteValueB = (const uint8*)B + ByteOffset;
return ((*ByteValueA ^ (B ? *ByteValueB : 0)) & FieldMask) == 0;
}
void FBoolProperty::SerializeItem(FStructuredArchive::FSlot Slot, void* Value, void const* Defaults) const
{
check(FieldSize != 0);
uint8* ByteValue = (uint8*)Value + ByteOffset;
uint8 B = (*ByteValue & FieldMask) ? 1 : 0;
Slot << B;
*ByteValue = ((*ByteValue) & ~FieldMask) | (B ? ByteMask : 0);
}
bool FBoolProperty::NetSerializeItem(FArchive& Ar, UPackageMap* Map, void* Data, TArray<uint8>* MetaData) const
{
check(FieldSize != 0);
uint8* ByteValue = (uint8*)Data + ByteOffset;
uint8 Value = ((*ByteValue & FieldMask) != 0);
Ar.SerializeBits(&Value, 1);
*ByteValue = ((*ByteValue) & ~FieldMask) | (Value ? ByteMask : 0);
return true;
}
void FBoolProperty::CopyValuesInternal(void* Dest, void const* Src, int32 Count) const
{
check(FieldSize != 0 && !IsNativeBool());
for (int32 Index = 0; Index < Count; Index++)
{
uint8* DestByteValue = (uint8*)Dest + Index * ElementSize + ByteOffset;
uint8* SrcByteValue = (uint8*)Src + Index * ElementSize + ByteOffset;
*DestByteValue = (*DestByteValue & ~FieldMask) | (*SrcByteValue & FieldMask);
}
}
void FBoolProperty::ClearValueInternal(void* Data) const
{
check(FieldSize != 0);
uint8* ByteValue = (uint8*)Data + ByteOffset;
*ByteValue &= ~FieldMask;
}
void FBoolProperty::InitializeValueInternal(void* Data) const
{
check(FieldSize != 0);
uint8* ByteValue = (uint8*)Data + ByteOffset;
*ByteValue &= ~FieldMask;
}
uint32 FBoolProperty::GetValueTypeHashInternal(const void* Src) const
{
return GetTypeHash(*(const bool*)Src);
}
#include "UObject/DefineUPropertyMacros.h"