Files
UnrealEngineUWP/Engine/Source/Runtime/WebBrowser/Private/CEF/CEFJSStructSerializerBackend.cpp
marc audy cff01aa9fa Added support for native FProperty setters and getters.
Setters and getters are native functions called by FProperties when setting property values with *_InContainer functions.
Setters and getter function names can be manually specified with Setter = Func and Getter = Func keywords inside of UPROEPRTY macro but they will also be automatically parsed if the name is not explicitly specified if the setter or getter function name matches SetPropertyName and GetPropertyName pattern.
The latter behavior can be disabled in UHT's DefaultEngine.ini by setting AutomaticSettersAndGetters=False.
ImportText and ExportTextItem functions have been deprecated and should be replaced with *_InContainer or *_Direct variants.

#rb Steve.Robb
#preflight 6210a377a83e0bcefd03d9e1

#ROBOMERGE-OWNER: marc.audy
#ROBOMERGE-AUTHOR: robert.manuszewski
#ROBOMERGE-SOURCE: CL 19070318 via CL 19098059 via CL 19104650 via CL 19104661 via CL 19110012
#ROBOMERGE-BOT: UE5 (Release-Engine-Staging -> Main) (v921-19075845)

[CL 19147839 by marc audy in ue5-main branch]
2022-02-25 10:39:39 -05:00

