You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
Copying //UE4/Dev-Enterprise to //UE4/Dev-Main (Source: //UE4/Dev-Enterprise @ 3797699)
#lockdown Nick.Penwarden
#rb JeanMichel.Dignard
============================
MAJOR FEATURES & CHANGES
============================
Change 3770717 by Simon.Tourangeau
Fix Blank Enterprise template project creation
Change 3773186 by Simon.Tourangeau
Fix asset migration to correctly handle the migration of content from Content Plugins
Change 3773230 by JeanLuc.Corenthin
Adding new material asset for CAD importer
Removing old material assets for CAD importer
Change 3774391 by JeanMichel.Dignard
Added support for IES asymmetrical light profile
- IES textures are now 2D (256*256) and the shader will use the light tangent to sample the texture.
- Point light tangent is now the Z axis to match the spot lights. Tube shaped point lights will be automatically rotated to compensate for this change. Dynamically generated point lights with a source length will need to have a 90 degrees pitch added to their orientation.
#jira UEENT-55
Change 3775668 by JeanMichel.Dignard
Fixed linux and mac editor builds. Use FVector::DotProduct instead of Dot3 since we're using FVectors.
Change 3781147 by Jamie.Dale
[Python] Prevent the Xcode version of Python being used by default
Change 3781991 by JeanMichel.Dignard
Send the IES texture profile to lightmass in a separate TArray to fix warning 6262 about using too much stack during static analysis.
Change 3783479 by Simon.Tourangeau
Fix NewProjectWizard crash if starter content was enabled
#jira UEENT-635
Change 3784279 by Jamie.Dale
[Python] Added ScopedEditorTransaction and an editor specific module
Change 3787566 by JeanLuc.Corenthin
Fixed issue with display of units which were not reflecting the project settings when enbling unit display.
Got Jamie Dale to help me find the correct solution to this problem: a lambda function.
Thanks, Jamie!
Change 3788178 by Martin.Sevigny
Make sure that FLightPropagationVolume is properly initialized before using it. Can currently trigger a check in FProjectedShadowInfo::SetupWholeSceneProjection because of an uninitialized BoundingBox if LPVIntensity is saved at 0.
Solves: https://udn.unrealengine.com/questions/354040/switching-gi-lpvs-at-runtime.html
Change 3788301 by JeanLuc.Corenthin
On behalf of Anousack:
UE assets necessary to properly handle Cropped procedural textures.
#jira UEENT-522
Change 3789146 by Martin.Sevigny
Bringing back the LPVIntensity test as per MarcusW review.
Change 3789467 by Patrick.Boutot
Add Analytics to PythonScriptPlugin.
Change 3789473 by Patrick.Boutot
Add a slow task dialog when executing a Python script.
Change 3790809 by Patrick.Boutot
Add GIsRunningUnattendedScript. If true, we are running an editor script that should not prompt any dialog modal. The default value of any model will be used. This is used when running a Blutility or script like Python and we don't want an OK dialog to pop while the script is running. Could be set for commandlet with -RUNNINGUNATTENDEDSCRIPT
Change 3790970 by Patrick.Boutot
Add SavePackages with Dialog version in EditorLoadingAndSavingUtils. Refactor some internal save & checkout function in FileHelpers to prevent dialogs from showing when it was not requested.
Change 3790976 by Patrick.Boutot
Add RenameAssetsWithDialog to AssetTools. All previous implementation now use the WithDialog version.
Allow DeleteObject & DuplicatedAsset to be completed without dialog.
Change 3791597 by Simon.Tourangeau
Fix custom window positions in "windowed mode"
#jira UE-52873
Change 3791633 by Patrick.Boutot
Expose to Blueprint the actor' label and folder path.
Change 3791634 by Patrick.Boutot
Change size of the OutputLog's SuggestionList box.
Change 3791637 by Patrick.Boutot
Make sure the suggestions panel is closed before executing the command. Some command wants to run dialog and the suggestions panel may prevent it from opening.
Change 3791661 by Jamie.Dale
[Python] Fixed a bug where we could return an object of the incorrect type from the cache
This could happen if the same instance pointer actually represented two different things, such as when a struct had a different struct as its first member as both of those have the same address, but reflect two different things.
We now treat the type as significant in the cache, and only return something if it matches both the instance and the type.
#jira UEENT-651
Change 3794968 by Patrick.Boutot
Extend File menu to include Python menu. Save the last 10 scripts executed in the user config.
Change 3795084 by Jamie.Dale
[Python] Added a way to purge all references to a given UObject (or set of UObjects) from any living Python objects
Change 3795324 by Jamie.Dale
[Python] Ensure that Python objects referencing the current world/level are purged when the active world/level is changed
This is needed to avoid a fatal assert about a GC leak
#jira UEENT-658
Change 3796248 by Jamie.Dale
FilterAssetDataWithNoTags no longer implicitly removes localized assets
Change 3773185 by Simon.Tourangeau
Move DatasmithImporter plugin content to a content-only plugin under Engine/Plugins/Enterprise/DatasmithContent
This makes it possible to load content created with the DatasmithImporter without having access to Enterprise plugins.
#jira UEENT-544
Change 3790982 by Patrick.Boutot
Set GIsRunningUnattendedScript to EditorScriptUtilities callable functions.
Load level without a prompt.
Change 3791539 by Jamie.Dale
[Python] Added ScriptName and ScriptNoExport meta-data to allow control over how things are exposed to scripts
ScriptName can be used to override the basic name we use when converting classes, structs, enums, properties, and functions to their Python names. It has been used here to remove all the K2_ and BP_ prefixes, and to remove Kismet and Blueprint from some library names.
ScriptNoExport can be used to prevent a property or function from exporting to Python. It has been used here to prevent exporting some deprecated functions that had names that would conflict if we stripped off the K2_ prefix of some newer functions (there were only a handful of these cases).
Change 3773163 by Patrick.Boutot
Improve ConvertActors implementation. Check if the StaticMesh path is valid and do not use dialog in the case we are converting a Brush to a StaticMesh.
Change 3776401 by Patrick.Boutot
Add function to spawn and destroy an actor in editor mode. Spawn use the Place functionality of the editor, you can spawn from an asset, class, archetype or factory.
Change 3778137 by Patrick.Boutot
Add 2 functions to EditorAssetLibrary. GetPathNameForLoadedAsset, wrapper for UObject.GetPathName(). FindPackageReferencersForAsset similar to AssetRegistry.FindPackageReferencer. It will load the assets and all the referencers to confirm the reference.
EditorAssetLibrary now support full path.
Change 3778139 by Patrick.Boutot
Update example data for EditorScriptingUtilities.
Change 3778768 by Patrick.Boutot
Update EditorScriptingUtilities py file with the new naming convention.
Change 3779291 by Patrick.Boutot
Remove const& on TSubLassOf because Blueprint do not show the Pick tool with it.
Update py script & blueprint to point to the new paths.
Change 3783246 by Patrick.Boutot
After review. Tech art prefer to have a filter that check the class and not have the class pass as argument for GetAllLevelActor.
Fix return type in Blueprint for SpawnActorFromClass.
Change 3789367 by Patrick.Boutot
Gets all TagValues associated with an asset as strings value.
Change 3789438 by Patrick.Boutot
Split EditorLevelLibrary into EditorFilterLibrary. All filter function are now in their own modules.
Change 3789489 by Patrick.Boutot
Update script examples with copyright and with the split from EditorFilterLibrary.
Change 3790980 by Patrick.Boutot
Prevent all dialog modal from showing up when running a Python script via command line.
Change 3790984 by Patrick.Boutot
Fix typo in content_browser.py. Delete asset with the loaded version. Fix double values initialized by float.
[CL 3797855 by Simon Tourangeau in Main branch]
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreTypes.h"
|
||||
|
||||
#if WITH_PYTHON
|
||||
|
||||
THIRD_PARTY_INCLUDES_START
|
||||
#include "Python.h"
|
||||
#include "structmember.h"
|
||||
THIRD_PARTY_INCLUDES_END
|
||||
|
||||
#endif // WITH_PYTHON
|
||||
@@ -0,0 +1,146 @@
|
||||
// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#include "PyConstant.h"
|
||||
#include "PyUtil.h"
|
||||
#include "PyPtr.h"
|
||||
|
||||
#if WITH_PYTHON
|
||||
|
||||
void InitializePyConstant()
|
||||
{
|
||||
PyType_Ready(&PyConstantDescrType);
|
||||
}
|
||||
|
||||
bool FPyConstantDef::AddConstantsToType(FPyConstantDef* InConstants, PyTypeObject* InType)
|
||||
{
|
||||
return AddConstantsToDict(InConstants, InType->tp_dict);
|
||||
}
|
||||
|
||||
bool FPyConstantDef::AddConstantsToModule(FPyConstantDef* InConstants, PyObject* InModule)
|
||||
{
|
||||
if (!PyModule_Check(InModule))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
PyObject* ModuleDict = PyModule_GetDict(InModule);
|
||||
return AddConstantsToDict(InConstants, ModuleDict);
|
||||
}
|
||||
|
||||
bool FPyConstantDef::AddConstantsToDict(FPyConstantDef* InConstants, PyObject* InDict)
|
||||
{
|
||||
if (!PyDict_Check(InDict))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (FPyConstantDef* ConstantDef = InConstants; ConstantDef->ConstantName; ++ConstantDef)
|
||||
{
|
||||
FPyObjectPtr PyConstantDescr = FPyObjectPtr::StealReference((PyObject*)FPyConstantDescrObject::New(ConstantDef));
|
||||
if (!PyConstantDescr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (PyDict_SetItemString(InDict, ConstantDef->ConstantName, PyConstantDescr) != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
FPyConstantDescrObject* FPyConstantDescrObject::New(const FPyConstantDef* InConstantDef)
|
||||
{
|
||||
FPyConstantDescrObject* Self = (FPyConstantDescrObject*)PyConstantDescrType.tp_alloc(&PyConstantDescrType, 0);
|
||||
if (Self)
|
||||
{
|
||||
Self->ConstantName = PyUnicode_FromString(InConstantDef->ConstantName);
|
||||
Self->ConstantDef = InConstantDef;
|
||||
}
|
||||
return Self;
|
||||
}
|
||||
|
||||
void FPyConstantDescrObject::Free(FPyConstantDescrObject* InSelf)
|
||||
{
|
||||
Py_XDECREF(InSelf->ConstantName);
|
||||
InSelf->ConstantName = nullptr;
|
||||
|
||||
InSelf->ConstantDef = nullptr;
|
||||
|
||||
Py_TYPE(InSelf)->tp_free((PyObject*)InSelf);
|
||||
}
|
||||
|
||||
PyTypeObject InitializePyConstantDescrType()
|
||||
{
|
||||
struct FFuncs
|
||||
{
|
||||
static void Dealloc(FPyConstantDescrObject* InSelf)
|
||||
{
|
||||
FPyConstantDescrObject::Free(InSelf);
|
||||
}
|
||||
|
||||
static PyObject* Str(FPyConstantDescrObject* InSelf)
|
||||
{
|
||||
return PyUnicode_FromString("<built-in constant value>");
|
||||
}
|
||||
|
||||
static PyObject* DescrGet(FPyConstantDescrObject* InSelf, PyObject* InObj, PyObject* InType)
|
||||
{
|
||||
return InSelf->ConstantDef->ConstantGetter(InSelf->ConstantDef->ConstantPtr);
|
||||
}
|
||||
|
||||
static int DescrSet(FPyConstantDescrObject* InSelf, PyObject* InObj, PyObject* InValue)
|
||||
{
|
||||
PyErr_SetString(PyExc_Exception, "Constant values are read-only");
|
||||
return -1;
|
||||
}
|
||||
};
|
||||
|
||||
struct FGetSets
|
||||
{
|
||||
static PyObject* GetDoc(FPyConstantDescrObject* InSelf, void* InClosure)
|
||||
{
|
||||
if (InSelf->ConstantDef->ConstantDoc)
|
||||
{
|
||||
return PyUnicode_FromString(InSelf->ConstantDef->ConstantDoc);
|
||||
}
|
||||
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
};
|
||||
|
||||
static PyMemberDef PyMembers[] = {
|
||||
{ PyCStrCast("__name__"), T_OBJECT, STRUCT_OFFSET(FPyConstantDescrObject, ConstantName), READONLY, nullptr },
|
||||
{ nullptr, 0, 0, 0, nullptr }
|
||||
};
|
||||
|
||||
static PyGetSetDef PyGetSets[] = {
|
||||
{ PyCStrCast("__doc__"), (getter)&FGetSets::GetDoc, nullptr, nullptr, nullptr },
|
||||
{ nullptr, nullptr, nullptr, nullptr, nullptr }
|
||||
};
|
||||
|
||||
PyTypeObject PyType = {
|
||||
PyVarObject_HEAD_INIT(nullptr, 0)
|
||||
"constant_value", /* tp_name */
|
||||
sizeof(FPyConstantDescrObject), /* tp_basicsize */
|
||||
};
|
||||
|
||||
PyType.tp_dealloc = (destructor)&FFuncs::Dealloc;
|
||||
PyType.tp_str = (reprfunc)&FFuncs::Str;
|
||||
PyType.tp_descr_get = (descrgetfunc)&FFuncs::DescrGet;
|
||||
PyType.tp_descr_set = (descrsetfunc)&FFuncs::DescrSet;
|
||||
PyType.tp_getattro = (getattrofunc)&PyObject_GenericGetAttr;
|
||||
|
||||
PyType.tp_members = PyMembers;
|
||||
PyType.tp_getset = PyGetSets;
|
||||
|
||||
PyType.tp_flags = Py_TPFLAGS_DEFAULT;
|
||||
|
||||
return PyType;
|
||||
}
|
||||
|
||||
PyTypeObject PyConstantDescrType = InitializePyConstantDescrType();
|
||||
|
||||
#endif // WITH_PYTHON
|
||||
@@ -0,0 +1,70 @@
|
||||
// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IncludePython.h"
|
||||
#include "CoreMinimal.h"
|
||||
|
||||
#if WITH_PYTHON
|
||||
|
||||
/** Python type for FPyConstantDescrObject */
|
||||
extern PyTypeObject PyConstantDescrType;
|
||||
|
||||
/** Initialize the PyConstant types */
|
||||
void InitializePyConstant();
|
||||
|
||||
/** Function pointer used to convert a constant value pointer into a Python object */
|
||||
typedef PyObject*(*PyConstantGetter)(const void*);
|
||||
|
||||
/**
|
||||
* Definition for a constant value
|
||||
* This takes a pointer to some static or otherwise persistent data, along with a function used to convert this pointer into a Python object when needed
|
||||
* Compared to a template, this avoids variance in the Python-type which would require a new Python-type to be registered for each instantiation
|
||||
* Compared to storing a PyObject*, this avoids returning an instance that could be mutated and affect the constant value
|
||||
*/
|
||||
struct FPyConstantDef
|
||||
{
|
||||
/** A pointer to the constant value */
|
||||
const void* ConstantPtr;
|
||||
|
||||
/** Function pointer used to convert a constant value pointer into a Python object */
|
||||
PyConstantGetter ConstantGetter;
|
||||
|
||||
/** The name of the constant value */
|
||||
const char* ConstantName;
|
||||
|
||||
/** The doc string of the constant value (may be null) */
|
||||
const char* ConstantDoc;
|
||||
|
||||
/** Add the given null-terminated table of constants to the given type */
|
||||
static bool AddConstantsToType(FPyConstantDef* InConstants, PyTypeObject* InType);
|
||||
|
||||
/** Add the given null-terminated table of constants to the given type */
|
||||
static bool AddConstantsToModule(FPyConstantDef* InConstants, PyObject* InModule);
|
||||
|
||||
/** Add the given null-terminated table of constants to the given type */
|
||||
static bool AddConstantsToDict(FPyConstantDef* InConstants, PyObject* InDict);
|
||||
};
|
||||
|
||||
/**
|
||||
* Python object for the descriptor of an constant value
|
||||
*/
|
||||
struct FPyConstantDescrObject
|
||||
{
|
||||
/** Common Python Object */
|
||||
PyObject_HEAD
|
||||
|
||||
/** Name of the constant being described */
|
||||
PyObject* ConstantName;
|
||||
|
||||
/** Pointer to the definition of this constant */
|
||||
const FPyConstantDef* ConstantDef;
|
||||
|
||||
/** New an instance */
|
||||
static FPyConstantDescrObject* New(const FPyConstantDef* InConstantDef);
|
||||
|
||||
/** Free this instance */
|
||||
static void Free(FPyConstantDescrObject* InSelf);
|
||||
};
|
||||
|
||||
#endif // WITH_PYTHON
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,204 @@
|
||||
// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IncludePython.h"
|
||||
#include "PyConversionMethod.h"
|
||||
#include "PyWrapperOwnerContext.h"
|
||||
#include "UObject/Class.h"
|
||||
#include "Templates/EnableIf.h"
|
||||
#include "Templates/UnrealTemplate.h"
|
||||
#include "Templates/PointerIsConvertibleFromTo.h"
|
||||
|
||||
#if WITH_PYTHON
|
||||
|
||||
/**
|
||||
* Conversion between native and Python types.
|
||||
* @note These functions may set error state when using ESetErrorState::Yes.
|
||||
*/
|
||||
namespace PyConversion
|
||||
{
|
||||
enum class ESetErrorState : uint8 { No, Yes };
|
||||
|
||||
/** bool overload */
|
||||
bool Nativize(PyObject* PyObj, bool& OutVal, const ESetErrorState SetErrorState = ESetErrorState::Yes);
|
||||
bool Pythonize(const bool Val, PyObject*& OutPyObj, const ESetErrorState SetErrorState = ESetErrorState::Yes);
|
||||
|
||||
/** int8 overload */
|
||||
bool Nativize(PyObject* PyObj, int8& OutVal, const ESetErrorState SetErrorState = ESetErrorState::Yes);
|
||||
bool Pythonize(const int8 Val, PyObject*& OutPyObj, const ESetErrorState SetErrorState = ESetErrorState::Yes);
|
||||
|
||||
/** uint8 overload */
|
||||
bool Nativize(PyObject* PyObj, uint8& OutVal, const ESetErrorState SetErrorState = ESetErrorState::Yes);
|
||||
bool Pythonize(const uint8 Val, PyObject*& OutPyObj, const ESetErrorState SetErrorState = ESetErrorState::Yes);
|
||||
|
||||
/** int16 overload */
|
||||
bool Nativize(PyObject* PyObj, int16& OutVal, const ESetErrorState SetErrorState = ESetErrorState::Yes);
|
||||
bool Pythonize(const int16 Val, PyObject*& OutPyObj, const ESetErrorState SetErrorState = ESetErrorState::Yes);
|
||||
|
||||
/** uint16 overload */
|
||||
bool Nativize(PyObject* PyObj, uint16& OutVal, const ESetErrorState SetErrorState = ESetErrorState::Yes);
|
||||
bool Pythonize(const uint16 Val, PyObject*& OutPyObj, const ESetErrorState SetErrorState = ESetErrorState::Yes);
|
||||
|
||||
/** int32 overload */
|
||||
bool Nativize(PyObject* PyObj, int32& OutVal, const ESetErrorState ErrorState = ESetErrorState::Yes);
|
||||
bool Pythonize(const int32 Val, PyObject*& OutPyObj, const ESetErrorState SetErrorState = ESetErrorState::Yes);
|
||||
|
||||
/** uint32 overload */
|
||||
bool Nativize(PyObject* PyObj, uint32& OutVal, const ESetErrorState SetErrorState = ESetErrorState::Yes);
|
||||
bool Pythonize(const uint32 Val, PyObject*& OutPyObj, const ESetErrorState SetErrorState = ESetErrorState::Yes);
|
||||
|
||||
/** int64 overload */
|
||||
bool Nativize(PyObject* PyObj, int64& OutVal, const ESetErrorState SetErrorState = ESetErrorState::Yes);
|
||||
bool Pythonize(const int64 Val, PyObject*& OutPyObj, const ESetErrorState SetErrorState = ESetErrorState::Yes);
|
||||
|
||||
/** uint64 overload */
|
||||
bool Nativize(PyObject* PyObj, uint64& OutVal, const ESetErrorState SetErrorState = ESetErrorState::Yes);
|
||||
bool Pythonize(const uint64 Val, PyObject*& OutPyObj, const ESetErrorState SetErrorState = ESetErrorState::Yes);
|
||||
|
||||
/** float overload */
|
||||
bool Nativize(PyObject* PyObj, float& OutVal, const ESetErrorState SetErrorState = ESetErrorState::Yes);
|
||||
bool Pythonize(const float Val, PyObject*& OutPyObj, const ESetErrorState SetErrorState = ESetErrorState::Yes);
|
||||
|
||||
/** double overload */
|
||||
bool Nativize(PyObject* PyObj, double& OutVal, const ESetErrorState SetErrorState = ESetErrorState::Yes);
|
||||
bool Pythonize(const double Val, PyObject*& OutPyObj, const ESetErrorState SetErrorState = ESetErrorState::Yes);
|
||||
|
||||
/** FString overload */
|
||||
bool Nativize(PyObject* PyObj, FString& OutVal, const ESetErrorState SetErrorState = ESetErrorState::Yes);
|
||||
bool Pythonize(const FString& Val, PyObject*& OutPyObj, const ESetErrorState SetErrorState = ESetErrorState::Yes);
|
||||
|
||||
/** FName overload */
|
||||
bool Nativize(PyObject* PyObj, FName& OutVal, const ESetErrorState SetErrorState = ESetErrorState::Yes);
|
||||
bool Pythonize(const FName& Val, PyObject*& OutPyObj, const ESetErrorState SetErrorState = ESetErrorState::Yes);
|
||||
|
||||
/** FText overload */
|
||||
bool Nativize(PyObject* PyObj, FText& OutVal, const ESetErrorState SetErrorState = ESetErrorState::Yes);
|
||||
bool Pythonize(const FText& Val, PyObject*& OutPyObj, const ESetErrorState SetErrorState = ESetErrorState::Yes);
|
||||
|
||||
/** UObject overload */
|
||||
bool Nativize(PyObject* PyObj, UObject*& OutVal, const ESetErrorState SetErrorState = ESetErrorState::Yes);
|
||||
bool Pythonize(UObject* Val, PyObject*& OutPyObj, const ESetErrorState SetErrorState = ESetErrorState::Yes);
|
||||
|
||||
/** Conversion for object types, including optional type checking */
|
||||
bool NativizeObject(PyObject* PyObj, UObject*& OutVal, UClass* ExpectedType, const ESetErrorState SetErrorState = ESetErrorState::Yes);
|
||||
bool PythonizeObject(UObject* Val, PyObject*& OutPyObj, const ESetErrorState SetErrorState = ESetErrorState::Yes);
|
||||
PyObject* PythonizeObject(UObject* Val, const ESetErrorState SetErrorState = ESetErrorState::Yes);
|
||||
|
||||
/** Conversion for class types, including optional type checking */
|
||||
bool NativizeClass(PyObject* PyObj, UClass*& OutVal, UClass* ExpectedType, const ESetErrorState SetErrorState = ESetErrorState::Yes);
|
||||
bool PythonizeClass(UClass* Val, PyObject*& OutPyObj, const ESetErrorState SetErrorState = ESetErrorState::Yes);
|
||||
PyObject* PythonizeClass(UClass* Val, const ESetErrorState SetErrorState = ESetErrorState::Yes);
|
||||
|
||||
namespace Internal
|
||||
{
|
||||
/** Internal version of NativizeStruct/PythonizeStruct that work on the type-erased data */
|
||||
bool NativizeStruct(PyObject* PyObj, UScriptStruct* StructType, void* StructInstance, const ESetErrorState SetErrorState);
|
||||
bool PythonizeStruct(UScriptStruct* StructType, const void* StructInstance, PyObject*& OutPyObj, const ESetErrorState SetErrorState);
|
||||
|
||||
/** Dummy catch-all for type conversions that aren't yet implemented */
|
||||
template <typename T, typename Spec = void>
|
||||
struct FTypeConv
|
||||
{
|
||||
static bool Nativize(PyObject* PyObj, T& OutVal, const ESetErrorState SetErrorState)
|
||||
{
|
||||
ensureAlwaysMsgf(false, TEXT("Nativize not implemented for type"));
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool Pythonize(const T& Val, PyObject*& OutPyObj, const ESetErrorState SetErrorState)
|
||||
{
|
||||
ensureAlwaysMsgf(false, TEXT("Pythonize not implemented for type"));
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
/** Override the catch-all for UObject types */
|
||||
template <typename T>
|
||||
struct FTypeConv<T, typename TEnableIf<TPointerIsConvertibleFromTo<typename TRemovePointer<T>::Type, UObject>::Value>::Type>
|
||||
{
|
||||
static bool Nativize(PyObject* PyObj, T& OutVal, const ESetErrorState SetErrorState)
|
||||
{
|
||||
return PyConversion::NativizeObject(PyObj, (UObject*&)OutVal, TRemovePointer<T>::Type::StaticClass(), SetErrorState);
|
||||
}
|
||||
|
||||
static bool Pythonize(const T& Val, PyObject*& OutPyObj, const ESetErrorState SetErrorState)
|
||||
{
|
||||
return PyConversion::PythonizeObject((UObject*)Val, OutPyObj, SetErrorState);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic version of Nativize used if there is no matching overload.
|
||||
* Used to allow conversion from object and struct types that don't match a specific override (see FTypeConv).
|
||||
*/
|
||||
template <typename T>
|
||||
bool Nativize(PyObject* PyObj, T& OutVal, const ESetErrorState SetErrorState = ESetErrorState::Yes)
|
||||
{
|
||||
return Internal::FTypeConv<T>::Nativize(PyObj, OutVal, SetErrorState);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic version of Pythonize used if there is no matching overload.
|
||||
* Used to allow conversion from object and struct types that don't match a specific override (see FTypeConv).
|
||||
*/
|
||||
template <typename T>
|
||||
bool Pythonize(const T& Val, PyObject*& OutPyObj, const ESetErrorState SetErrorState = ESetErrorState::Yes)
|
||||
{
|
||||
return Internal::FTypeConv<T>::Pythonize(Val, OutPyObj, SetErrorState);
|
||||
}
|
||||
|
||||
/** Generic version of Pythonize that returns a PyObject rather than a bool */
|
||||
template <typename T>
|
||||
PyObject* Pythonize(const T& Val, const ESetErrorState SetErrorState = ESetErrorState::Yes)
|
||||
{
|
||||
PyObject* Obj = nullptr;
|
||||
Pythonize(Val, Obj, SetErrorState);
|
||||
return Obj;
|
||||
}
|
||||
|
||||
/** Conversion for known struct types */
|
||||
template <typename T>
|
||||
bool NativizeStruct(PyObject* PyObj, T& OutVal, const ESetErrorState SetErrorState = ESetErrorState::Yes)
|
||||
{
|
||||
return Internal::NativizeStruct(PyObj, TBaseStructure<T>::Get(), &OutVal, SetErrorState);
|
||||
}
|
||||
|
||||
/** Conversion for known struct types */
|
||||
template <typename T>
|
||||
bool PythonizeStruct(const T& Val, PyObject*& OutPyObj, const ESetErrorState SetErrorState = ESetErrorState::Yes)
|
||||
{
|
||||
return Internal::PythonizeStruct(TBaseStructure<T>::Get(), &Val, OutPyObj, SetErrorState);
|
||||
}
|
||||
|
||||
/** Conversion for known struct types that returns a PyObject rather than a bool */
|
||||
template <typename T>
|
||||
PyObject* PythonizeStruct(const T& Val, const ESetErrorState SetErrorState = ESetErrorState::Yes)
|
||||
{
|
||||
PyObject* Obj = nullptr;
|
||||
Internal::PythonizeStruct(TBaseStructure<T>::Get(), &Val, Obj, SetErrorState);
|
||||
return Obj;
|
||||
}
|
||||
|
||||
/** Conversion for property instances (including fixed arrays) - ValueAddr should point to the property data */
|
||||
bool NativizeProperty(PyObject* PyObj, const UProperty* Prop, void* ValueAddr, const FPyWrapperOwnerContext& InChangeOwner = FPyWrapperOwnerContext(), const ESetErrorState SetErrorState = ESetErrorState::Yes);
|
||||
bool PythonizeProperty(const UProperty* Prop, const void* ValueAddr, PyObject*& OutPyObj, const EPyConversionMethod ConversionMethod = EPyConversionMethod::Copy, PyObject* OwnerPyObj = nullptr, const ESetErrorState SetErrorState = ESetErrorState::Yes);
|
||||
|
||||
/** Conversion for single property instances - ValueAddr should point to the property data */
|
||||
bool NativizeProperty_Direct(PyObject* PyObj, const UProperty* Prop, void* ValueAddr, const FPyWrapperOwnerContext& InChangeOwner = FPyWrapperOwnerContext(), const ESetErrorState SetErrorState = ESetErrorState::Yes);
|
||||
bool PythonizeProperty_Direct(const UProperty* Prop, const void* ValueAddr, PyObject*& OutPyObj, const EPyConversionMethod ConversionMethod = EPyConversionMethod::Copy, PyObject* OwnerPyObj = nullptr, const ESetErrorState SetErrorState = ESetErrorState::Yes);
|
||||
|
||||
/** Conversion for property instances within a structure (including fixed arrays) - BaseAddr should point to the structure data */
|
||||
bool NativizeProperty_InContainer(PyObject* PyObj, const UProperty* Prop, void* BaseAddr, const int32 ArrayIndex, const FPyWrapperOwnerContext& InChangeOwner = FPyWrapperOwnerContext(), const ESetErrorState SetErrorState = ESetErrorState::Yes);
|
||||
bool PythonizeProperty_InContainer(const UProperty* Prop, const void* BaseAddr, const int32 ArrayIndex, PyObject*& OutPyObj, const EPyConversionMethod ConversionMethod = EPyConversionMethod::Copy, PyObject* OwnerPyObj = nullptr, const ESetErrorState SetErrorState = ESetErrorState::Yes);
|
||||
|
||||
/**
|
||||
* Helper function used to emit property change notifications as value changes are made
|
||||
* This function should be called when you know the value will actually change (or know you want to emit the notifications for it changing) and will do
|
||||
* the pre-change notify, invoke the passed delegate to perform the change, then do the post-change notify
|
||||
*/
|
||||
void EmitPropertyChangeNotifications(const FPyWrapperOwnerContext& InChangeOwner, const TFunctionRef<void()>& InDoChangeFunc);
|
||||
}
|
||||
|
||||
#endif // WITH_PYTHON
|
||||
@@ -0,0 +1,25 @@
|
||||
// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IncludePython.h"
|
||||
#include "CoreMinimal.h"
|
||||
|
||||
#if WITH_PYTHON
|
||||
|
||||
enum class EPyConversionMethod : uint8
|
||||
{
|
||||
/** Copy the value */
|
||||
Copy,
|
||||
/** Steal the value (or fallback to Copy) */
|
||||
Steal,
|
||||
/** Reference the value from the given owner (or fallback to Copy) */
|
||||
Reference,
|
||||
};
|
||||
|
||||
FORCEINLINE void AssertValidPyConversionOwner(PyObject* InPyOwner, const EPyConversionMethod InMethod)
|
||||
{
|
||||
checkf(InPyOwner || InMethod != EPyConversionMethod::Reference, TEXT("EPyConversionMethod::Reference requires a valid owner object"));
|
||||
}
|
||||
|
||||
#endif // WITH_PYTHON
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,148 @@
|
||||
// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IncludePython.h"
|
||||
#include "PyPtr.h"
|
||||
#include "CoreMinimal.h"
|
||||
#include "EnumClassFlags.h"
|
||||
|
||||
#if WITH_PYTHON
|
||||
|
||||
/** Get the object that Python created transient properties should be outered to */
|
||||
UObject* GetPythonPropertyContainer();
|
||||
|
||||
/** Get the object that Python created types should be outered to */
|
||||
UObject* GetPythonTypeContainer();
|
||||
|
||||
/** Python type for FPyUValueDef */
|
||||
extern PyTypeObject PyUValueDefType;
|
||||
|
||||
/** Python type for FPyUPropertyDef */
|
||||
extern PyTypeObject PyUPropertyDefType;
|
||||
|
||||
/** Python type for FPyUFunctionDef */
|
||||
extern PyTypeObject PyUFunctionDefType;
|
||||
|
||||
/** Type used to define constant values from Python */
|
||||
struct FPyUValueDef
|
||||
{
|
||||
/** Common Python Object */
|
||||
PyObject_HEAD
|
||||
|
||||
/** Value of this definition */
|
||||
PyObject* Value;
|
||||
|
||||
/** Dictionary of meta-data associated with this value */
|
||||
PyObject* MetaData;
|
||||
|
||||
/** New this instance (called via tp_new for Python, or directly in C++) */
|
||||
static FPyUValueDef* New(PyTypeObject* InType);
|
||||
|
||||
/** Free this instance (called via tp_dealloc for Python) */
|
||||
static void Free(FPyUValueDef* InSelf);
|
||||
|
||||
/** Initialize this instance (called via tp_init for Python, or directly in C++) */
|
||||
static int Init(FPyUValueDef* InSelf, PyObject* InValue, PyObject* InMetaData);
|
||||
|
||||
/** Deinitialize this instance (called via Init and Free to restore the instance to its New state) */
|
||||
static void Deinit(FPyUValueDef* InSelf);
|
||||
|
||||
/** Apply the meta-data on this instance via the given predicate */
|
||||
static void ApplyMetaData(FPyUValueDef* InSelf, const TFunctionRef<void(const FString&, const FString&)>& InPredicate);
|
||||
};
|
||||
|
||||
/** Type used to define UProperty fields from Python */
|
||||
struct FPyUPropertyDef
|
||||
{
|
||||
/** Common Python Object */
|
||||
PyObject_HEAD
|
||||
|
||||
/** Type of this property */
|
||||
PyObject* PropType;
|
||||
|
||||
/** Dictionary of meta-data associated with this property */
|
||||
PyObject* MetaData;
|
||||
|
||||
/** Getter function to use with this property */
|
||||
FString GetterFuncName;
|
||||
|
||||
/** Setter function to use with this property */
|
||||
FString SetterFuncName;
|
||||
|
||||
/** New this instance (called via tp_new for Python, or directly in C++) */
|
||||
static FPyUPropertyDef* New(PyTypeObject* InType);
|
||||
|
||||
/** Free this instance (called via tp_dealloc for Python) */
|
||||
static void Free(FPyUPropertyDef* InSelf);
|
||||
|
||||
/** Initialize this instance (called via tp_init for Python, or directly in C++) */
|
||||
static int Init(FPyUPropertyDef* InSelf, PyObject* InPropType, PyObject* InMetaData, FString InGetterFuncName, FString InSetterFuncName);
|
||||
|
||||
/** Deinitialize this instance (called via Init and Free to restore the instance to its New state) */
|
||||
static void Deinit(FPyUPropertyDef* InSelf);
|
||||
|
||||
/** Apply the meta-data on this instance to the given property */
|
||||
static void ApplyMetaData(FPyUPropertyDef* InSelf, UProperty* InProp);
|
||||
};
|
||||
|
||||
/** Flags used to define the attributes of a UFunction field from Python */
|
||||
enum class EPyUFunctionDefFlags : uint8
|
||||
{
|
||||
None = 0,
|
||||
Override = 1<<0,
|
||||
Static = 1<<1,
|
||||
Pure = 1<<2,
|
||||
Impure = 1<<3,
|
||||
Getter = 1<<4,
|
||||
Setter = 1<<5,
|
||||
};
|
||||
ENUM_CLASS_FLAGS(EPyUFunctionDefFlags);
|
||||
|
||||
/** Type used to define UFunction fields from Python */
|
||||
struct FPyUFunctionDef
|
||||
{
|
||||
/** Common Python Object */
|
||||
PyObject_HEAD
|
||||
|
||||
/** Python function to call */
|
||||
PyObject* Func;
|
||||
|
||||
/** Return type of this function */
|
||||
PyObject* FuncRetType;
|
||||
|
||||
/** List of types for each parameter of this function */
|
||||
PyObject* FuncParamTypes;
|
||||
|
||||
/** Dictionary of meta-data associated with this function */
|
||||
PyObject* MetaData;
|
||||
|
||||
/** Flags used to define this function */
|
||||
EPyUFunctionDefFlags FuncFlags;
|
||||
|
||||
/** New this instance (called via tp_new for Python, or directly in C++) */
|
||||
static FPyUFunctionDef* New(PyTypeObject* InType);
|
||||
|
||||
/** Free this instance (called via tp_dealloc for Python) */
|
||||
static void Free(FPyUFunctionDef* InSelf);
|
||||
|
||||
/** Initialize this instance (called via tp_init for Python, or directly in C++) */
|
||||
static int Init(FPyUFunctionDef* InSelf, PyObject* InFunc, PyObject* InFuncRetType, PyObject* InFuncParamTypes, PyObject* InMetaData, EPyUFunctionDefFlags InFuncFlags);
|
||||
|
||||
/** Deinitialize this instance (called via Init and Free to restore the instance to its New state) */
|
||||
static void Deinit(FPyUFunctionDef* InSelf);
|
||||
|
||||
/** Apply the meta-data on this instance to the given function */
|
||||
static void ApplyMetaData(FPyUFunctionDef* InSelf, UFunction* InFunc);
|
||||
};
|
||||
|
||||
typedef TPyPtr<FPyUValueDef> FPyUValueDefPtr;
|
||||
typedef TPyPtr<FPyUPropertyDef> FPyUPropertyDefPtr;
|
||||
typedef TPyPtr<FPyUFunctionDef> FPyUFunctionDefPtr;
|
||||
|
||||
namespace PyCore
|
||||
{
|
||||
void InitializeModule();
|
||||
}
|
||||
|
||||
#endif // WITH_PYTHON
|
||||
@@ -0,0 +1,172 @@
|
||||
// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#include "PyEditor.h"
|
||||
#include "PyUtil.h"
|
||||
#include "PyConversion.h"
|
||||
|
||||
#if WITH_EDITOR
|
||||
#include "Editor.h"
|
||||
#endif // WITH_EDITOR
|
||||
|
||||
#if WITH_PYTHON
|
||||
|
||||
#if WITH_EDITOR
|
||||
|
||||
FPyScopedEditorTransaction* FPyScopedEditorTransaction::New(PyTypeObject* InType)
|
||||
{
|
||||
FPyScopedEditorTransaction* Self = (FPyScopedEditorTransaction*)InType->tp_alloc(InType, 0);
|
||||
if (Self)
|
||||
{
|
||||
new(&Self->Description) FText();
|
||||
Self->PendingTransactionId = INDEX_NONE;
|
||||
}
|
||||
return Self;
|
||||
}
|
||||
|
||||
void FPyScopedEditorTransaction::Free(FPyScopedEditorTransaction* InSelf)
|
||||
{
|
||||
Deinit(InSelf);
|
||||
|
||||
InSelf->Description.~FText();
|
||||
Py_TYPE(InSelf)->tp_free((PyObject*)InSelf);
|
||||
}
|
||||
|
||||
int FPyScopedEditorTransaction::Init(FPyScopedEditorTransaction* InSelf, const FText& InDescription)
|
||||
{
|
||||
Deinit(InSelf);
|
||||
|
||||
InSelf->Description = InDescription;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void FPyScopedEditorTransaction::Deinit(FPyScopedEditorTransaction* InSelf)
|
||||
{
|
||||
InSelf->Description = FText();
|
||||
InSelf->PendingTransactionId = INDEX_NONE;
|
||||
}
|
||||
|
||||
PyTypeObject InitializePyScopedEditorTransactionType()
|
||||
{
|
||||
struct FFuncs
|
||||
{
|
||||
static PyObject* New(PyTypeObject* InType, PyObject* InArgs, PyObject* InKwds)
|
||||
{
|
||||
return (PyObject*)FPyScopedEditorTransaction::New(InType);
|
||||
}
|
||||
|
||||
static void Dealloc(FPyScopedEditorTransaction* InSelf)
|
||||
{
|
||||
FPyScopedEditorTransaction::Free(InSelf);
|
||||
}
|
||||
|
||||
static int Init(FPyScopedEditorTransaction* InSelf, PyObject* InArgs, PyObject* InKwds)
|
||||
{
|
||||
PyObject* PyDescObj = nullptr;
|
||||
|
||||
static const char *ArgsKwdList[] = { "desc", nullptr };
|
||||
if (!PyArg_ParseTupleAndKeywords(InArgs, InKwds, "O:call", (char**)ArgsKwdList, &PyDescObj))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
FText Desc;
|
||||
if (!PyConversion::Nativize(PyDescObj, Desc))
|
||||
{
|
||||
PyUtil::SetPythonError(PyExc_TypeError, InSelf, *FString::Printf(TEXT("Failed to convert 'desc' (%s) to 'Text'"), *PyUtil::GetFriendlyTypename(PyDescObj)));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return FPyScopedEditorTransaction::Init(InSelf, Desc);
|
||||
}
|
||||
};
|
||||
|
||||
struct FMethods
|
||||
{
|
||||
static PyObject* EnterScope(FPyScopedEditorTransaction* InSelf)
|
||||
{
|
||||
ensure(InSelf->PendingTransactionId == INDEX_NONE);
|
||||
InSelf->PendingTransactionId = GEditor->BeginTransaction(InSelf->Description);
|
||||
|
||||
Py_INCREF(InSelf);
|
||||
return (PyObject*)InSelf;
|
||||
}
|
||||
|
||||
static PyObject* ExitScope(FPyScopedEditorTransaction* InSelf, PyObject* InArgs, PyObject* InKwds)
|
||||
{
|
||||
if (InSelf->PendingTransactionId != INDEX_NONE)
|
||||
{
|
||||
GEditor->EndTransaction();
|
||||
InSelf->PendingTransactionId = INDEX_NONE;
|
||||
}
|
||||
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
static PyObject* Cancel(FPyScopedEditorTransaction* InSelf)
|
||||
{
|
||||
if (InSelf->PendingTransactionId != INDEX_NONE)
|
||||
{
|
||||
GEditor->CancelTransaction(InSelf->PendingTransactionId);
|
||||
InSelf->PendingTransactionId = INDEX_NONE;
|
||||
}
|
||||
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
};
|
||||
|
||||
static PyMethodDef PyMethods[] = {
|
||||
{ "__enter__", PyCFunctionCast(&FMethods::EnterScope), METH_NOARGS, "x.__enter__() -> self -- begin this transaction" },
|
||||
{ "__exit__", PyCFunctionCast(&FMethods::ExitScope), METH_VARARGS | METH_KEYWORDS, "x.__exit__(type, value, traceback) -- end this transaction" },
|
||||
{ "cancel", PyCFunctionCast(&FMethods::Cancel), METH_NOARGS, "x.cancel() -- cancel this transaction" },
|
||||
{ nullptr, nullptr, 0, nullptr }
|
||||
};
|
||||
|
||||
PyTypeObject PyType = {
|
||||
PyVarObject_HEAD_INIT(nullptr, 0)
|
||||
"ScopedEditorTransaction", /* tp_name */
|
||||
sizeof(FPyScopedEditorTransaction), /* tp_basicsize */
|
||||
};
|
||||
|
||||
PyType.tp_new = (newfunc)&FFuncs::New;
|
||||
PyType.tp_dealloc = (destructor)&FFuncs::Dealloc;
|
||||
PyType.tp_init = (initproc)&FFuncs::Init;
|
||||
|
||||
PyType.tp_methods = PyMethods;
|
||||
|
||||
PyType.tp_flags = Py_TPFLAGS_DEFAULT;
|
||||
PyType.tp_doc = "Type used to create and managed a scoped editor transaction in Python";
|
||||
|
||||
return PyType;
|
||||
}
|
||||
|
||||
PyTypeObject PyScopedEditorTransactionType = InitializePyScopedEditorTransactionType();
|
||||
|
||||
namespace PyEditor
|
||||
{
|
||||
|
||||
PyMethodDef PyEditorMethods[] = {
|
||||
{ nullptr, nullptr, 0, nullptr }
|
||||
};
|
||||
|
||||
void InitializeModule()
|
||||
{
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
PyObject* PyModule = PyImport_AddModule("_unreal_editor");
|
||||
PyModule_AddFunctions(PyModule, PyEditorMethods);
|
||||
#else // PY_MAJOR_VERSION >= 3
|
||||
PyObject* PyModule = Py_InitModule("_unreal_editor", PyEditorMethods);
|
||||
#endif // PY_MAJOR_VERSION >= 3
|
||||
|
||||
if (PyType_Ready(&PyScopedEditorTransactionType) == 0)
|
||||
{
|
||||
Py_INCREF(&PyScopedEditorTransactionType);
|
||||
PyModule_AddObject(PyModule, PyScopedEditorTransactionType.tp_name, (PyObject*)&PyScopedEditorTransactionType);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // WITH_EDITOR
|
||||
|
||||
#endif // WITH_PYTHON
|
||||
@@ -0,0 +1,50 @@
|
||||
// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IncludePython.h"
|
||||
#include "PyPtr.h"
|
||||
#include "CoreMinimal.h"
|
||||
|
||||
#if WITH_PYTHON
|
||||
|
||||
#if WITH_EDITOR
|
||||
|
||||
/** Python type for FPyScopedEditorTransaction */
|
||||
extern PyTypeObject PyScopedEditorTransactionType;
|
||||
|
||||
/** Type used to create and managed a scoped editor transaction in Python */
|
||||
struct FPyScopedEditorTransaction
|
||||
{
|
||||
/** Common Python Object */
|
||||
PyObject_HEAD
|
||||
|
||||
/** Description of the transaction */
|
||||
FText Description;
|
||||
|
||||
/** Id of the pending transaction, or INDEX_NONE if there is no pending transaction */
|
||||
int32 PendingTransactionId;
|
||||
|
||||
/** New this instance (called via tp_new for Python, or directly in C++) */
|
||||
static FPyScopedEditorTransaction* New(PyTypeObject* InType);
|
||||
|
||||
/** Free this instance (called via tp_dealloc for Python) */
|
||||
static void Free(FPyScopedEditorTransaction* InSelf);
|
||||
|
||||
/** Initialize this instance (called via tp_init for Python, or directly in C++) */
|
||||
static int Init(FPyScopedEditorTransaction* InSelf, const FText& InDescription);
|
||||
|
||||
/** Deinitialize this instance (called via Init and Free to restore the instance to its New state) */
|
||||
static void Deinit(FPyScopedEditorTransaction* InSelf);
|
||||
};
|
||||
|
||||
typedef TPyPtr<FPyScopedEditorTransaction> FPyScopedEditorTransactionPtr;
|
||||
|
||||
namespace PyEditor
|
||||
{
|
||||
void InitializeModule();
|
||||
}
|
||||
|
||||
#endif // WITH_EDITOR
|
||||
|
||||
#endif // WITH_PYTHON
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,333 @@
|
||||
// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IncludePython.h"
|
||||
#include "PyPtr.h"
|
||||
#include "PyMethodWithClosure.h"
|
||||
#include "CoreMinimal.h"
|
||||
#include "UObject/ObjectMacros.h"
|
||||
|
||||
#if WITH_PYTHON
|
||||
|
||||
struct FPyWrapperBaseMetaData;
|
||||
|
||||
namespace PyGenUtil
|
||||
{
|
||||
extern const FName ScriptNameMetaDataKey;
|
||||
extern const FName ScriptNoExportMetaDataKey;
|
||||
extern const FName BlueprintTypeMetaDataKey;
|
||||
extern const FName NotBlueprintTypeMetaDataKey;
|
||||
extern const FName BlueprintSpawnableComponentMetaDataKey;
|
||||
extern const FName BlueprintGetterMetaDataKey;
|
||||
extern const FName BlueprintSetterMetaDataKey;
|
||||
|
||||
/** Name used by the Python equivalent of PostInitProperties */
|
||||
static const char* PostInitFuncName = "_post_init";
|
||||
|
||||
/** Buffer for storing the UTF-8 strings used by Python types */
|
||||
typedef TArray<char> FUTF8Buffer;
|
||||
|
||||
/** Stores the data needed by a runtime generated Python parameter */
|
||||
struct FGeneratedWrappedMethodParameter
|
||||
{
|
||||
/** The name of the parameter */
|
||||
FUTF8Buffer ParamName;
|
||||
|
||||
/** The Unreal property name for this parameter */
|
||||
FName ParamPropName;
|
||||
|
||||
/** The default Unreal ExportText value of this parameter; parameters with this set are considered optional */
|
||||
TOptional<FString> ParamDefaultValue;
|
||||
};
|
||||
|
||||
/** Stores the data needed by a runtime generated Python method */
|
||||
struct FGeneratedWrappedMethod
|
||||
{
|
||||
FGeneratedWrappedMethod()
|
||||
: Class(nullptr)
|
||||
, MethodCallback(nullptr)
|
||||
, MethodFlags(0)
|
||||
{
|
||||
}
|
||||
|
||||
/** Convert this wrapper type to its Python type */
|
||||
void ToPython(FPyMethodWithClosureDef& OutPyMethod) const;
|
||||
|
||||
/** The class to call the method on (static dispatch) */
|
||||
UClass* Class;
|
||||
|
||||
/** The name of the method */
|
||||
FUTF8Buffer MethodName;
|
||||
|
||||
/** The doc string of the method */
|
||||
FUTF8Buffer MethodDoc;
|
||||
|
||||
/** The Unreal function name for this method */
|
||||
FName MethodFuncName;
|
||||
|
||||
/* The C function this method should call */
|
||||
PyCFunctionWithClosure MethodCallback;
|
||||
|
||||
/* The METH_ flags for this method */
|
||||
int MethodFlags;
|
||||
|
||||
/** Array of parameters associated with this method */
|
||||
TArray<FGeneratedWrappedMethodParameter> MethodParams;
|
||||
};
|
||||
|
||||
/** Stores the data needed by a runtime generated Python get/set */
|
||||
struct FGeneratedWrappedGetSet
|
||||
{
|
||||
FGeneratedWrappedGetSet()
|
||||
: Class(nullptr)
|
||||
, GetCallback(nullptr)
|
||||
, SetCallback(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
/** Convert this wrapper type to its Python type */
|
||||
void ToPython(PyGetSetDef& OutPyGetSet) const;
|
||||
|
||||
/** The class to call the get/set functions on (static dispatch) */
|
||||
UClass* Class;
|
||||
|
||||
/** The name of the get/set */
|
||||
FUTF8Buffer GetSetName;
|
||||
|
||||
/** The doc string of the get/set */
|
||||
FUTF8Buffer GetSetDoc;
|
||||
|
||||
/** The Unreal property name for this get/set */
|
||||
FName PropName;
|
||||
|
||||
/** The Unreal function for the get (if any) */
|
||||
FName GetFuncName;
|
||||
|
||||
/** The Unreal function for the set (if any) */
|
||||
FName SetFuncName;
|
||||
|
||||
/* The C function that should be called for get */
|
||||
getter GetCallback;
|
||||
|
||||
/* The C function that should be called for set */
|
||||
setter SetCallback;
|
||||
};
|
||||
|
||||
/** Stores the data needed to generate a Python doc string for editor exposed properties */
|
||||
struct FGeneratedWrappedPropertyDoc
|
||||
{
|
||||
explicit FGeneratedWrappedPropertyDoc(const UProperty* InProp);
|
||||
|
||||
/** Util function to sort an array of doc structs based on the Pythonized property name */
|
||||
static bool SortPredicate(const FGeneratedWrappedPropertyDoc& InOne, const FGeneratedWrappedPropertyDoc& InTwo);
|
||||
|
||||
/** Util function to convert an array of doc structs into a combined doc string (the array should have been sorted before calling this) */
|
||||
static FString BuildDocString(const TArray<FGeneratedWrappedPropertyDoc>& InDocs, const bool bEditorVariant = false);
|
||||
|
||||
/** Util function to convert an array of doc structs into a combined doc string (the array should have been sorted before calling this) */
|
||||
static void AppendDocString(const TArray<FGeneratedWrappedPropertyDoc>& InDocs, FString& OutStr, const bool bEditorVariant = false);
|
||||
|
||||
/** Pythonized name of the property */
|
||||
FString PythonPropName;
|
||||
|
||||
/** Pythonized doc string of the property */
|
||||
FString DocString;
|
||||
|
||||
/** Pythonized editor doc string of the property */
|
||||
FString EditorDocString;
|
||||
};
|
||||
|
||||
/** Stores the data needed by a runtime generated Python type */
|
||||
struct FGeneratedWrappedType
|
||||
{
|
||||
FGeneratedWrappedType()
|
||||
{
|
||||
PyType = { PyVarObject_HEAD_INIT(nullptr, 0) };
|
||||
}
|
||||
|
||||
/** Called to ready the generated type with Python */
|
||||
bool Finalize();
|
||||
|
||||
/** The name of the type */
|
||||
FUTF8Buffer TypeName;
|
||||
|
||||
/** The doc string of the type */
|
||||
FUTF8Buffer TypeDoc;
|
||||
|
||||
/** Array of methods associated with this type */
|
||||
TArray<FGeneratedWrappedMethod> TypeMethods;
|
||||
|
||||
/** The Python methods that were generated from TypeMethods (in Finalize) */
|
||||
TArray<FPyMethodWithClosureDef> PyMethods;
|
||||
|
||||
/** Array of get/sets associated with this type */
|
||||
TArray<FGeneratedWrappedGetSet> TypeGetSets;
|
||||
|
||||
/** The Python get/sets that were generated from TypeGetSets (in Finalize) */
|
||||
TArray<PyGetSetDef> PyGetSets;
|
||||
|
||||
/** The doc string data for the properties associated with this type */
|
||||
TArray<FGeneratedWrappedPropertyDoc> TypePropertyDocs;
|
||||
|
||||
/** The meta-data associated with this type */
|
||||
TSharedPtr<FPyWrapperBaseMetaData> MetaData;
|
||||
|
||||
/* The Python type that was generated */
|
||||
PyTypeObject PyType;
|
||||
};
|
||||
|
||||
/** Definition data for an Unreal property generated from a Python type */
|
||||
struct FPropertyDef
|
||||
{
|
||||
/** Data needed to re-wrap this property for Python */
|
||||
FGeneratedWrappedGetSet GeneratedWrappedGetSet;
|
||||
|
||||
/** Definition of the re-wrapped property for Python */
|
||||
PyGetSetDef PyGetSet;
|
||||
};
|
||||
|
||||
/** Definition data for an Unreal function generated from a Python type */
|
||||
struct FFunctionDef
|
||||
{
|
||||
/** Data needed to re-wrap this function for Python */
|
||||
FGeneratedWrappedMethod GeneratedWrappedMethod;
|
||||
|
||||
/** Definition of the re-wrapped function for Python */
|
||||
FPyMethodWithClosureDef PyMethod;
|
||||
|
||||
/** Python function to call when invoking this re-wrapped function */
|
||||
FPyObjectPtr PyFunction;
|
||||
|
||||
/** Is this a function hidden from Python? (eg, internal getter/setter function) */
|
||||
bool bIsHidden;
|
||||
};
|
||||
|
||||
/** How should PythonizeName adjust the final name? */
|
||||
enum EPythonizeNameCase : uint8
|
||||
{
|
||||
/** lower_snake_case */
|
||||
Lower,
|
||||
/** UPPER_SNAKE_CASE */
|
||||
Upper,
|
||||
};
|
||||
|
||||
/** Context information passed to PythonizeTooltip */
|
||||
struct FPythonizeTooltipContext
|
||||
{
|
||||
FPythonizeTooltipContext()
|
||||
: Prop(nullptr)
|
||||
, ParamsStruct(nullptr)
|
||||
, ReadOnlyFlags(CPF_BlueprintReadOnly | CPF_EditConst)
|
||||
{
|
||||
}
|
||||
|
||||
FPythonizeTooltipContext(const UProperty* InProp, const UStruct* InParamsStruct, const uint64 InReadOnlyFlags = CPF_BlueprintReadOnly | CPF_EditConst)
|
||||
: Prop(InProp)
|
||||
, ParamsStruct(InParamsStruct)
|
||||
, ReadOnlyFlags(InReadOnlyFlags)
|
||||
{
|
||||
}
|
||||
|
||||
/** Optional property that should be used when converting property tooltips */
|
||||
const UProperty* Prop;
|
||||
|
||||
/** Optional structure of params that should be used when converting function tooltips */
|
||||
const UStruct* ParamsStruct;
|
||||
|
||||
/** Flags that dictate whether the property should be considered read-only */
|
||||
uint64 ReadOnlyFlags;
|
||||
};
|
||||
|
||||
/** Convert a TCHAR to a UTF-8 buffer */
|
||||
FUTF8Buffer TCHARToUTF8Buffer(const TCHAR* InStr);
|
||||
|
||||
/** Get the PostInit function from this Python type */
|
||||
PyObject* GetPostInitFunc(PyTypeObject* InPyType);
|
||||
|
||||
/** Add a struct init parameter to the given array of method parameters */
|
||||
void AddStructInitParam(const TCHAR* InUnrealPropName, const TCHAR* InPythonAttrName, TArray<FGeneratedWrappedMethodParameter>& OutInitParams);
|
||||
|
||||
/** Parse an array Python objects from the args and keywords based on the generated method parameter data */
|
||||
bool ParseMethodParameters(PyObject* InArgs, PyObject* InKwds, const TArray<FGeneratedWrappedMethodParameter>& InParamDef, const char* InPyMethodName, TArray<PyObject*>& OutPyParams);
|
||||
|
||||
/** Is the given class generated by Blueprints? */
|
||||
bool IsBlueprintGeneratedClass(const UClass* InClass);
|
||||
|
||||
/** Is the given struct generated by Blueprints? */
|
||||
bool IsBlueprintGeneratedStruct(const UStruct* InStruct);
|
||||
|
||||
/** Is the given enum generated by Blueprints? */
|
||||
bool IsBlueprintGeneratedEnum(const UEnum* InEnum);
|
||||
|
||||
/** Should the given class be exported to Python? */
|
||||
bool ShouldExportClass(const UClass* InClass);
|
||||
|
||||
/** Should the given struct be exported to Python? */
|
||||
bool ShouldExportStruct(const UStruct* InStruct);
|
||||
|
||||
/** Should the given enum be exported to Python? */
|
||||
bool ShouldExportEnum(const UEnum* InEnum);
|
||||
|
||||
/** Should the given property be exported to Python? */
|
||||
bool ShouldExportProperty(const UProperty* InProp);
|
||||
|
||||
/** Should the given property be exported to Python as editor-only data? */
|
||||
bool ShouldExportEditorOnlyProperty(const UProperty* InProp);
|
||||
|
||||
/** Should the given function be exported to Python? */
|
||||
bool ShouldExportFunction(const UFunction* InFunc);
|
||||
|
||||
/** Given a CamelCase name, convert it to snake_case */
|
||||
FString PythonizeName(const FString& InName, const EPythonizeNameCase InNameCase);
|
||||
|
||||
/** Given a CamelCase property name, convert it to snake_case (may remove some superfluous parts of the property name) */
|
||||
FString PythonizePropertyName(const FString& InName, const EPythonizeNameCase InNameCase);
|
||||
|
||||
/** Given a property tooltip, convert it to a doc string */
|
||||
FString PythonizePropertyTooltip(const FString& InTooltip, const UProperty* InProp, const uint64 InReadOnlyFlags = CPF_BlueprintReadOnly | CPF_EditConst);
|
||||
|
||||
/** Given a function tooltip, convert it to a doc string */
|
||||
FString PythonizeFunctionTooltip(const FString& InTooltip, const UStruct* InParamsStruct);
|
||||
|
||||
/** Given a tooltip, convert it to a doc string */
|
||||
FString PythonizeTooltip(const FString& InTooltip, const FPythonizeTooltipContext& InContext = FPythonizeTooltipContext());
|
||||
|
||||
/** Get the native module the given field belongs to */
|
||||
FString GetFieldModule(const UField* InField);
|
||||
|
||||
/** Given a native module name, get the Python module we should use */
|
||||
FString GetModulePythonName(const FName InModuleName, const bool bIncludePrefix = true);
|
||||
|
||||
/** Get the Python name of the given class */
|
||||
FString GetClassPythonName(const UClass* InClass);
|
||||
|
||||
/** Get the Python name of the given struct */
|
||||
FString GetStructPythonName(const UStruct* InStruct);
|
||||
|
||||
/** Get the Python name of the given enum */
|
||||
FString GetEnumPythonName(const UEnum* InEnum);
|
||||
|
||||
/** Get the Python name of the given delegate signature */
|
||||
FString GetDelegatePythonName(const UFunction* InDelegateSignature);
|
||||
|
||||
/** Get the Python name of the given property */
|
||||
FString GetFunctionPythonName(const UFunction* InFunc);
|
||||
|
||||
/** Get the Python name of the given property */
|
||||
FString GetPropertyPythonName(const UProperty* InProp);
|
||||
|
||||
/** Get the Python type of the given property */
|
||||
FString GetPropertyPythonType(const UProperty* InProp, const bool bIncludeReadWriteState = false, const uint64 InReadOnlyFlags = CPF_BlueprintReadOnly | CPF_EditConst);
|
||||
|
||||
/** Append the Python type of the given property to the given string */
|
||||
void AppendPropertyPythonType(const UProperty* InProp, FString& OutStr, const bool bIncludeReadWriteState = false, const uint64 InReadOnlyFlags = CPF_BlueprintReadOnly | CPF_EditConst);
|
||||
|
||||
/** Get the tooltip for the given field */
|
||||
FString GetFieldTooltip(const UField* InField);
|
||||
|
||||
/** Get the tooltip for the given enum entry */
|
||||
FString GetEnumEntryTooltip(const UEnum* InEnum, const int64 InEntryIndex);
|
||||
}
|
||||
|
||||
#endif // WITH_PYTHON
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,132 @@
|
||||
// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IncludePython.h"
|
||||
#include "CoreMinimal.h"
|
||||
|
||||
#if WITH_PYTHON
|
||||
|
||||
/** Python type for FPyCFunctionWithClosureObject */
|
||||
extern PyTypeObject PyCFunctionWithClosureType;
|
||||
|
||||
/** Python type for FPyMethodWithClosureDescrObject */
|
||||
extern PyTypeObject PyMethodWithClosureDescrType;
|
||||
|
||||
/** Python type for FPyMethodWithClosureDescrObject (for class methods) */
|
||||
extern PyTypeObject PyClassMethodWithClosureDescrType;
|
||||
|
||||
/** Initialize the PyMethodWithClosure types */
|
||||
void InitializePyMethodWithClosure();
|
||||
|
||||
/** Shutdown the PyMethodWithClosure types */
|
||||
void ShutdownPyMethodWithClosure();
|
||||
|
||||
/** C function pointers used by FPyMethodWithClosureDef */
|
||||
typedef PyObject*(*PyCFunctionWithClosure)(PyObject*, PyObject*, void*);
|
||||
typedef PyObject*(*PyCFunctionWithClosureAndKeywords)(PyObject*, PyObject*, PyObject*, void*);
|
||||
typedef PyObject*(*PyCFunctionWithClosureAndNoArgs)(PyObject*, void*);
|
||||
|
||||
/** Cast a function pointer to PyCFunctionWithClosure (via a void* to avoid a compiler warning) */
|
||||
#define PyCFunctionWithClosureCast(FUNCPTR) (PyCFunctionWithClosure)(void*)(FUNCPTR)
|
||||
|
||||
/** Definition for a method with a closure (equivalent to PyMethodDef) */
|
||||
struct FPyMethodWithClosureDef
|
||||
{
|
||||
/* The name of the method */
|
||||
const char* MethodName;
|
||||
|
||||
/* The C function this method should call */
|
||||
PyCFunctionWithClosure MethodCallback;
|
||||
|
||||
/* Combination of METH_ flags describing how the C function should be called */
|
||||
int MethodFlags;
|
||||
|
||||
/* The method documentation, or nullptr */
|
||||
const char* MethodDoc;
|
||||
|
||||
/** The closure passed to the C function, or nullptr */
|
||||
void* MethodClosure;
|
||||
|
||||
/** Add the given null-terminated table of methods to the given type */
|
||||
static bool AddMethods(FPyMethodWithClosureDef* InMethods, PyTypeObject* InType);
|
||||
|
||||
/** Create a method descriptor for the given definition */
|
||||
static PyObject* NewMethodDescriptor(PyTypeObject* InType, FPyMethodWithClosureDef* InDef);
|
||||
|
||||
/** Call the method with the given self and arguments */
|
||||
static PyObject* Call(FPyMethodWithClosureDef* InDef, PyObject* InSelf, PyObject* InArgs, PyObject* InKwds);
|
||||
};
|
||||
|
||||
/** Python object for the bound callable form of method with a closure (equivalent to PyCFunctionObject) */
|
||||
struct FPyCFunctionWithClosureObject
|
||||
{
|
||||
/** Common Python Object */
|
||||
PyObject_HEAD
|
||||
|
||||
/* Definition of the method to call */
|
||||
FPyMethodWithClosureDef* MethodDef;
|
||||
|
||||
/* The 'self' argument passed to the C function, or nullptr */
|
||||
PyObject* SelfArg;
|
||||
|
||||
/* The __module__ attribute, can be anything */
|
||||
PyObject* ModuleAttr;
|
||||
|
||||
/** New this instance */
|
||||
static FPyCFunctionWithClosureObject* New(FPyMethodWithClosureDef* InMethod, PyObject* InSelf, PyObject* InModule);
|
||||
|
||||
/** Free this instance */
|
||||
static void Free(FPyCFunctionWithClosureObject* InSelf);
|
||||
|
||||
/** Handle a Python GC traverse */
|
||||
static int GCTraverse(FPyCFunctionWithClosureObject* InSelf, visitproc InVisit, void* InArg);
|
||||
|
||||
/** Handle a Python GC clear */
|
||||
static int GCClear(FPyCFunctionWithClosureObject* InSelf);
|
||||
|
||||
/** Get a string representing this instance */
|
||||
static PyObject* Str(FPyCFunctionWithClosureObject* InSelf);
|
||||
};
|
||||
|
||||
/** Python object for the descriptor of a method with a closure (equivalent to PyMethodDescrObject) */
|
||||
struct FPyMethodWithClosureDescrObject
|
||||
{
|
||||
/** Common Python Object */
|
||||
PyObject_HEAD
|
||||
|
||||
/** Type of the owner object */
|
||||
PyTypeObject* OwnerType;
|
||||
|
||||
/** Name of the method being described */
|
||||
PyObject* MethodName;
|
||||
|
||||
/* Definition of the method to call */
|
||||
FPyMethodWithClosureDef* MethodDef;
|
||||
|
||||
/** New a method */
|
||||
static FPyMethodWithClosureDescrObject* NewMethod(PyTypeObject* InType, FPyMethodWithClosureDef* InMethod);
|
||||
|
||||
/** New a class method */
|
||||
static FPyMethodWithClosureDescrObject* NewClassMethod(PyTypeObject* InType, FPyMethodWithClosureDef* InMethod);
|
||||
|
||||
/** New this instance */
|
||||
static FPyMethodWithClosureDescrObject* NewImpl(PyTypeObject* InDescrType, PyTypeObject* InType, FPyMethodWithClosureDef* InMethod);
|
||||
|
||||
/** Free this instance */
|
||||
static void Free(FPyMethodWithClosureDescrObject* InSelf);
|
||||
|
||||
/** Handle a Python GC traverse */
|
||||
static int GCTraverse(FPyMethodWithClosureDescrObject* InSelf, visitproc InVisit, void* InArg);
|
||||
|
||||
/** Handle a Python GC clear */
|
||||
static int GCClear(FPyMethodWithClosureDescrObject* InSelf);
|
||||
|
||||
/** Get a string representing this instance */
|
||||
static PyObject* Str(FPyMethodWithClosureDescrObject* InSelf);
|
||||
|
||||
/** Safely get the name of the method (if known) */
|
||||
static FString GetMethodName(FPyMethodWithClosureDescrObject* InSelf);
|
||||
};
|
||||
|
||||
#endif // WITH_PYTHON
|
||||
@@ -0,0 +1,212 @@
|
||||
// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IncludePython.h"
|
||||
#include "Misc/AssertionMacros.h"
|
||||
|
||||
#if WITH_PYTHON
|
||||
|
||||
/** Wrapper that handles the ref-counting of the contained Python object */
|
||||
template <typename TPythonType>
|
||||
class TPyPtr
|
||||
{
|
||||
public:
|
||||
/** Create a null pointer */
|
||||
TPyPtr()
|
||||
: Ptr(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
/** Copy a pointer */
|
||||
TPyPtr(const TPyPtr& InOther)
|
||||
: Ptr(InOther.Ptr)
|
||||
{
|
||||
Py_XINCREF(Ptr);
|
||||
}
|
||||
|
||||
/** Copy a pointer */
|
||||
template <typename TOtherPythonType>
|
||||
TPyPtr(const TPyPtr<TOtherPythonType>& InOther)
|
||||
: Ptr(InOther.Ptr)
|
||||
{
|
||||
Py_XINCREF(Ptr);
|
||||
}
|
||||
|
||||
/** Move a pointer */
|
||||
TPyPtr(TPyPtr&& InOther)
|
||||
: Ptr(InOther.Ptr)
|
||||
{
|
||||
InOther.Ptr = nullptr;
|
||||
}
|
||||
|
||||
/** Move a pointer */
|
||||
template <typename TOtherPythonType>
|
||||
TPyPtr(TPyPtr<TOtherPythonType>&& InOther)
|
||||
: Ptr(InOther.Ptr)
|
||||
{
|
||||
InOther.Ptr = nullptr;
|
||||
}
|
||||
|
||||
/** Release our reference to this object */
|
||||
~TPyPtr()
|
||||
{
|
||||
Py_XDECREF(Ptr);
|
||||
}
|
||||
|
||||
/** Create a pointer from the given object, incrementing its reference count */
|
||||
static TPyPtr NewReference(TPythonType* InPtr)
|
||||
{
|
||||
return TPyPtr(InPtr, true);
|
||||
}
|
||||
|
||||
/** Create a pointer from the given object, leaving its reference count alone */
|
||||
static TPyPtr StealReference(TPythonType* InPtr)
|
||||
{
|
||||
return TPyPtr(InPtr, false);
|
||||
}
|
||||
|
||||
/** Copy a pointer */
|
||||
TPyPtr& operator=(const TPyPtr& InOther)
|
||||
{
|
||||
if (this != &InOther)
|
||||
{
|
||||
Py_XDECREF(Ptr);
|
||||
Ptr = InOther.Ptr;
|
||||
Py_XINCREF(Ptr);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Copy a pointer */
|
||||
template <typename TOtherPythonType>
|
||||
TPyPtr& operator=(const TPyPtr<TOtherPythonType>& InOther)
|
||||
{
|
||||
if (this != &InOther)
|
||||
{
|
||||
Py_XDECREF(Ptr);
|
||||
Ptr = InOther.Ptr;
|
||||
Py_XINCREF(Ptr);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Move a pointer */
|
||||
TPyPtr& operator=(TPyPtr&& InOther)
|
||||
{
|
||||
if (this != &InOther)
|
||||
{
|
||||
Py_XDECREF(Ptr);
|
||||
Ptr = InOther.Ptr;
|
||||
InOther.Ptr = nullptr;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Move a pointer */
|
||||
template <typename TOtherPythonType>
|
||||
TPyPtr& operator=(TPyPtr<TOtherPythonType>&& InOther)
|
||||
{
|
||||
if (this != &InOther)
|
||||
{
|
||||
Py_XDECREF(Ptr);
|
||||
Ptr = InOther.Ptr;
|
||||
InOther.Ptr = nullptr;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
explicit operator bool() const
|
||||
{
|
||||
return Ptr != nullptr;
|
||||
}
|
||||
|
||||
bool IsValid() const
|
||||
{
|
||||
return Ptr != nullptr;
|
||||
}
|
||||
|
||||
operator TPythonType*()
|
||||
{
|
||||
return Ptr;
|
||||
}
|
||||
|
||||
operator const TPythonType*() const
|
||||
{
|
||||
return Ptr;
|
||||
}
|
||||
|
||||
TPythonType& operator*()
|
||||
{
|
||||
check(Ptr);
|
||||
return *Ptr;
|
||||
}
|
||||
|
||||
const TPythonType& operator*() const
|
||||
{
|
||||
check(Ptr);
|
||||
return *Ptr;
|
||||
}
|
||||
|
||||
TPythonType* operator->()
|
||||
{
|
||||
check(Ptr);
|
||||
return Ptr;
|
||||
}
|
||||
|
||||
const TPythonType* operator->() const
|
||||
{
|
||||
check(Ptr);
|
||||
return Ptr;
|
||||
}
|
||||
|
||||
TPythonType*& Get()
|
||||
{
|
||||
return Ptr;
|
||||
}
|
||||
|
||||
const TPythonType*& Get() const
|
||||
{
|
||||
return Ptr;
|
||||
}
|
||||
|
||||
TPythonType* GetPtr()
|
||||
{
|
||||
return Ptr;
|
||||
}
|
||||
|
||||
const TPythonType* GetPtr() const
|
||||
{
|
||||
return Ptr;
|
||||
}
|
||||
|
||||
TPythonType* Release()
|
||||
{
|
||||
TPythonType* RetPtr = Ptr;
|
||||
Ptr = nullptr;
|
||||
return RetPtr;
|
||||
}
|
||||
|
||||
void Reset()
|
||||
{
|
||||
Py_XDECREF(Ptr);
|
||||
Ptr = nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
TPyPtr(TPythonType* InPtr, const bool bIncRef)
|
||||
: Ptr(InPtr)
|
||||
{
|
||||
if (bIncRef)
|
||||
{
|
||||
Py_XINCREF(Ptr);
|
||||
}
|
||||
}
|
||||
|
||||
TPythonType* Ptr;
|
||||
};
|
||||
|
||||
typedef TPyPtr<PyObject> FPyObjectPtr;
|
||||
typedef TPyPtr<PyTypeObject> FPyTypeObjectPtr;
|
||||
|
||||
#endif // WITH_PYTHON
|
||||
@@ -0,0 +1,261 @@
|
||||
// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#include "PyReferenceCollector.h"
|
||||
#include "PyWrapperBase.h"
|
||||
#include "UObject/UnrealType.h"
|
||||
#include "UObject/UObjectHash.h"
|
||||
|
||||
#if WITH_PYTHON
|
||||
|
||||
/** Reference collector that will purge (null) any references to the given set of objects (as if they'd bee marked PendingKill) */
|
||||
class FPyPurgingReferenceCollector : public FReferenceCollector
|
||||
{
|
||||
public:
|
||||
bool HasObjectToPurge() const
|
||||
{
|
||||
return ObjectsToPurge.Num() > 0;
|
||||
}
|
||||
|
||||
void AddObjectToPurge(const UObject* Object)
|
||||
{
|
||||
ObjectsToPurge.Add(Object);
|
||||
}
|
||||
|
||||
virtual bool IsIgnoringArchetypeRef() const override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual bool IsIgnoringTransient() const override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void HandleObjectReference(UObject*& Object, const UObject* ReferencingObject, const UProperty* ReferencingProperty) override
|
||||
{
|
||||
ConditionalPurgeObject(Object);
|
||||
}
|
||||
|
||||
virtual void HandleObjectReferences(UObject** InObjects, const int32 ObjectNum, const UObject* InReferencingObject, const UProperty* InReferencingProperty) override
|
||||
{
|
||||
for (int32 ObjectIndex = 0; ObjectIndex < ObjectNum; ++ObjectIndex)
|
||||
{
|
||||
UObject*& Object = InObjects[ObjectIndex];
|
||||
ConditionalPurgeObject(Object);
|
||||
}
|
||||
}
|
||||
|
||||
void ConditionalPurgeObject(UObject*& Object)
|
||||
{
|
||||
if (ObjectsToPurge.Contains(Object))
|
||||
{
|
||||
Object = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
TSet<const UObject*> ObjectsToPurge;
|
||||
};
|
||||
|
||||
FPyReferenceCollector& FPyReferenceCollector::Get()
|
||||
{
|
||||
static FPyReferenceCollector Instance;
|
||||
return Instance;
|
||||
}
|
||||
|
||||
void FPyReferenceCollector::AddWrappedInstance(FPyWrapperBase* InInstance)
|
||||
{
|
||||
PythonWrappedInstances.Add(InInstance);
|
||||
}
|
||||
|
||||
void FPyReferenceCollector::RemoveWrappedInstance(FPyWrapperBase* InInstance)
|
||||
{
|
||||
PythonWrappedInstances.Remove(InInstance);
|
||||
}
|
||||
|
||||
void FPyReferenceCollector::AddReferencedObjects(FReferenceCollector& InCollector)
|
||||
{
|
||||
for (FPyWrapperBase* PythonWrappedInstance : PythonWrappedInstances)
|
||||
{
|
||||
FPyWrapperBaseMetaData* PythonWrappedInstanceMetaData = FPyWrapperBaseMetaData::GetMetaData(PythonWrappedInstance);
|
||||
if (PythonWrappedInstanceMetaData && PythonWrappedInstanceMetaData->AddReferencedObjects)
|
||||
{
|
||||
PythonWrappedInstanceMetaData->AddReferencedObjects(PythonWrappedInstance, InCollector);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FPyReferenceCollector::PurgeUnrealObjectReferences(const UObject* InObject, const bool bIncludeInnerObjects)
|
||||
{
|
||||
PurgeUnrealObjectReferences(TArrayView<const UObject*>(&InObject, 1), bIncludeInnerObjects);
|
||||
}
|
||||
|
||||
void FPyReferenceCollector::PurgeUnrealObjectReferences(const TArrayView<const UObject*>& InObjects, const bool bIncludeInnerObjects)
|
||||
{
|
||||
FPyPurgingReferenceCollector PurgingReferenceCollector;
|
||||
|
||||
for (const UObject* Object : InObjects)
|
||||
{
|
||||
PurgingReferenceCollector.AddObjectToPurge(Object);
|
||||
|
||||
if (bIncludeInnerObjects)
|
||||
{
|
||||
TArray<UObject*> InnerObjects;
|
||||
GetObjectsWithOuter(Object, InnerObjects, true);
|
||||
|
||||
for (const UObject* InnerObject : InnerObjects)
|
||||
{
|
||||
PurgingReferenceCollector.AddObjectToPurge(InnerObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (PurgingReferenceCollector.HasObjectToPurge())
|
||||
{
|
||||
AddReferencedObjects(PurgingReferenceCollector);
|
||||
}
|
||||
}
|
||||
|
||||
void FPyReferenceCollector::AddReferencedObjectsFromStruct(FReferenceCollector& InCollector, const UStruct* InStruct, void* InStructAddr)
|
||||
{
|
||||
bool bUnused = false;
|
||||
AddReferencedObjectsFromStructInternal(InCollector, InStruct, InStructAddr, bUnused);
|
||||
}
|
||||
|
||||
void FPyReferenceCollector::AddReferencedObjectsFromProperty(FReferenceCollector& InCollector, const UProperty* InProp, void* InBaseAddr)
|
||||
{
|
||||
bool bUnused = false;
|
||||
AddReferencedObjectsFromPropertyInternal(InCollector, InProp, InBaseAddr, bUnused);
|
||||
}
|
||||
|
||||
void FPyReferenceCollector::AddReferencedObjectsFromStructInternal(FReferenceCollector& InCollector, const UStruct* InStruct, void* InStructAddr, bool& OutValueChanged)
|
||||
{
|
||||
for (TFieldIterator<const UProperty> PropIt(InStruct); PropIt; ++PropIt)
|
||||
{
|
||||
AddReferencedObjectsFromPropertyInternal(InCollector, *PropIt, InStructAddr, OutValueChanged);
|
||||
}
|
||||
}
|
||||
|
||||
void FPyReferenceCollector::AddReferencedObjectsFromPropertyInternal(FReferenceCollector& InCollector, const UProperty* InProp, void* InBaseAddr, bool& OutValueChanged)
|
||||
{
|
||||
if (const UObjectPropertyBase* CastProp = Cast<UObjectPropertyBase>(InProp))
|
||||
{
|
||||
for (int32 ArrIndex = 0; ArrIndex < InProp->ArrayDim; ++ArrIndex)
|
||||
{
|
||||
void* ObjValuePtr = CastProp->ContainerPtrToValuePtr<void>(InBaseAddr, ArrIndex);
|
||||
UObject* CurObjVal = CastProp->GetObjectPropertyValue(ObjValuePtr);
|
||||
if (CurObjVal)
|
||||
{
|
||||
UObject* NewObjVal = CurObjVal;
|
||||
InCollector.AddReferencedObject(NewObjVal);
|
||||
|
||||
if (NewObjVal != CurObjVal)
|
||||
{
|
||||
OutValueChanged = true;
|
||||
CastProp->SetObjectPropertyValue(ObjValuePtr, NewObjVal);
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (const UInterfaceProperty* CastProp = Cast<UInterfaceProperty>(InProp))
|
||||
{
|
||||
for (int32 ArrIndex = 0; ArrIndex < InProp->ArrayDim; ++ArrIndex)
|
||||
{
|
||||
void* ValuePtr = CastProp->ContainerPtrToValuePtr<void>(InBaseAddr, ArrIndex);
|
||||
UObject* CurObjVal = CastProp->GetPropertyValue(ValuePtr).GetObject();
|
||||
if (CurObjVal)
|
||||
{
|
||||
UObject* NewObjVal = CurObjVal;
|
||||
InCollector.AddReferencedObject(NewObjVal);
|
||||
|
||||
if (NewObjVal != CurObjVal)
|
||||
{
|
||||
OutValueChanged = true;
|
||||
CastProp->SetPropertyValue(ValuePtr, FScriptInterface(NewObjVal, NewObjVal ? NewObjVal->GetInterfaceAddress(CastProp->InterfaceClass) : nullptr));
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (const UStructProperty* CastProp = Cast<UStructProperty>(InProp))
|
||||
{
|
||||
for (int32 ArrIndex = 0; ArrIndex < InProp->ArrayDim; ++ArrIndex)
|
||||
{
|
||||
AddReferencedObjectsFromStructInternal(InCollector, CastProp->Struct, CastProp->ContainerPtrToValuePtr<void>(InBaseAddr, ArrIndex), OutValueChanged);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (const UArrayProperty* CastProp = Cast<UArrayProperty>(InProp))
|
||||
{
|
||||
for (int32 ArrIndex = 0; ArrIndex < InProp->ArrayDim; ++ArrIndex)
|
||||
{
|
||||
FScriptArrayHelper_InContainer ScriptArrayHelper(CastProp, InBaseAddr, ArrIndex);
|
||||
|
||||
const int32 ElementCount = ScriptArrayHelper.Num();
|
||||
for (int32 ElementIndex = 0; ElementIndex < ElementCount; ++ElementIndex)
|
||||
{
|
||||
AddReferencedObjectsFromPropertyInternal(InCollector, CastProp->Inner, ScriptArrayHelper.GetRawPtr(ElementIndex), OutValueChanged);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (const USetProperty* CastProp = Cast<USetProperty>(InProp))
|
||||
{
|
||||
for (int32 ArrIndex = 0; ArrIndex < InProp->ArrayDim; ++ArrIndex)
|
||||
{
|
||||
bool bSetValuesChanged = false;
|
||||
FScriptSetHelper_InContainer ScriptSetHelper(CastProp, InBaseAddr, ArrIndex);
|
||||
|
||||
for (int32 SparseElementIndex = 0; SparseElementIndex < ScriptSetHelper.GetMaxIndex(); ++SparseElementIndex)
|
||||
{
|
||||
if (ScriptSetHelper.IsValidIndex(SparseElementIndex))
|
||||
{
|
||||
AddReferencedObjectsFromPropertyInternal(InCollector, ScriptSetHelper.GetElementProperty(), ScriptSetHelper.GetElementPtr(SparseElementIndex), bSetValuesChanged);
|
||||
}
|
||||
}
|
||||
|
||||
if (bSetValuesChanged)
|
||||
{
|
||||
OutValueChanged = true;
|
||||
ScriptSetHelper.Rehash();
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (const UMapProperty* CastProp = Cast<UMapProperty>(InProp))
|
||||
{
|
||||
for (int32 ArrIndex = 0; ArrIndex < InProp->ArrayDim; ++ArrIndex)
|
||||
{
|
||||
bool bMapKeysChanged = false;
|
||||
bool bMapValuesChanged = false;
|
||||
FScriptMapHelper_InContainer ScriptMapHelper(CastProp, InBaseAddr, ArrIndex);
|
||||
|
||||
for (int32 SparseElementIndex = 0; SparseElementIndex < ScriptMapHelper.GetMaxIndex(); ++SparseElementIndex)
|
||||
{
|
||||
if (ScriptMapHelper.IsValidIndex(SparseElementIndex))
|
||||
{
|
||||
AddReferencedObjectsFromPropertyInternal(InCollector, ScriptMapHelper.GetKeyProperty(), ScriptMapHelper.GetKeyPtr(SparseElementIndex), bMapKeysChanged);
|
||||
AddReferencedObjectsFromPropertyInternal(InCollector, ScriptMapHelper.GetValueProperty(), ScriptMapHelper.GetValuePtr(SparseElementIndex), bMapValuesChanged);
|
||||
}
|
||||
}
|
||||
|
||||
if (bMapKeysChanged || bMapValuesChanged)
|
||||
{
|
||||
OutValueChanged = true;
|
||||
if (bMapKeysChanged)
|
||||
{
|
||||
ScriptMapHelper.Rehash();
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // WITH_PYTHON
|
||||
@@ -0,0 +1,51 @@
|
||||
// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "UObject/GCObject.h"
|
||||
#include "Containers/ArrayView.h"
|
||||
|
||||
#if WITH_PYTHON
|
||||
|
||||
struct FPyWrapperBase;
|
||||
|
||||
/** Singleton instance that keeps UObject instances alive while they're being referenced by Python */
|
||||
class FPyReferenceCollector : public FGCObject
|
||||
{
|
||||
public:
|
||||
/** Access the singleton instance */
|
||||
static FPyReferenceCollector& Get();
|
||||
|
||||
/** Add a wrapped instance so it can be reference collected */
|
||||
void AddWrappedInstance(FPyWrapperBase* InInstance);
|
||||
|
||||
/** Remove a wrapped instance */
|
||||
void RemoveWrappedInstance(FPyWrapperBase* InInstance);
|
||||
|
||||
/** Purge any Python references to the given UObject instance */
|
||||
void PurgeUnrealObjectReferences(const UObject* InObject, const bool bIncludeInnerObjects);
|
||||
|
||||
/** Purge any Python references to the given UObject instances */
|
||||
void PurgeUnrealObjectReferences(const TArrayView<const UObject*>& InObjects, const bool bIncludeInnerObjects);
|
||||
|
||||
//~ FGCObject interface
|
||||
virtual void AddReferencedObjects(FReferenceCollector& InCollector) override;
|
||||
|
||||
/** Utility function to ARO all properties on a struct instance */
|
||||
static void AddReferencedObjectsFromStruct(FReferenceCollector& InCollector, const UStruct* InStruct, void* InStructAddr);
|
||||
|
||||
/** Utility function to ARO the given property instance */
|
||||
static void AddReferencedObjectsFromProperty(FReferenceCollector& InCollector, const UProperty* InProp, void* InBaseAddr);
|
||||
|
||||
private:
|
||||
/** Utility function to ARO all properties on a struct instance */
|
||||
static void AddReferencedObjectsFromStructInternal(FReferenceCollector& InCollector, const UStruct* InStruct, void* InStructAddr, bool& OutValueChanged);
|
||||
|
||||
/** Utility function to ARO the given property instance */
|
||||
static void AddReferencedObjectsFromPropertyInternal(FReferenceCollector& InCollector, const UProperty* InProp, void* InBaseAddr, bool& OutValueChanged);
|
||||
|
||||
/** Set of Python wrapped instances to ARO */
|
||||
TSet<FPyWrapperBase*> PythonWrappedInstances;
|
||||
};
|
||||
|
||||
#endif // WITH_PYTHON
|
||||
@@ -0,0 +1,64 @@
|
||||
// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#include "PyTest.h"
|
||||
#include "PyUtil.h"
|
||||
|
||||
FPyTestStruct::FPyTestStruct()
|
||||
{
|
||||
Bool = false;
|
||||
Int = 0;
|
||||
Float = 0.0f;
|
||||
Enum = EPyTestEnum::One;
|
||||
}
|
||||
|
||||
UPyTestObject::UPyTestObject()
|
||||
{
|
||||
StructArray.AddDefaulted();
|
||||
StructArray.AddDefaulted();
|
||||
}
|
||||
|
||||
int32 UPyTestObject::FuncBlueprintNative_Implementation(const int32 InValue) const
|
||||
{
|
||||
return InValue;
|
||||
}
|
||||
|
||||
int32 UPyTestObject::CallFuncBlueprintImplementable(const int32 InValue) const
|
||||
{
|
||||
return FuncBlueprintImplementable(InValue);
|
||||
}
|
||||
|
||||
int32 UPyTestObject::CallFuncBlueprintNative(const int32 InValue) const
|
||||
{
|
||||
return FuncBlueprintNative(InValue);
|
||||
}
|
||||
|
||||
void UPyTestObject::FuncTakingPyTestStruct(const FPyTestStruct& InStruct) const
|
||||
{
|
||||
}
|
||||
|
||||
void UPyTestObject::FuncTakingPyTestChildStruct(const FPyTestChildStruct& InStruct) const
|
||||
{
|
||||
}
|
||||
|
||||
int32 UPyTestObject::FuncTakingPyTestDelegate(const FPyTestDelegate& InDelegate, const int32 InValue) const
|
||||
{
|
||||
return InDelegate.IsBound() ? InDelegate.Execute(InValue) : INDEX_NONE;
|
||||
}
|
||||
|
||||
int32 UPyTestObject::DelegatePropertyCallback(const int32 InValue) const
|
||||
{
|
||||
if (InValue != Int)
|
||||
{
|
||||
UE_LOG(LogPython, Error, TEXT("Given value (%d) did not match the Int property value (%d)"), InValue, Int);
|
||||
}
|
||||
|
||||
return InValue;
|
||||
}
|
||||
|
||||
void UPyTestObject::MulticastDelegatePropertyCallback(FString InStr) const
|
||||
{
|
||||
if (InStr != String)
|
||||
{
|
||||
UE_LOG(LogPython, Error, TEXT("Given value (%s) did not match the String property value (%s)"), *InStr, *String);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,170 @@
|
||||
// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "PyTest.generated.h"
|
||||
|
||||
/**
|
||||
* Delegate to allow testing of the various script delegate features that are exposed to Python wrapped types.
|
||||
*/
|
||||
DECLARE_DYNAMIC_DELEGATE_RetVal_OneParam(int32, FPyTestDelegate, int32, InValue);
|
||||
|
||||
/**
|
||||
* Multicast delegate to allow testing of the various script delegate features that are exposed to Python wrapped types.
|
||||
*/
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FPyTestMulticastDelegate, FString, InStr);
|
||||
|
||||
/**
|
||||
* Enum to allow testing of the various UEnum features that are exposed to Python wrapped types.
|
||||
*/
|
||||
UENUM(BlueprintType)
|
||||
enum class EPyTestEnum : uint8
|
||||
{
|
||||
One,
|
||||
Two,
|
||||
};
|
||||
|
||||
/**
|
||||
* Struct to allow testing of the various UStruct features that are exposed to Python wrapped types.
|
||||
*/
|
||||
USTRUCT(BlueprintType)
|
||||
struct FPyTestStruct
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
FPyTestStruct();
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Python)
|
||||
bool Bool;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Python)
|
||||
int32 Int;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Python)
|
||||
float Float;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Python)
|
||||
EPyTestEnum Enum;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Python)
|
||||
FString String;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Python)
|
||||
FName Name;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Python)
|
||||
FText Text;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Python)
|
||||
TArray<FString> StringArray;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Python)
|
||||
TSet<FString> StringSet;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Python)
|
||||
TMap<FString, int32> StringIntMap;
|
||||
};
|
||||
|
||||
/**
|
||||
* Struct to allow testing of inheritance on Python wrapped types.
|
||||
*/
|
||||
USTRUCT(BlueprintType)
|
||||
struct FPyTestChildStruct : public FPyTestStruct
|
||||
{
|
||||
GENERATED_BODY()
|
||||
};
|
||||
|
||||
/**
|
||||
* Object to allow testing of the various UObject features that are exposed to Python wrapped types.
|
||||
*/
|
||||
UCLASS(Blueprintable)
|
||||
class UPyTestObject : public UObject
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UPyTestObject();
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Python)
|
||||
bool Bool;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Python)
|
||||
int32 Int;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Python)
|
||||
float Float;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Python)
|
||||
EPyTestEnum Enum;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Python)
|
||||
FString String;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Python)
|
||||
FName Name;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Python)
|
||||
FText Text;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Python)
|
||||
TArray<FString> StringArray;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Python)
|
||||
TSet<FString> StringSet;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Python)
|
||||
TMap<FString, int32> StringIntMap;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Python)
|
||||
FPyTestDelegate Delegate;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Python)
|
||||
FPyTestMulticastDelegate MulticastDelegate;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Python)
|
||||
FPyTestStruct Struct;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Python)
|
||||
TArray<FPyTestStruct> StructArray;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Python)
|
||||
FPyTestChildStruct ChildStruct;
|
||||
|
||||
UFUNCTION(BlueprintImplementableEvent, Category = Python)
|
||||
int32 FuncBlueprintImplementable(const int32 InValue) const;
|
||||
|
||||
UFUNCTION(BlueprintNativeEvent, Category = Python)
|
||||
int32 FuncBlueprintNative(const int32 InValue) const;
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = Python)
|
||||
int32 CallFuncBlueprintImplementable(const int32 InValue) const;
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = Python)
|
||||
int32 CallFuncBlueprintNative(const int32 InValue) const;
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = Python)
|
||||
void FuncTakingPyTestStruct(const FPyTestStruct& InStruct) const;
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = Python)
|
||||
void FuncTakingPyTestChildStruct(const FPyTestChildStruct& InStruct) const;
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = Python)
|
||||
int32 FuncTakingPyTestDelegate(const FPyTestDelegate& InDelegate, const int32 InValue) const;
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = Python)
|
||||
int32 DelegatePropertyCallback(const int32 InValue) const;
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = Python)
|
||||
void MulticastDelegatePropertyCallback(FString InStr) const;
|
||||
};
|
||||
|
||||
/**
|
||||
* Object to allow testing of inheritance on Python wrapped types.
|
||||
*/
|
||||
UCLASS(Blueprintable)
|
||||
class UPyTestChildObject : public UPyTestObject
|
||||
{
|
||||
GENERATED_BODY()
|
||||
};
|
||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user