Hello All.
What is the proper way to archive (serialize, and deserialize) enumerations? For some reason I am not able to include them in the stream.
I have several enum’s defined at the global namespace, all contained within a single header file, and of the format:
UENUM(BlueprintType)
enum class EditMode : uint8
{
Add UMETA(DisplayName = "Add"),
Modify UMETA(DisplayName = "Modify"),
View UMETA(DisplayName = "View"),
Delete UMETA(DisplayName = "Delete")
};
And from this I attempted to use the below in the same header file:
FORCEINLINE FArchive& operator<<(FArchive& ar, EditMode& editMode)
{
ar << editMode;
return ar;
}
Unfortunately I get bazaar errors:
'operator<<' : recursive on all control paths, function will cause runtime stack overflow
:
:
'operator<<' : recursive call has no side effects, deleting
Can someone provide any insight into this?
Thank you for your help.
Rama
(Rama)
August 2, 2015, 12:23am
2
Serializing Enum as Byte (inside a USTRUCT)
Dear Community and ,
Here’s a system I’ve used in the past for serializing enums.
I wrote this up quickly just for you and anyone else who read this
I used this method to serialize BP-exposed Enums in Solus quite successfully so I know it works
Including the USTRUCT is not necessary, I was just demoing the chain of operator<< overloads and also making sure it all compiled properly
UENUM(BlueprintType)
enum class ENature : uint8
{
Trees UMETA(DisplayName = "Trees"),
Streams UMETA(DisplayName = "Streams"),
Flowers UMETA(DisplayName = "Flowers"),
Rivers UMETA(DisplayName = "Rivers")
};
USTRUCT()
struct FNatureStruct
{
GENERATED_USTRUCT_BODY()
UPROPERTY()
ENature Nature1;
FNatureStruct(){}
};
FORCEINLINE FArchive &operator<<(FArchive &Ar, ENature& TheEnum)
{
uint8 AsByte = (uint8)TheEnum; //When saving
//Serialize as byte
Ar << AsByte;
//Loading
if(Ar.IsLoading())
{
TheEnum = (ENature)AsByte; //When loading
}
return Ar;
}
FORCEINLINE FArchive &operator<<(FArchive &Ar, FNatureStruct& TheStruct)
{
Ar << TheStruct.Nature1;
return Ar;
}
**<< Operator Goes Both Ways**
Remember the << operator is used during both loading and saving, that's why I have to make sure that both saving and loading are covered inside the operator:
```
FORCEINLINE FArchive &operator<<(FArchive &Ar, ENature& TheEnum)
{
uint8 AsByte = (uint8)TheEnum; //When saving
//Serialize as byte
Ar << AsByte;
//Loading
if(Ar.IsLoading())
{
TheEnum = (ENature)AsByte; //When loading
}
return Ar;
}
```
Thank You for Enum Extending Byte !
This is all even easier now that we have the wonderful new enum syntax that extends directly from uint8! Thanks Epic!
I hope you find this useful and everyone!
Enjoy!
Rama
Thank you Rama. Based on your example I have the following that appears to work:
if (ar.IsSaving())
{
uint8 val = (uint8)data.myType;
ar << val;
}
else
{
uint8 val;
ar << val;
data.myType = (MyEnumType)val;
}
May I ask how would you handle TArray<enum> myArray?
If I try to define the operator<< for the different enumerations I get the bazaar error that I mentioned above.
To get around the errors I am converting the enumerations “up” a level in the stream instead of relying on the operator overload.
uced
(uced)
September 7, 2015, 4:03pm
4
Hello,
Just in case this helps, it seems that when declared as a TEnumAsByte, everything is handled gracefully.
The following code works for me:
UENUM()
enum ObjectMeshTypeEnum
{
OBJECT_MESH_TYPE_CUBE,
OBJECT_MESH_TYPE_MODEL,
OBJECT_MESH_TYPE_EFFECT
};
-------------------------------------------------------------------
UPROPERTY()
TEnumAsByte<ObjectMeshTypeEnum> MeshTypeEnum;
-------------------------------------------------------------------
Ar << MeshTypeEnum;
Cheers
Cedric
Jambax
(Jambax)
September 7, 2015, 4:14pm
5
I use class-based enums now instead, they’re much easier to work with than the TEnumAsByte workaround, and you get some level of control over their size as well (sizeof)