299 lines
9.9 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "CEF/CEFJSStructSerializerBackend.h"
#if WITH_CEF3
#include "UObject/EnumProperty.h"
#include "UObject/TextProperty.h"
#include "UObject/PropertyPortFlags.h"
#include "Misc/CommandLine.h"
static FString GetBindingName(const TSharedPtr<FCEFJSScripting>& Scripting, const FProperty* ValueProperty)
{
//@todo samz - HACK
static const bool bIsKairos = FParse::Param(FCommandLine::Get(), TEXT("KairosOnly"));
if (bIsKairos)
{
// skip lowercasing property field names for compatibility with FNativeJSStructSerializerBackend/FMobileJSStructSerializerBackend
return ValueProperty->GetName();
}
else
{
return Scripting->GetBindingName(ValueProperty);
}
}
/* Private methods
*****************************************************************************/
void FCEFJSStructSerializerBackend::AddNull(const FStructSerializerState& State)
{
StackItem& Current = Stack.Top();
switch (Current.Kind) {
case StackItem::STYPE_DICTIONARY:
Current.DictionaryValue->SetNull(TCHAR_TO_WCHAR(*GetBindingName(Scripting, State.ValueProperty)));
break;
case StackItem::STYPE_LIST:
Current.ListValue->SetNull(Current.ListValue->GetSize());
break;
}
}
void FCEFJSStructSerializerBackend::Add(const FStructSerializerState& State, bool Value)
{
StackItem& Current = Stack.Top();
switch (Current.Kind) {
case StackItem::STYPE_DICTIONARY:
Current.DictionaryValue->SetBool(TCHAR_TO_WCHAR(*GetBindingName(Scripting, State.ValueProperty)), Value);
break;
case StackItem::STYPE_LIST:
Current.ListValue->SetBool(Current.ListValue->GetSize(), Value);
break;
}
}
void FCEFJSStructSerializerBackend::Add(const FStructSerializerState& State, int32 Value)
{
StackItem& Current = Stack.Top();
switch (Current.Kind) {
case StackItem::STYPE_DICTIONARY:
Current.DictionaryValue->SetInt(TCHAR_TO_WCHAR(*GetBindingName(Scripting, State.ValueProperty)), Value);
break;
case StackItem::STYPE_LIST:
Current.ListValue->SetInt(Current.ListValue->GetSize(), Value);
break;
}
}
void FCEFJSStructSerializerBackend::Add(const FStructSerializerState& State, double Value)
{
StackItem& Current = Stack.Top();
switch (Current.Kind) {
case StackItem::STYPE_DICTIONARY:
Current.DictionaryValue->SetDouble(TCHAR_TO_WCHAR(*GetBindingName(Scripting, State.ValueProperty)), Value);
break;
case StackItem::STYPE_LIST:
Current.ListValue->SetDouble(Current.ListValue->GetSize(), Value);
break;
}
}
void FCEFJSStructSerializerBackend::Add(const FStructSerializerState& State, FString Value)
{
StackItem& Current = Stack.Top();
switch (Current.Kind) {
case StackItem::STYPE_DICTIONARY:
Current.DictionaryValue->SetString(TCHAR_TO_WCHAR(*GetBindingName(Scripting, State.ValueProperty)), TCHAR_TO_WCHAR(*Value));
break;
case StackItem::STYPE_LIST:
Current.ListValue->SetString(Current.ListValue->GetSize(), TCHAR_TO_WCHAR(*Value));
break;
}
}
void FCEFJSStructSerializerBackend::Add(const FStructSerializerState& State, UObject* Value)
{
StackItem& Current = Stack.Top();
switch (Current.Kind) {
case StackItem::STYPE_DICTIONARY:
Current.DictionaryValue->SetDictionary(TCHAR_TO_WCHAR(*GetBindingName(Scripting, State.ValueProperty)), Scripting->ConvertObject(Value));
break;
case StackItem::STYPE_LIST:
Current.ListValue->SetDictionary(Current.ListValue->GetSize(), Scripting->ConvertObject(Value));
break;
}
}
/* IStructSerializerBackend interface
*****************************************************************************/
void FCEFJSStructSerializerBackend::BeginArray(const FStructSerializerState& State)
{
CefRefPtr<CefListValue> ListValue = CefListValue::Create();
Stack.Push(StackItem(GetBindingName(Scripting, State.ValueProperty), ListValue));
}
void FCEFJSStructSerializerBackend::BeginStructure(const FStructSerializerState& State)
{
if (State.KeyProperty != nullptr)
{
FString KeyString;
State.KeyProperty->ExportTextItem_Direct(KeyString, State.KeyData, nullptr, nullptr, PPF_None);
CefRefPtr<CefDictionaryValue> DictionaryValue = CefDictionaryValue::Create();
Stack.Push(StackItem(KeyString, DictionaryValue));
}
else if (State.ValueProperty != nullptr)
{
CefRefPtr<CefDictionaryValue> DictionaryValue = CefDictionaryValue::Create();
Stack.Push(StackItem(GetBindingName(Scripting, State.ValueProperty), DictionaryValue));
}
else
{
Result = CefDictionaryValue::Create();
Stack.Push(StackItem(FString(), Result));
}
}
void FCEFJSStructSerializerBackend::EndArray(const FStructSerializerState& /*State*/)
{
StackItem Previous = Stack.Pop();
check(Previous.Kind == StackItem::STYPE_LIST);
check(Stack.Num() > 0); // The root level object is always a struct
StackItem& Current = Stack.Top();
switch (Current.Kind) {
case StackItem::STYPE_DICTIONARY:
Current.DictionaryValue->SetList(TCHAR_TO_WCHAR(*Previous.Name), Previous.ListValue);
break;
case StackItem::STYPE_LIST:
Current.ListValue->SetList(Current.ListValue->GetSize(), Previous.ListValue);
break;
}
}
void FCEFJSStructSerializerBackend::EndStructure(const FStructSerializerState& /*State*/)
{
StackItem Previous = Stack.Pop();
check(Previous.Kind == StackItem::STYPE_DICTIONARY);
if (Stack.Num() > 0)
{
StackItem& Current = Stack.Top();
switch (Current.Kind) {
case StackItem::STYPE_DICTIONARY:
Current.DictionaryValue->SetDictionary(TCHAR_TO_WCHAR(*Previous.Name), Previous.DictionaryValue);
break;
case StackItem::STYPE_LIST:
Current.ListValue->SetDictionary(Current.ListValue->GetSize(), Previous.DictionaryValue);
break;
}
}
else
{
check(Result == Previous.DictionaryValue);
}
}
void FCEFJSStructSerializerBackend::WriteComment(const FString& Comment)
{
// Cef values do not support comments
}
void FCEFJSStructSerializerBackend::WriteProperty(const FStructSerializerState& State, int32 ArrayIndex)
{
// booleans
if (State.FieldType == FBoolProperty::StaticClass())
{
Add(State, CastFieldChecked<FBoolProperty>(State.ValueProperty)->GetPropertyValue_InContainer(State.ValueData, ArrayIndex));
}
// unsigned bytes & enumerations
else if (State.FieldType == FEnumProperty::StaticClass())
{
FEnumProperty* EnumProperty = CastFieldChecked<FEnumProperty>(State.ValueProperty);
Add(State, EnumProperty->GetEnum()->GetNameStringByValue(EnumProperty->GetUnderlyingProperty()->GetSignedIntPropertyValue(EnumProperty->ContainerPtrToValuePtr<void>(State.ValueData, ArrayIndex))));
}
else if (State.FieldType == FByteProperty::StaticClass())
{
FByteProperty* ByteProperty = CastFieldChecked<FByteProperty>(State.ValueProperty);
if (ByteProperty->IsEnum())
{
Add(State, ByteProperty->Enum->GetNameStringByValue(ByteProperty->GetPropertyValue_InContainer(State.ValueData, ArrayIndex)));
}
else
{
Add(State, (double)ByteProperty->GetPropertyValue_InContainer(State.ValueData, ArrayIndex));
}
}
// floating point numbers
else if (State.FieldType == FDoubleProperty::StaticClass())
{
Add(State, CastFieldChecked<FDoubleProperty>(State.ValueProperty)->GetPropertyValue_InContainer(State.ValueData, ArrayIndex));
}
else if (State.FieldType == FFloatProperty::StaticClass())
{
Add(State, CastFieldChecked<FFloatProperty>(State.ValueProperty)->GetPropertyValue_InContainer(State.ValueData, ArrayIndex));
}
// signed integers
else if (State.FieldType == FIntProperty::StaticClass())
{
Add(State, (int32)CastFieldChecked<FIntProperty>(State.ValueProperty)->GetPropertyValue_InContainer(State.ValueData, ArrayIndex));
}
else if (State.FieldType == FInt8Property::StaticClass())
{
Add(State, (int32)CastFieldChecked<FInt8Property>(State.ValueProperty)->GetPropertyValue_InContainer(State.ValueData, ArrayIndex));
}
else if (State.FieldType == FInt16Property::StaticClass())
{
Add(State, (int32)CastFieldChecked<FInt16Property>(State.ValueProperty)->GetPropertyValue_InContainer(State.ValueData, ArrayIndex));
}
else if (State.FieldType == FInt64Property::StaticClass())
{
Add(State, (double)CastFieldChecked<FInt64Property>(State.ValueProperty)->GetPropertyValue_InContainer(State.ValueData, ArrayIndex));
}
// unsigned integers
else if (State.FieldType == FUInt16Property::StaticClass())
{
Add(State, (int32)CastFieldChecked<FUInt16Property>(State.ValueProperty)->GetPropertyValue_InContainer(State.ValueData, ArrayIndex));
}
else if (State.FieldType == FUInt32Property::StaticClass())
{
Add(State, (double)CastFieldChecked<FUInt32Property>(State.ValueProperty)->GetPropertyValue_InContainer(State.ValueData, ArrayIndex));
}
else if (State.FieldType == FUInt64Property::StaticClass())
{
Add(State, (double)CastFieldChecked<FUInt64Property>(State.ValueProperty)->GetPropertyValue_InContainer(State.ValueData, ArrayIndex));
}
// names & strings
else if (State.FieldType == FNameProperty::StaticClass())
{
Add(State, CastFieldChecked<FNameProperty>(State.ValueProperty)->GetPropertyValue_InContainer(State.ValueData, ArrayIndex).ToString());
}
else if (State.FieldType == FStrProperty::StaticClass())
{
Add(State, CastFieldChecked<FStrProperty>(State.ValueProperty)->GetPropertyValue_InContainer(State.ValueData, ArrayIndex));
}
else if (State.FieldType == FTextProperty::StaticClass())
{
Add(State, CastFieldChecked<FTextProperty>(State.ValueProperty)->GetPropertyValue_InContainer(State.ValueData, ArrayIndex).ToString());
}
// classes & objects
else if (FClassProperty* ClassProperty = CastField<FClassProperty>(State.ValueProperty))
{
Add(State, ClassProperty->GetPropertyValue_InContainer(State.ValueData, ArrayIndex)->GetPathName());
}
else if (FObjectProperty* ObjectProperty = CastField<FObjectProperty>(State.ValueProperty))
{
Add(State, ObjectProperty->GetPropertyValue_InContainer(State.ValueData, ArrayIndex));
}
// unsupported property type
else
{
GLog->Logf(ELogVerbosity::Warning, TEXT("FCEFJSStructSerializerBackend: Property %s cannot be serialized, because its type (%s) is not supported"), *State.ValueProperty->GetName(), *State.ValueType->GetName());
}
}
#endif