You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
Merging //UE4/Dev-Main @ 4114877 to Dev-Core (//UE4/Dev-Core)
#rb none [CL 4115001 by Robert Manuszewski in Dev-Core branch]
This commit is contained in:
@@ -6,6 +6,7 @@
|
||||
|
||||
#include "PyWrapperObject.h"
|
||||
#include "PyWrapperStruct.h"
|
||||
#include "PyWrapperEnum.h"
|
||||
#include "PyWrapperDelegate.h"
|
||||
#include "PyWrapperName.h"
|
||||
#include "PyWrapperText.h"
|
||||
@@ -57,7 +58,7 @@ FPyConversionResult NativizeStructInstance(PyObject* PyObj, UScriptStruct* Struc
|
||||
StructType->CopyScriptStruct(StructInstance, PyStruct->StructInstance);
|
||||
}
|
||||
|
||||
PYCONVERSION_RETURN(Result, TEXT("Nativize"), *FString::Printf(TEXT("Cannot nativize '%s' as '%s'"), *PyUtil::GetFriendlyTypename(PyObj), *StructType->GetName()));
|
||||
PYCONVERSION_RETURN(Result, TEXT("Nativize"), *FString::Printf(TEXT("Cannot nativize '%s' as '%s'"), *PyUtil::GetFriendlyTypename(PyObj), *PyUtil::GetFriendlyTypename(PyStructType)));
|
||||
}
|
||||
|
||||
FPyConversionResult PythonizeStructInstance(UScriptStruct* StructType, const void* StructInstance, PyObject*& OutPyObj, const ESetErrorState SetErrorState)
|
||||
@@ -627,6 +628,48 @@ PyObject* PythonizeStruct(UScriptStruct* Val, const ESetErrorState SetErrorState
|
||||
return Obj;
|
||||
}
|
||||
|
||||
FPyConversionResult NativizeEnumEntry(PyObject* PyObj, const UEnum* EnumType, int64& OutVal, const ESetErrorState SetErrorState)
|
||||
{
|
||||
FPyConversionResult Result = FPyConversionResult::Failure();
|
||||
|
||||
PyTypeObject* PyEnumType = FPyWrapperTypeRegistry::Get().GetWrappedEnumType(EnumType);
|
||||
FPyWrapperEnumPtr PyEnum = FPyWrapperEnumPtr::StealReference(FPyWrapperEnum::CastPyObject(PyObj, PyEnumType, &Result));
|
||||
if (PyEnum)
|
||||
{
|
||||
OutVal = FPyWrapperEnum::GetEnumEntryValue(PyEnum);
|
||||
}
|
||||
|
||||
PYCONVERSION_RETURN(Result, TEXT("Nativize"), *FString::Printf(TEXT("Cannot nativize '%s' as '%s'"), *PyUtil::GetFriendlyTypename(PyObj), *PyUtil::GetFriendlyTypename(PyEnumType)));
|
||||
}
|
||||
|
||||
FPyConversionResult PythonizeEnumEntry(const int64 Val, const UEnum* EnumType, PyObject*& OutPyObj, const ESetErrorState SetErrorState)
|
||||
{
|
||||
PyTypeObject* PyEnumType = FPyWrapperTypeRegistry::Get().GetWrappedEnumType(EnumType);
|
||||
if (const FPyWrapperEnumMetaData* PyEnumMetaData = FPyWrapperEnumMetaData::GetMetaData(PyEnumType))
|
||||
{
|
||||
// Find an enum entry using this value
|
||||
for (FPyWrapperEnum* PyEnumEntry : PyEnumMetaData->EnumEntries)
|
||||
{
|
||||
const int64 EnumEntryVal = FPyWrapperEnum::GetEnumEntryValue(PyEnumEntry);
|
||||
if (EnumEntryVal == Val)
|
||||
{
|
||||
Py_INCREF(PyEnumEntry);
|
||||
OutPyObj = (PyObject*)PyEnumEntry;
|
||||
return FPyConversionResult::Success();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PYCONVERSION_RETURN(FPyConversionResult::Failure(), TEXT("Nativize"), *FString::Printf(TEXT("Cannot pythonize '%d' (int64) as '%s'"), Val, *PyUtil::GetFriendlyTypename(PyEnumType)));
|
||||
}
|
||||
|
||||
PyObject* PythonizeEnumEntry(const int64 Val, const UEnum* EnumType, const ESetErrorState SetErrorState)
|
||||
{
|
||||
PyObject* Obj = nullptr;
|
||||
PythonizeEnumEntry(Val, EnumType, Obj, SetErrorState);
|
||||
return Obj;
|
||||
}
|
||||
|
||||
FPyConversionResult NativizeProperty(PyObject* PyObj, const UProperty* Prop, void* ValueAddr, const FPyWrapperOwnerContext& InChangeOwner, const ESetErrorState SetErrorState)
|
||||
{
|
||||
#define PYCONVERSION_PROPERTY_RETURN(RESULT) \
|
||||
@@ -709,7 +752,6 @@ FPyConversionResult NativizeProperty_Direct(PyObject* PyObj, const UProperty* Pr
|
||||
|
||||
NATIVIZE_SETTER_PROPERTY(UBoolProperty);
|
||||
NATIVIZE_INLINE_PROPERTY(UInt8Property);
|
||||
NATIVIZE_INLINE_PROPERTY(UByteProperty);
|
||||
NATIVIZE_INLINE_PROPERTY(UInt16Property);
|
||||
NATIVIZE_INLINE_PROPERTY(UUInt16Property);
|
||||
NATIVIZE_INLINE_PROPERTY(UIntProperty);
|
||||
@@ -722,10 +764,74 @@ FPyConversionResult NativizeProperty_Direct(PyObject* PyObj, const UProperty* Pr
|
||||
NATIVIZE_INLINE_PROPERTY(UNameProperty);
|
||||
NATIVIZE_INLINE_PROPERTY(UTextProperty);
|
||||
|
||||
if (auto* CastProp = Cast<UByteProperty>(Prop))
|
||||
{
|
||||
uint8 NewValue = 0;
|
||||
FPyConversionResult Result = FPyConversionResult::Failure();
|
||||
|
||||
if (CastProp->Enum)
|
||||
{
|
||||
int64 EnumVal = 0;
|
||||
Result = NativizeEnumEntry(PyObj, CastProp->Enum, EnumVal, SetErrorState);
|
||||
if (Result.GetState() == EPyConversionResultState::SuccessWithCoercion)
|
||||
{
|
||||
// Don't allow implicit conversion on enum properties
|
||||
Result.SetState(EPyConversionResultState::Failure);
|
||||
}
|
||||
if (Result)
|
||||
{
|
||||
NewValue = (uint8)EnumVal;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Result = Nativize(PyObj, NewValue, SetErrorState);
|
||||
}
|
||||
|
||||
if (Result)
|
||||
{
|
||||
auto* ValuePtr = static_cast<uint8*>(ValueAddr);
|
||||
if (*ValuePtr != NewValue)
|
||||
{
|
||||
EmitPropertyChangeNotifications(InChangeOwner, [&]()
|
||||
{
|
||||
*ValuePtr = NewValue;
|
||||
});
|
||||
}
|
||||
}
|
||||
PYCONVERSION_PROPERTY_RETURN(Result);
|
||||
}
|
||||
|
||||
if (auto* CastProp = Cast<UEnumProperty>(Prop))
|
||||
{
|
||||
FPyConversionResult Result = FPyConversionResult::Failure();
|
||||
|
||||
UNumericProperty* EnumInternalProp = CastProp->GetUnderlyingProperty();
|
||||
PYCONVERSION_PROPERTY_RETURN(EnumInternalProp ? NativizeProperty_Direct(PyObj, EnumInternalProp, ValueAddr, InChangeOwner, SetErrorState) : FPyConversionResult::Failure());
|
||||
if (EnumInternalProp)
|
||||
{
|
||||
int64 NewValue = 0;
|
||||
|
||||
Result = NativizeEnumEntry(PyObj, CastProp->GetEnum(), NewValue, SetErrorState);
|
||||
if (Result.GetState() == EPyConversionResultState::SuccessWithCoercion)
|
||||
{
|
||||
// Don't allow implicit conversion on enum properties
|
||||
Result.SetState(EPyConversionResultState::Failure);
|
||||
}
|
||||
|
||||
if (Result)
|
||||
{
|
||||
const int64 OldValue = EnumInternalProp->GetSignedIntPropertyValue(ValueAddr);
|
||||
if (OldValue != NewValue)
|
||||
{
|
||||
EmitPropertyChangeNotifications(InChangeOwner, [&]()
|
||||
{
|
||||
EnumInternalProp->SetIntPropertyValue(ValueAddr, NewValue);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PYCONVERSION_PROPERTY_RETURN(Result);
|
||||
}
|
||||
|
||||
if (auto* CastProp = Cast<UClassProperty>(Prop))
|
||||
@@ -912,7 +1018,6 @@ FPyConversionResult PythonizeProperty_Direct(const UProperty* Prop, const void*
|
||||
|
||||
PYTHONIZE_GETTER_PROPERTY(UBoolProperty);
|
||||
PYTHONIZE_GETTER_PROPERTY(UInt8Property);
|
||||
PYTHONIZE_GETTER_PROPERTY(UByteProperty);
|
||||
PYTHONIZE_GETTER_PROPERTY(UInt16Property);
|
||||
PYTHONIZE_GETTER_PROPERTY(UUInt16Property);
|
||||
PYTHONIZE_GETTER_PROPERTY(UIntProperty);
|
||||
@@ -925,10 +1030,23 @@ FPyConversionResult PythonizeProperty_Direct(const UProperty* Prop, const void*
|
||||
PYTHONIZE_GETTER_PROPERTY(UNameProperty);
|
||||
PYTHONIZE_GETTER_PROPERTY(UTextProperty);
|
||||
|
||||
if (auto* CastProp = Cast<UByteProperty>(Prop))
|
||||
{
|
||||
const uint8 Value = CastProp->GetPropertyValue(ValueAddr);
|
||||
if (CastProp->Enum)
|
||||
{
|
||||
PYCONVERSION_PROPERTY_RETURN(PythonizeEnumEntry((int64)Value, CastProp->Enum, OutPyObj, SetErrorState));
|
||||
}
|
||||
else
|
||||
{
|
||||
PYCONVERSION_PROPERTY_RETURN(Pythonize(Value, OutPyObj, SetErrorState));
|
||||
}
|
||||
}
|
||||
|
||||
if (auto* CastProp = Cast<UEnumProperty>(Prop))
|
||||
{
|
||||
UNumericProperty* EnumInternalProp = CastProp->GetUnderlyingProperty();
|
||||
PYCONVERSION_PROPERTY_RETURN(EnumInternalProp ? PythonizeProperty_Direct(EnumInternalProp, ValueAddr, OutPyObj, ConversionMethod, OwnerPyObj, SetErrorState) : FPyConversionResult::Failure());
|
||||
PYCONVERSION_PROPERTY_RETURN(PythonizeEnumEntry(EnumInternalProp ? EnumInternalProp->GetSignedIntPropertyValue(ValueAddr) : 0, CastProp->GetEnum(), OutPyObj, SetErrorState));
|
||||
}
|
||||
|
||||
if (auto* CastProp = Cast<UClassProperty>(Prop))
|
||||
|
||||
@@ -100,6 +100,11 @@ namespace PyConversion
|
||||
FPyConversionResult PythonizeStruct(UScriptStruct* Val, PyObject*& OutPyObj, const ESetErrorState SetErrorState = ESetErrorState::Yes);
|
||||
PyObject* PythonizeStruct(UScriptStruct* Val, const ESetErrorState SetErrorState = ESetErrorState::Yes);
|
||||
|
||||
/** Conversion for enum entries */
|
||||
FPyConversionResult NativizeEnumEntry(PyObject* PyObj, const UEnum* EnumType, int64& OutVal, const ESetErrorState SetErrorState = ESetErrorState::Yes);
|
||||
FPyConversionResult PythonizeEnumEntry(const int64 Val, const UEnum* EnumType, PyObject*& OutPyObj, const ESetErrorState SetErrorState = ESetErrorState::Yes);
|
||||
PyObject* PythonizeEnumEntry(const int64 Val, const UEnum* EnumType, const ESetErrorState SetErrorState = ESetErrorState::Yes);
|
||||
|
||||
namespace Internal
|
||||
{
|
||||
/** Internal version of NativizeStructInstance/PythonizeStructInstance that work on the type-erased data */
|
||||
@@ -193,16 +198,23 @@ namespace PyConversion
|
||||
|
||||
/** Conversion for known enum types */
|
||||
template <typename T>
|
||||
FPyConversionResult NativizeEnum(PyObject* PyObj, T& OutVal, const ESetErrorState SetErrorState = ESetErrorState::Yes)
|
||||
FPyConversionResult NativizeEnumEntry(PyObject* PyObj, const UEnum* EnumType, T& OutVal, const ESetErrorState SetErrorState = ESetErrorState::Yes)
|
||||
{
|
||||
return Nativize(PyObj, (__underlying_type(T)&)OutVal, SetErrorState);
|
||||
int64 OutTmpVal = 0;
|
||||
FPyConversionResult Result = NativizeEnumEntry(PyObj, EnumType, OutTmpVal, SetErrorState);
|
||||
if (Result)
|
||||
{
|
||||
OutVal = (T)OutTmpVal;
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
||||
/** Conversion for known enum types */
|
||||
template <typename T>
|
||||
FPyConversionResult PythonizeEnum(const T& Val, PyObject*& OutPyObj, const ESetErrorState SetErrorState = ESetErrorState::Yes)
|
||||
FPyConversionResult PythonizeEnumEntry(const T& Val, const UEnum* EnumType, PyObject*& OutPyObj, const ESetErrorState SetErrorState = ESetErrorState::Yes)
|
||||
{
|
||||
return Pythonize((__underlying_type(T))Val, OutPyObj, SetErrorState);
|
||||
const int64 TmpVal = (int64)Val;
|
||||
return PythonizeEnumEntry(TmpVal, EnumType, OutPyObj, SetErrorState);
|
||||
}
|
||||
|
||||
/** Conversion for property instances (including fixed arrays) - ValueAddr should point to the property data */
|
||||
|
||||
@@ -49,7 +49,7 @@ void FPyFileWriter::Write(const FString& InStr)
|
||||
|
||||
void FPyFileWriter::WriteDocString(const TCHAR* InDocString)
|
||||
{
|
||||
if (*InDocString)
|
||||
if (InDocString && *InDocString)
|
||||
{
|
||||
WriteDocString(FString(InDocString));
|
||||
}
|
||||
|
||||
@@ -653,24 +653,34 @@ void FGeneratedWrappedEnumType::Finalize_PostReady()
|
||||
{
|
||||
FGeneratedWrappedType::Finalize_PostReady();
|
||||
|
||||
check(MetaData.IsValid() && MetaData->GetTypeId() == FPyWrapperEnumMetaData::StaticTypeId());
|
||||
TSharedRef<FPyWrapperEnumMetaData> EnumMetaData = StaticCastSharedRef<FPyWrapperEnumMetaData>(MetaData.ToSharedRef());
|
||||
|
||||
// Execute Python code within this block
|
||||
{
|
||||
FPyScopedGIL GIL;
|
||||
for (const FGeneratedWrappedEnumEntry& EnumEntry : EnumEntries)
|
||||
{
|
||||
FPyWrapperEnum::SetEnumEntryValue(&PyType, EnumEntry.EntryValue, EnumEntry.EntryName.GetData(), EnumEntry.EntryDoc.GetData());
|
||||
FPyWrapperEnum* PyEnumEntry = FPyWrapperEnum::AddEnumEntry(&PyType, EnumEntry.EntryValue, EnumEntry.EntryName.GetData(), EnumEntry.EntryDoc.GetData());
|
||||
if (PyEnumEntry)
|
||||
{
|
||||
EnumMetaData->EnumEntries.Add(PyEnumEntry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EnumMetaData->bFinalized = true;
|
||||
}
|
||||
|
||||
void FGeneratedWrappedEnumType::ExtractEnumEntries(const UEnum* InEnum)
|
||||
{
|
||||
for (int32 EnumEntryIndex = 0; EnumEntryIndex < InEnum->NumEnums() - 1; ++EnumEntryIndex)
|
||||
{
|
||||
// todo: deprecated enum entries?
|
||||
if (ShouldExportEnumEntry(InEnum, EnumEntryIndex))
|
||||
{
|
||||
FGeneratedWrappedEnumEntry& EnumEntry = EnumEntries.AddDefaulted_GetRef();
|
||||
EnumEntry.EntryName = TCHARToUTF8Buffer(*PythonizeName(InEnum->GetNameStringByIndex(EnumEntryIndex), EPythonizeNameCase::Upper));
|
||||
EnumEntry.EntryName = TCHARToUTF8Buffer(*GetEnumEntryPythonName(InEnum, EnumEntryIndex));
|
||||
EnumEntry.EntryDoc = TCHARToUTF8Buffer(*PythonizeTooltip(GetEnumEntryTooltip(InEnum, EnumEntryIndex)));
|
||||
EnumEntry.EntryValue = InEnum->GetValueByIndex(EnumEntryIndex);
|
||||
}
|
||||
@@ -2326,6 +2336,34 @@ TArray<FString> GetDeprecatedEnumPythonNames(const UEnum* InEnum)
|
||||
return GetDeprecatedFieldPythonNamesImpl(InEnum, ScriptNameMetaDataKey);
|
||||
}
|
||||
|
||||
FString GetEnumEntryPythonName(const UEnum* InEnum, const int32 InEntryIndex)
|
||||
{
|
||||
FString EnumEntryName;
|
||||
|
||||
// First see if we have a name override in the meta-data
|
||||
{
|
||||
EnumEntryName = InEnum->GetMetaData(TEXT("ScriptName"), InEntryIndex);
|
||||
|
||||
// This may be a semi-colon separated list - the first item is the one we want for the current name
|
||||
if (!EnumEntryName.IsEmpty())
|
||||
{
|
||||
int32 SemiColonIndex = INDEX_NONE;
|
||||
if (EnumEntryName.FindChar(TEXT(';'), SemiColonIndex))
|
||||
{
|
||||
EnumEntryName.RemoveAt(SemiColonIndex, EnumEntryName.Len() - SemiColonIndex, /*bAllowShrinking*/false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Just use the entry name if we have no meta-data
|
||||
if (EnumEntryName.IsEmpty())
|
||||
{
|
||||
EnumEntryName = InEnum->GetNameStringByIndex(InEntryIndex);
|
||||
}
|
||||
|
||||
return PythonizeName(EnumEntryName, EPythonizeNameCase::Upper);
|
||||
}
|
||||
|
||||
FString GetDelegatePythonName(const UFunction* InDelegateSignature)
|
||||
{
|
||||
return InDelegateSignature->GetName().LeftChop(19); // Trim the "__DelegateSignature" suffix from the name
|
||||
|
||||
@@ -1003,6 +1003,9 @@ namespace PyGenUtil
|
||||
/** Get the deprecated Python names of the given enum */
|
||||
TArray<FString> GetDeprecatedEnumPythonNames(const UEnum* InEnum);
|
||||
|
||||
/** Get the Python name of the given enum entry */
|
||||
FString GetEnumEntryPythonName(const UEnum* InEnum, const int32 InEntryIndex);
|
||||
|
||||
/** Get the Python name of the given delegate signature */
|
||||
FString GetDelegatePythonName(const UFunction* InDelegateSignature);
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "PyConversion.h"
|
||||
#include "PyWrapperTypeRegistry.h"
|
||||
|
||||
#include "UObject/Package.h"
|
||||
#include "Framework/Application/SlateApplication.h"
|
||||
|
||||
#if PLATFORM_WINDOWS
|
||||
@@ -139,8 +140,9 @@ PyObject* ParentExternalWindowToSlate(PyObject* InSelf, PyObject* InArgs)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static const UEnum* ParentWindowSearchMethodEnum = FindObject<UEnum>(ANY_PACKAGE, TEXT("ESlateParentWindowSearchMethod"));
|
||||
ESlateParentWindowSearchMethod ParentWindowSearchMethod = ESlateParentWindowSearchMethod::ActiveWindow;
|
||||
if (PyParentWindowSearchMethod && !PyConversion::NativizeEnum(PyParentWindowSearchMethod, ParentWindowSearchMethod))
|
||||
if (PyParentWindowSearchMethod && !PyConversion::NativizeEnumEntry(PyParentWindowSearchMethod, ParentWindowSearchMethodEnum, ParentWindowSearchMethod))
|
||||
{
|
||||
PyUtil::SetPythonError(PyExc_TypeError, TEXT("parent_external_window_to_slate"), *FString::Printf(TEXT("Failed to convert argument '%s' to 'SlateParentWindowSearchMethod'"), *PyUtil::GetFriendlyTypename(PyParentWindowSearchMethod)));
|
||||
return nullptr;
|
||||
|
||||
@@ -637,6 +637,11 @@ int ValidateContainerIndexParam(const Py_ssize_t InIndex, const Py_ssize_t InLen
|
||||
return 0;
|
||||
}
|
||||
|
||||
Py_ssize_t ResolveContainerIndexParam(const Py_ssize_t InIndex, const Py_ssize_t InLen)
|
||||
{
|
||||
return InIndex < 0 ? InIndex + InLen : InIndex;
|
||||
}
|
||||
|
||||
UObject* GetOwnerObject(PyObject* InPyObj)
|
||||
{
|
||||
FPyWrapperOwnerContext OwnerContext = FPyWrapperOwnerContext(InPyObj);
|
||||
|
||||
@@ -215,6 +215,9 @@ namespace PyUtil
|
||||
/** Validate that the given index is valid for the container length */
|
||||
int ValidateContainerIndexParam(const Py_ssize_t InIndex, const Py_ssize_t InLen, const UProperty* InProp, const TCHAR* InErrorCtxt);
|
||||
|
||||
/** Resolve a container index (taking into account negative indices) */
|
||||
Py_ssize_t ResolveContainerIndexParam(const Py_ssize_t InIndex, const Py_ssize_t InLen);
|
||||
|
||||
/**
|
||||
* Given a Python object, try and get the owner Unreal object for the instance.
|
||||
* For wrapped objects this is the wrapped instance, for wrapped structs it will attempt to walk through the owner chain to find a wrapped object.
|
||||
|
||||
@@ -407,16 +407,17 @@ PyObject* FPyWrapperArray::GetItem(FPyWrapperArray* InSelf, Py_ssize_t InIndex)
|
||||
|
||||
FScriptArrayHelper SelfScriptArrayHelper(InSelf->ArrayProp, InSelf->ArrayInstance);
|
||||
const int32 ElementCount = SelfScriptArrayHelper.Num();
|
||||
const Py_ssize_t ResolvedIndex = PyUtil::ResolveContainerIndexParam(InIndex, ElementCount);
|
||||
|
||||
if (PyUtil::ValidateContainerIndexParam(InIndex, ElementCount, InSelf->ArrayProp, *PyUtil::GetErrorContext(InSelf)) != 0)
|
||||
if (PyUtil::ValidateContainerIndexParam(ResolvedIndex, ElementCount, InSelf->ArrayProp, *PyUtil::GetErrorContext(InSelf)) != 0)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
PyObject* PyItemObj = nullptr;
|
||||
if (!PyConversion::PythonizeProperty(InSelf->ArrayProp->Inner, SelfScriptArrayHelper.GetRawPtr(InIndex), PyItemObj))
|
||||
if (!PyConversion::PythonizeProperty(InSelf->ArrayProp->Inner, SelfScriptArrayHelper.GetRawPtr(ResolvedIndex), PyItemObj))
|
||||
{
|
||||
PyUtil::SetPythonError(PyExc_TypeError, InSelf, *FString::Printf(TEXT("Failed to convert element property '%s' (%s) at index %d"), *InSelf->ArrayProp->Inner->GetName(), *InSelf->ArrayProp->Inner->GetClass()->GetName(), InIndex));
|
||||
PyUtil::SetPythonError(PyExc_TypeError, InSelf, *FString::Printf(TEXT("Failed to convert element property '%s' (%s) at index %d"), *InSelf->ArrayProp->Inner->GetName(), *InSelf->ArrayProp->Inner->GetClass()->GetName(), ResolvedIndex));
|
||||
return nullptr;
|
||||
}
|
||||
return PyItemObj;
|
||||
@@ -431,16 +432,17 @@ int FPyWrapperArray::SetItem(FPyWrapperArray* InSelf, Py_ssize_t InIndex, PyObje
|
||||
|
||||
FScriptArrayHelper SelfScriptArrayHelper(InSelf->ArrayProp, InSelf->ArrayInstance);
|
||||
const int32 ElementCount = SelfScriptArrayHelper.Num();
|
||||
const Py_ssize_t ResolvedIndex = PyUtil::ResolveContainerIndexParam(InIndex, ElementCount);
|
||||
|
||||
const int ValidateIndexResult = PyUtil::ValidateContainerIndexParam(InIndex, ElementCount, InSelf->ArrayProp, *PyUtil::GetErrorContext(InSelf));
|
||||
const int ValidateIndexResult = PyUtil::ValidateContainerIndexParam(ResolvedIndex, ElementCount, InSelf->ArrayProp, *PyUtil::GetErrorContext(InSelf));
|
||||
if (ValidateIndexResult != 0)
|
||||
{
|
||||
return ValidateIndexResult;
|
||||
}
|
||||
|
||||
if (!PyConversion::NativizeProperty(InValue, InSelf->ArrayProp->Inner, SelfScriptArrayHelper.GetRawPtr(InIndex)))
|
||||
if (!PyConversion::NativizeProperty(InValue, InSelf->ArrayProp->Inner, SelfScriptArrayHelper.GetRawPtr(ResolvedIndex)))
|
||||
{
|
||||
PyUtil::SetPythonError(PyExc_TypeError, InSelf, *FString::Printf(TEXT("Failed to convert element property '%s' (%s) at index %d"), *InSelf->ArrayProp->Inner->GetName(), *InSelf->ArrayProp->Inner->GetClass()->GetName(), InIndex));
|
||||
PyUtil::SetPythonError(PyExc_TypeError, InSelf, *FString::Printf(TEXT("Failed to convert element property '%s' (%s) at index %d"), *InSelf->ArrayProp->Inner->GetName(), *InSelf->ArrayProp->Inner->GetClass()->GetName(), ResolvedIndex));
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -640,9 +642,11 @@ Py_ssize_t FPyWrapperArray::Index(FPyWrapperArray* InSelf, PyObject* InValue, Py
|
||||
|
||||
FScriptArrayHelper SelfScriptArrayHelper(InSelf->ArrayProp, InSelf->ArrayInstance);
|
||||
const int32 ElementCount = SelfScriptArrayHelper.Num();
|
||||
const Py_ssize_t ResolvedStartIndex = PyUtil::ResolveContainerIndexParam(InStartIndex, ElementCount);
|
||||
const Py_ssize_t ResolvedStopIndex = PyUtil::ResolveContainerIndexParam(InStopIndex, ElementCount);
|
||||
|
||||
const int32 StartIndex = FMath::Min((int32)InStartIndex, ElementCount);
|
||||
const int32 StopIndex = FMath::Max((int32)InStopIndex, ElementCount);
|
||||
const int32 StartIndex = FMath::Min((int32)ResolvedStartIndex, ElementCount);
|
||||
const int32 StopIndex = FMath::Max((int32)ResolvedStopIndex, ElementCount);
|
||||
|
||||
int32 ReturnIndex = INDEX_NONE;
|
||||
for (int32 ElementIndex = StartIndex; ElementIndex < StopIndex; ++ElementIndex)
|
||||
@@ -672,8 +676,9 @@ int FPyWrapperArray::Insert(FPyWrapperArray* InSelf, Py_ssize_t InIndex, PyObjec
|
||||
|
||||
FScriptArrayHelper SelfScriptArrayHelper(InSelf->ArrayProp, InSelf->ArrayInstance);
|
||||
const int32 ElementCount = SelfScriptArrayHelper.Num();
|
||||
const Py_ssize_t ResolvedIndex = PyUtil::ResolveContainerIndexParam(InIndex, ElementCount);
|
||||
|
||||
const int32 InsertIndex = FMath::Min((int32)InIndex, ElementCount);
|
||||
const int32 InsertIndex = FMath::Min((int32)ResolvedIndex, ElementCount);
|
||||
SelfScriptArrayHelper.InsertValues(InsertIndex);
|
||||
|
||||
if (!PyConversion::NativizeProperty(InValue, InSelf->ArrayProp->Inner, SelfScriptArrayHelper.GetRawPtr(InsertIndex)))
|
||||
@@ -695,21 +700,21 @@ PyObject* FPyWrapperArray::Pop(FPyWrapperArray* InSelf, Py_ssize_t InIndex)
|
||||
|
||||
FScriptArrayHelper SelfScriptArrayHelper(InSelf->ArrayProp, InSelf->ArrayInstance);
|
||||
const int32 ElementCount = SelfScriptArrayHelper.Num();
|
||||
const Py_ssize_t ResolvedIndex = PyUtil::ResolveContainerIndexParam(InIndex, ElementCount);
|
||||
|
||||
int32 ValueIndex = InIndex == -1 ? ElementCount - 1 : (int32)InIndex;
|
||||
if (PyUtil::ValidateContainerIndexParam(ValueIndex, ElementCount, InSelf->ArrayProp, *PyUtil::GetErrorContext(InSelf)) != 0)
|
||||
if (PyUtil::ValidateContainerIndexParam(ResolvedIndex, ElementCount, InSelf->ArrayProp, *PyUtil::GetErrorContext(InSelf)) != 0)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
PyObject* PyReturnValue = nullptr;
|
||||
if (!PyConversion::PythonizeProperty(InSelf->ArrayProp->Inner, SelfScriptArrayHelper.GetRawPtr(ValueIndex), PyReturnValue))
|
||||
if (!PyConversion::PythonizeProperty(InSelf->ArrayProp->Inner, SelfScriptArrayHelper.GetRawPtr(ResolvedIndex), PyReturnValue))
|
||||
{
|
||||
PyUtil::SetPythonError(PyExc_TypeError, InSelf, *FString::Printf(TEXT("Failed to convert element property '%s' (%s) at index %d"), *InSelf->ArrayProp->Inner->GetName(), *InSelf->ArrayProp->Inner->GetClass()->GetName(), ValueIndex));
|
||||
PyUtil::SetPythonError(PyExc_TypeError, InSelf, *FString::Printf(TEXT("Failed to convert element property '%s' (%s) at index %d"), *InSelf->ArrayProp->Inner->GetName(), *InSelf->ArrayProp->Inner->GetClass()->GetName(), ResolvedIndex));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SelfScriptArrayHelper.RemoveValues(ValueIndex);
|
||||
SelfScriptArrayHelper.RemoveValues(ResolvedIndex);
|
||||
|
||||
return PyReturnValue;
|
||||
}
|
||||
@@ -991,7 +996,12 @@ PyTypeObject InitializePyWrapperArrayType()
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const Py_ssize_t SliceLen = FMath::Max(InSliceStop - InSliceStart, (Py_ssize_t)0);
|
||||
FScriptArrayHelper SelfScriptArrayHelper(InSelf->ArrayProp, InSelf->ArrayInstance);
|
||||
const int32 SelfElementCount = SelfScriptArrayHelper.Num();
|
||||
const Py_ssize_t ResolvedSliceStart = PyUtil::ResolveContainerIndexParam(InSliceStart, SelfElementCount);
|
||||
const Py_ssize_t ResolvedSliceStop = PyUtil::ResolveContainerIndexParam(InSliceStop, SelfElementCount);
|
||||
|
||||
const Py_ssize_t SliceLen = FMath::Max(ResolvedSliceStop - ResolvedSliceStart, (Py_ssize_t)0);
|
||||
|
||||
const PyUtil::FPropertyDef SelfElementDef = InSelf->ArrayProp->Inner;
|
||||
FPyWrapperArrayPtr NewArray = FPyWrapperArrayPtr::StealReference(FPyWrapperArray::New(Py_TYPE(InSelf)));
|
||||
@@ -1000,13 +1010,12 @@ PyTypeObject InitializePyWrapperArrayType()
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
FScriptArrayHelper SelfScriptArrayHelper(InSelf->ArrayProp, InSelf->ArrayInstance);
|
||||
FScriptArrayHelper NewScriptArrayHelper(NewArray->ArrayProp, NewArray->ArrayInstance);
|
||||
NewScriptArrayHelper.Resize(SliceLen);
|
||||
|
||||
for (Py_ssize_t ElementIndex = InSliceStart; ElementIndex < InSliceStop; ++ElementIndex)
|
||||
for (Py_ssize_t ElementIndex = ResolvedSliceStart; ElementIndex < ResolvedSliceStop; ++ElementIndex)
|
||||
{
|
||||
InSelf->ArrayProp->Inner->CopyCompleteValue(NewScriptArrayHelper.GetRawPtr((int32)(ElementIndex - InSliceStart)), SelfScriptArrayHelper.GetRawPtr((int32)ElementIndex));
|
||||
InSelf->ArrayProp->Inner->CopyCompleteValue(NewScriptArrayHelper.GetRawPtr((int32)(ElementIndex - ResolvedSliceStart)), SelfScriptArrayHelper.GetRawPtr((int32)ElementIndex));
|
||||
}
|
||||
return (PyObject*)NewArray.Release();
|
||||
}
|
||||
@@ -1018,7 +1027,12 @@ PyTypeObject InitializePyWrapperArrayType()
|
||||
return -1;
|
||||
}
|
||||
|
||||
const Py_ssize_t SliceLen = FMath::Max(InSliceStop - InSliceStart, (Py_ssize_t)0);
|
||||
FScriptArrayHelper SelfScriptArrayHelper(InSelf->ArrayProp, InSelf->ArrayInstance);
|
||||
const int32 SelfElementCount = SelfScriptArrayHelper.Num();
|
||||
const Py_ssize_t ResolvedSliceStart = PyUtil::ResolveContainerIndexParam(InSliceStart, SelfElementCount);
|
||||
const Py_ssize_t ResolvedSliceStop = PyUtil::ResolveContainerIndexParam(InSliceStop, SelfElementCount);
|
||||
|
||||
const Py_ssize_t SliceLen = FMath::Max(ResolvedSliceStop - ResolvedSliceStart, (Py_ssize_t)0);
|
||||
|
||||
// Value will be null when performing a slice delete
|
||||
FPyWrapperArrayPtr Value;
|
||||
@@ -1033,18 +1047,17 @@ PyTypeObject InitializePyWrapperArrayType()
|
||||
}
|
||||
}
|
||||
|
||||
FScriptArrayHelper SelfScriptArrayHelper(InSelf->ArrayProp, InSelf->ArrayInstance);
|
||||
SelfScriptArrayHelper.RemoveValues((int32)InSliceStart, (int32)SliceLen);
|
||||
SelfScriptArrayHelper.RemoveValues((int32)ResolvedSliceStart, (int32)SliceLen);
|
||||
|
||||
if (Value)
|
||||
{
|
||||
FScriptArrayHelper ValueScriptArrayHelper(Value->ArrayProp, Value->ArrayInstance);
|
||||
const int32 ValueElementCount = ValueScriptArrayHelper.Num();
|
||||
|
||||
SelfScriptArrayHelper.InsertValues((int32)InSliceStart, ValueElementCount);
|
||||
SelfScriptArrayHelper.InsertValues((int32)ResolvedSliceStart, ValueElementCount);
|
||||
for (int32 ElementIndex = 0; ElementIndex < ValueElementCount; ++ElementIndex)
|
||||
{
|
||||
InSelf->ArrayProp->Inner->CopyCompleteValue(SelfScriptArrayHelper.GetRawPtr(InSliceStart + ElementIndex), ValueScriptArrayHelper.GetRawPtr(ElementIndex));
|
||||
InSelf->ArrayProp->Inner->CopyCompleteValue(SelfScriptArrayHelper.GetRawPtr(ResolvedSliceStart + ElementIndex), ValueScriptArrayHelper.GetRawPtr(ElementIndex));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -11,17 +11,53 @@
|
||||
/** Python type for FPyWrapperEnum */
|
||||
extern PyTypeObject PyWrapperEnumType;
|
||||
|
||||
/** Python type for FPyWrapperEnumValueDescrObject */
|
||||
extern PyTypeObject PyWrapperEnumValueDescrType;
|
||||
|
||||
/** Initialize the PyWrapperEnum types and add them to the given Python module */
|
||||
void InitializePyWrapperEnum(PyGenUtil::FNativePythonModule& ModuleInfo);
|
||||
|
||||
/** Type for all UE4 exposed enum instances */
|
||||
/** Type for all UE4 exposed enum instances (an instance is created for each entry in the enum, before the enum type is locked for creating new instances) */
|
||||
struct FPyWrapperEnum : public FPyWrapperBase
|
||||
{
|
||||
/** Name of this enum entry */
|
||||
PyObject* EntryName;
|
||||
|
||||
/** Value of this enum entry */
|
||||
PyObject* EntryValue;
|
||||
|
||||
/** New this wrapper instance (called via tp_new for Python, or directly in C++) */
|
||||
static FPyWrapperEnum* New(PyTypeObject* InType);
|
||||
|
||||
/** Free this wrapper instance (called via tp_dealloc for Python) */
|
||||
static void Free(FPyWrapperEnum* InSelf);
|
||||
|
||||
/** Initialize this wrapper instance (called via tp_init for Python, or directly in C++) */
|
||||
static int Init(FPyWrapperEnum* InSelf);
|
||||
|
||||
/** Set the given enum entry value on the given enum type */
|
||||
static void SetEnumEntryValue(PyTypeObject* InType, const int64 InEnumValue, const char* InEnumValueName, const char* InEnumValueDoc);
|
||||
/** Initialize this wrapper instance (called directly in C++) */
|
||||
static int Init(FPyWrapperEnum* InSelf, const int64 InEnumEntryValue, const char* InEnumEntryName);
|
||||
|
||||
/** Deinitialize this wrapper instance (called via Init and Free to restore the instance to its New state) */
|
||||
static void Deinit(FPyWrapperEnum* InSelf);
|
||||
|
||||
/** Called to validate the internal state of this wrapper instance prior to operating on it (should be called by all functions that expect to operate on an initialized type; will set an error state on failure) */
|
||||
static bool ValidateInternalState(FPyWrapperEnum* InSelf);
|
||||
|
||||
/** Cast the given Python object to this wrapped type (returns a new reference) */
|
||||
static FPyWrapperEnum* CastPyObject(PyObject* InPyObject, FPyConversionResult* OutCastResult = nullptr);
|
||||
|
||||
/** Cast the given Python object to this wrapped type, or attempt to convert the type into a new wrapped instance (returns a new reference) */
|
||||
static FPyWrapperEnum* CastPyObject(PyObject* InPyObject, PyTypeObject* InType, FPyConversionResult* OutCastResult = nullptr);
|
||||
|
||||
/** Get the name of the enum entry as a string */
|
||||
static FString GetEnumEntryName(FPyWrapperEnum* InSelf);
|
||||
|
||||
/** Get the value of the enum entry as an int */
|
||||
static int64 GetEnumEntryValue(FPyWrapperEnum* InSelf);
|
||||
|
||||
/** Add the given enum entry on the given enum type (returns borrowed reference) */
|
||||
static FPyWrapperEnum* AddEnumEntry(PyTypeObject* InType, const int64 InEnumEntryValue, const char* InEnumEntryName, const char* InEnumEntryDoc);
|
||||
};
|
||||
|
||||
/** Meta-data for all UE4 exposed enum types */
|
||||
@@ -34,14 +70,32 @@ struct FPyWrapperEnumMetaData : public FPyWrapperBaseMetaData
|
||||
/** Get the UEnum from the given type */
|
||||
static UEnum* GetEnum(PyTypeObject* PyType);
|
||||
|
||||
/** Get the UEnum from the type of the given instance */
|
||||
static UEnum* GetEnum(FPyWrapperEnum* Instance);
|
||||
|
||||
/** Check to see if the enum is deprecated, and optionally return its deprecation message */
|
||||
static bool IsEnumDeprecated(PyTypeObject* PyType, FString* OutDeprecationMessage = nullptr);
|
||||
|
||||
/** Check to see if the enum is deprecated, and optionally return its deprecation message */
|
||||
static bool IsEnumDeprecated(FPyWrapperEnum* Instance, FString* OutDeprecationMessage = nullptr);
|
||||
|
||||
/** Check to see if the enum is finalized */
|
||||
static bool IsEnumFinalized(PyTypeObject* PyType);
|
||||
|
||||
/** Check to see if the enum is finalized */
|
||||
static bool IsEnumFinalized(FPyWrapperEnum* Instance);
|
||||
|
||||
/** Unreal enum */
|
||||
UEnum* Enum;
|
||||
|
||||
/** True if this enum type has been finalized after having all of its entries added to it */
|
||||
bool bFinalized;
|
||||
|
||||
/** Set if this struct is deprecated and using it should emit a deprecation warning */
|
||||
TOptional<FString> DeprecationMessage;
|
||||
|
||||
/** Array of enum entries in the order they were added (enum entries are stored as borrowed references) */
|
||||
TArray<FPyWrapperEnum*> EnumEntries;
|
||||
};
|
||||
|
||||
typedef TPyPtr<FPyWrapperEnum> FPyWrapperEnumPtr;
|
||||
|
||||
@@ -386,15 +386,16 @@ PyObject* FPyWrapperFixedArray::GetItem(FPyWrapperFixedArray* InSelf, Py_ssize_t
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (PyUtil::ValidateContainerIndexParam(InIndex, InSelf->ArrayProp->ArrayDim, InSelf->ArrayProp, *PyUtil::GetErrorContext(InSelf)) != 0)
|
||||
const Py_ssize_t ResolvedIndex = PyUtil::ResolveContainerIndexParam(InIndex, InSelf->ArrayProp->ArrayDim);
|
||||
if (PyUtil::ValidateContainerIndexParam(ResolvedIndex, InSelf->ArrayProp->ArrayDim, InSelf->ArrayProp, *PyUtil::GetErrorContext(InSelf)) != 0)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
PyObject* PyItemObj = nullptr;
|
||||
if (!PyConversion::PythonizeProperty_Direct(InSelf->ArrayProp, GetItemPtr(InSelf, InIndex), PyItemObj))
|
||||
if (!PyConversion::PythonizeProperty_Direct(InSelf->ArrayProp, GetItemPtr(InSelf, ResolvedIndex), PyItemObj))
|
||||
{
|
||||
PyUtil::SetPythonError(PyExc_TypeError, InSelf, *FString::Printf(TEXT("Failed to convert property '%s' (%s) at index %d"), *InSelf->ArrayProp->GetName(), *InSelf->ArrayProp->GetClass()->GetName(), InIndex));
|
||||
PyUtil::SetPythonError(PyExc_TypeError, InSelf, *FString::Printf(TEXT("Failed to convert property '%s' (%s) at index %d"), *InSelf->ArrayProp->GetName(), *InSelf->ArrayProp->GetClass()->GetName(), ResolvedIndex));
|
||||
return nullptr;
|
||||
}
|
||||
return PyItemObj;
|
||||
@@ -407,15 +408,16 @@ int FPyWrapperFixedArray::SetItem(FPyWrapperFixedArray* InSelf, Py_ssize_t InInd
|
||||
return -1;
|
||||
}
|
||||
|
||||
const int ValidateIndexResult = PyUtil::ValidateContainerIndexParam(InIndex, InSelf->ArrayProp->ArrayDim, InSelf->ArrayProp, *PyUtil::GetErrorContext(InSelf));
|
||||
const Py_ssize_t ResolvedIndex = PyUtil::ResolveContainerIndexParam(InIndex, InSelf->ArrayProp->ArrayDim);
|
||||
const int ValidateIndexResult = PyUtil::ValidateContainerIndexParam(ResolvedIndex, InSelf->ArrayProp->ArrayDim, InSelf->ArrayProp, *PyUtil::GetErrorContext(InSelf));
|
||||
if (ValidateIndexResult != 0)
|
||||
{
|
||||
return ValidateIndexResult;
|
||||
}
|
||||
|
||||
if (!PyConversion::NativizeProperty_Direct(InValue, InSelf->ArrayProp, GetItemPtr(InSelf, InIndex)))
|
||||
if (!PyConversion::NativizeProperty_Direct(InValue, InSelf->ArrayProp, GetItemPtr(InSelf, ResolvedIndex)))
|
||||
{
|
||||
PyUtil::SetPythonError(PyExc_TypeError, InSelf, *FString::Printf(TEXT("Failed to convert property '%s' (%s) at index %d"), *InSelf->ArrayProp->GetName(), *InSelf->ArrayProp->GetClass()->GetName(), InIndex));
|
||||
PyUtil::SetPythonError(PyExc_TypeError, InSelf, *FString::Printf(TEXT("Failed to convert property '%s' (%s) at index %d"), *InSelf->ArrayProp->GetName(), *InSelf->ArrayProp->GetClass()->GetName(), ResolvedIndex));
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -688,7 +690,9 @@ PyTypeObject InitializePyWrapperFixedArrayType()
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const Py_ssize_t SliceLen = InSliceStop - InSliceStart;
|
||||
const Py_ssize_t ResolvedSliceStart = PyUtil::ResolveContainerIndexParam(InSliceStart, InSelf->ArrayProp->ArrayDim);
|
||||
const Py_ssize_t ResolvedSliceStop = PyUtil::ResolveContainerIndexParam(InSliceStop, InSelf->ArrayProp->ArrayDim);
|
||||
const Py_ssize_t SliceLen = ResolvedSliceStop - ResolvedSliceStart;
|
||||
if (SliceLen <= 0)
|
||||
{
|
||||
PyUtil::SetPythonError(PyExc_Exception, InSelf, TEXT("Slice length must be greater than zero"));
|
||||
@@ -702,9 +706,9 @@ PyTypeObject InitializePyWrapperFixedArrayType()
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
for (Py_ssize_t ArrIndex = InSliceStart; ArrIndex < InSliceStop; ++ArrIndex)
|
||||
for (Py_ssize_t ArrIndex = ResolvedSliceStart; ArrIndex < ResolvedSliceStop; ++ArrIndex)
|
||||
{
|
||||
InSelf->ArrayProp->CopySingleValue(FPyWrapperFixedArray::GetItemPtr(NewArray, ArrIndex - InSliceStart), FPyWrapperFixedArray::GetItemPtr(InSelf, ArrIndex));
|
||||
InSelf->ArrayProp->CopySingleValue(FPyWrapperFixedArray::GetItemPtr(NewArray, ArrIndex - ResolvedSliceStart), FPyWrapperFixedArray::GetItemPtr(InSelf, ArrIndex));
|
||||
}
|
||||
return (PyObject*)NewArray.Release();
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ struct FPyWrapperFixedArray : public FPyWrapperBase
|
||||
/** Cast the given Python object to this wrapped type, or attempt to convert the type into a new wrapped instance (returns a new reference) */
|
||||
static FPyWrapperFixedArray* CastPyObject(PyObject* InPyObject, PyTypeObject* InType, const PyUtil::FPropertyDef& InPropDef, FPyConversionResult* OutCastResult = nullptr);
|
||||
|
||||
/** Get the raw pointer to the element at index N */
|
||||
/** Get the raw pointer to the element at index N (negative indexing not supported) */
|
||||
static void* GetItemPtr(FPyWrapperFixedArray* InSelf, Py_ssize_t InIndex);
|
||||
|
||||
/** Get the length of this container (equivalent to 'len(x)' in Python) */
|
||||
|
||||
@@ -2104,13 +2104,14 @@ void FPyWrapperTypeRegistry::GenerateStubCodeForWrappedTypes() const
|
||||
|
||||
void FPyWrapperTypeRegistry::GenerateStubCodeForWrappedType(PyTypeObject* PyType, const PyGenUtil::FGeneratedWrappedType* GeneratedTypeData, FPyFileWriter& OutPythonScript, FPyOnlineDocsSection* OutOnlineDocsSection)
|
||||
{
|
||||
OutPythonScript.WriteLine(FString::Printf(TEXT("class %s(%s):"), UTF8_TO_TCHAR(PyType->tp_name), UTF8_TO_TCHAR(PyType->tp_base->tp_name)));
|
||||
const FString PyTypeName = UTF8_TO_TCHAR(PyType->tp_name);
|
||||
OutPythonScript.WriteLine(FString::Printf(TEXT("class %s(%s):"), *PyTypeName, UTF8_TO_TCHAR(PyType->tp_base->tp_name)));
|
||||
OutPythonScript.IncreaseIndent();
|
||||
OutPythonScript.WriteDocString(UTF8_TO_TCHAR(PyType->tp_doc));
|
||||
|
||||
if (OutOnlineDocsSection)
|
||||
{
|
||||
OutOnlineDocsSection->AccumulateClass(UTF8_TO_TCHAR(PyType->tp_name));
|
||||
OutOnlineDocsSection->AccumulateClass(*PyTypeName);
|
||||
}
|
||||
|
||||
auto GetFunctionReturnValue = [](const void* InBaseParamsAddr, const TArray<PyGenUtil::FGeneratedWrappedMethodParameter>& InOutputParams) -> FString
|
||||
@@ -2332,13 +2333,8 @@ void FPyWrapperTypeRegistry::GenerateStubCodeForWrappedType(PyTypeObject* PyType
|
||||
|
||||
if (MetaGuid == FPyWrapperObjectMetaData::StaticTypeId())
|
||||
{
|
||||
// Skip the __init__ function on derived object types as the base one is already correct
|
||||
bWriteDefaultInit = false;
|
||||
bHasExportedClassData = true;
|
||||
|
||||
OutPythonScript.WriteLine(TEXT("def __init__(self, outer=None, name=\"None\"):"));
|
||||
OutPythonScript.IncreaseIndent();
|
||||
OutPythonScript.WriteLine(TEXT("pass"));
|
||||
OutPythonScript.DecreaseIndent();
|
||||
}
|
||||
else if (MetaGuid == FPyWrapperStructMetaData::StaticTypeId())
|
||||
{
|
||||
@@ -2394,11 +2390,55 @@ void FPyWrapperTypeRegistry::GenerateStubCodeForWrappedType(PyTypeObject* PyType
|
||||
}
|
||||
else if (MetaGuid == FPyWrapperEnumMetaData::StaticTypeId())
|
||||
{
|
||||
// Enums cannot be instanced, they don't have an __init__ function exposed
|
||||
// Skip the __init__ function on derived enums
|
||||
bWriteDefaultInit = false;
|
||||
}
|
||||
// todo: have correct __init__ signatures for the other intrinsic types?
|
||||
}
|
||||
else if (PyType == &PyWrapperObjectType)
|
||||
{
|
||||
bWriteDefaultInit = false;
|
||||
bHasExportedClassData = true;
|
||||
|
||||
OutPythonScript.WriteLine(TEXT("def __init__(self, outer=None, name=\"None\"):"));
|
||||
OutPythonScript.IncreaseIndent();
|
||||
OutPythonScript.WriteLine(TEXT("pass"));
|
||||
OutPythonScript.DecreaseIndent();
|
||||
}
|
||||
else if (PyType == &PyWrapperEnumType)
|
||||
{
|
||||
// Enums don't really have an __init__ function at runtime, so just give them a default one (with no arguments)
|
||||
bWriteDefaultInit = false;
|
||||
|
||||
OutPythonScript.WriteLine(TEXT("def __init__(self):"));
|
||||
OutPythonScript.IncreaseIndent();
|
||||
OutPythonScript.WriteLine(TEXT("pass"));
|
||||
OutPythonScript.DecreaseIndent();
|
||||
}
|
||||
else if (PyType == &PyWrapperEnumValueDescrType)
|
||||
{
|
||||
bWriteDefaultInit = false;
|
||||
bHasExportedClassData = true;
|
||||
|
||||
// This is a special internal decorator type used to define enum entries, which is why it has __get__ as well as __init__
|
||||
OutPythonScript.WriteLine(TEXT("def __init__(self, enum, name, value):"));
|
||||
OutPythonScript.IncreaseIndent();
|
||||
OutPythonScript.WriteLine(TEXT("self.enum = enum"));
|
||||
OutPythonScript.WriteLine(TEXT("self.name = name"));
|
||||
OutPythonScript.WriteLine(TEXT("self.value = value"));
|
||||
OutPythonScript.DecreaseIndent();
|
||||
|
||||
OutPythonScript.WriteLine(TEXT("def __get__(self, obj, type=None):"));
|
||||
OutPythonScript.IncreaseIndent();
|
||||
OutPythonScript.WriteLine(TEXT("return self"));
|
||||
OutPythonScript.DecreaseIndent();
|
||||
|
||||
// It also needs a __repr__ function for Sphinx to generate docs correctly
|
||||
OutPythonScript.WriteLine(TEXT("def __repr__(self):"));
|
||||
OutPythonScript.IncreaseIndent();
|
||||
OutPythonScript.WriteLine(TEXT("return \"{0}.{1}\".format(self.enum, self.name)"));
|
||||
OutPythonScript.DecreaseIndent();
|
||||
}
|
||||
|
||||
if (bWriteDefaultInit)
|
||||
{
|
||||
@@ -2544,25 +2584,31 @@ void FPyWrapperTypeRegistry::GenerateStubCodeForWrappedType(PyTypeObject* PyType
|
||||
}
|
||||
else if (MetaGuid == FPyWrapperEnumMetaData::StaticTypeId())
|
||||
{
|
||||
// Export enum values
|
||||
// Also see https://www.python.org/dev/peps/pep-0435/
|
||||
|
||||
// Export enum entries
|
||||
const PyGenUtil::FGeneratedWrappedEnumType* EnumType = static_cast<const PyGenUtil::FGeneratedWrappedEnumType*>(GeneratedTypeData);
|
||||
|
||||
bool bFirstEnumMember = true;
|
||||
|
||||
for (const PyGenUtil::FGeneratedWrappedEnumEntry& EnumMember : EnumType->EnumEntries)
|
||||
if (EnumType->EnumEntries.Num() > 0)
|
||||
{
|
||||
bHasExportedClassData = true;
|
||||
// Add extra line break for first enum member
|
||||
OutPythonScript.WriteNewLine();
|
||||
|
||||
if (bFirstEnumMember)
|
||||
for (const PyGenUtil::FGeneratedWrappedEnumEntry& EnumMember : EnumType->EnumEntries)
|
||||
{
|
||||
// Add extra line break for first enum member
|
||||
OutPythonScript.WriteNewLine();
|
||||
bFirstEnumMember = false;
|
||||
}
|
||||
const FString EntryName = UTF8_TO_TCHAR(EnumMember.EntryName.GetData());
|
||||
const FString EntryValue = LexToString(EnumMember.EntryValue);
|
||||
|
||||
ExportConstantValue(UTF8_TO_TCHAR(EnumMember.EntryName.GetData()), UTF8_TO_TCHAR(EnumMember.EntryDoc.GetData()), *LexToString(EnumMember.EntryValue));
|
||||
FString EntryDoc = UTF8_TO_TCHAR(EnumMember.EntryDoc.GetData());
|
||||
if (EntryDoc.IsEmpty())
|
||||
{
|
||||
EntryDoc = EntryValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
EntryDoc.InsertAt(0, *FString::Printf(TEXT("%s: "), *EntryValue));
|
||||
}
|
||||
|
||||
ExportConstantValue(*EntryName, *EntryDoc, *FString::Printf(TEXT("_EnumEntry(\"%s\", \"%s\", %s)"), *PyTypeName, *EntryName, *EntryValue));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user