Skip to content

Commit 9970cf9

Browse files
author
Roberto De Ioris
committed
first public import
1 parent d4af8b4 commit 9970cf9

File tree

12 files changed

+1099
-0
lines changed

12 files changed

+1099
-0
lines changed

Resources/Icon128.png

12.4 KB
Loading
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
#include "UnrealEnginePythonPrivatePCH.h"
2+
#include "PyActor.h"
3+
4+
5+
6+
APyActor::APyActor()
7+
{
8+
PrimaryActorTick.bCanEverTick = true;
9+
10+
// pre-generate PyUObject (for performance)
11+
ue_get_python_wrapper(this);
12+
}
13+
14+
15+
// Called when the game starts
16+
void APyActor::BeginPlay()
17+
{
18+
Super::BeginPlay();
19+
20+
// ...
21+
22+
const TCHAR *blob = *PythonCode;
23+
24+
int ret = PyRun_SimpleString(TCHAR_TO_UTF8(blob));
25+
26+
UE_LOG(LogPython, Warning, TEXT("Python ret = %d"), ret);
27+
28+
if (ret) {
29+
unreal_engine_py_log_error();
30+
}
31+
32+
if (PythonModule.IsEmpty())
33+
return;
34+
35+
PyObject *py_actor_module = PyImport_ImportModule(TCHAR_TO_UTF8(*PythonModule));
36+
if (!py_actor_module) {
37+
unreal_engine_py_log_error();
38+
return;
39+
}
40+
41+
// todo implement autoreload with a dictionary of module timestamps
42+
py_actor_module = PyImport_ReloadModule(py_actor_module);
43+
if (!py_actor_module) {
44+
unreal_engine_py_log_error();
45+
return;
46+
}
47+
48+
if (PythonClass.IsEmpty())
49+
return;
50+
51+
PyObject *py_actor_module_dict = PyModule_GetDict(py_actor_module);
52+
PyObject *py_actor_class = PyDict_GetItemString(py_actor_module_dict, TCHAR_TO_UTF8(*PythonClass));
53+
54+
if (!py_actor_class) {
55+
unreal_engine_py_log_error();
56+
return;
57+
}
58+
59+
py_actor_instance = PyObject_CallObject(py_actor_class, NULL);
60+
if (!py_actor_instance) {
61+
unreal_engine_py_log_error();
62+
return;
63+
}
64+
65+
PyObject *py_obj = (PyObject *) ue_get_python_wrapper(this);
66+
67+
if (py_obj) {
68+
PyObject_SetAttrString(py_actor_instance, "uobject", py_obj);
69+
}
70+
else {
71+
UE_LOG(LogPython, Error, TEXT("Unable to set 'uobject' field in actor wrapper class"));
72+
}
73+
74+
PyObject *bp_ret = PyObject_CallMethod(py_actor_instance, "begin_play", NULL);
75+
if (!bp_ret) {
76+
unreal_engine_py_log_error();
77+
return;
78+
}
79+
Py_DECREF(bp_ret);
80+
}
81+
82+
83+
// Called every frame
84+
void APyActor::Tick(float DeltaTime)
85+
{
86+
Super::Tick(DeltaTime);
87+
88+
if (!py_actor_instance)
89+
return;
90+
91+
PyObject *ret = PyObject_CallMethod(py_actor_instance, "tick", "f", DeltaTime);
92+
if (!ret) {
93+
unreal_engine_py_log_error();
94+
return;
95+
}
96+
Py_DECREF(ret);
97+
98+
}
99+
100+
APyActor::~APyActor()
101+
{
102+
Py_XDECREF(py_actor_instance);
103+
UE_LOG(LogPython, Error, TEXT("Python AActor wrapper XDECREF'ed"));
104+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#pragma once
2+
3+
4+
#include "GameFramework/Actor.h"
5+
6+
#include "PyActor.generated.h"
7+
8+
9+
10+
UCLASS(BlueprintType, Blueprintable, Config = Engine, ClassGroup = (Python))
11+
class APyActor : public AActor
12+
{
13+
GENERATED_BODY()
14+
15+
public:
16+
// Sets default values for this component's properties
17+
APyActor();
18+
~APyActor();
19+
20+
// Called when the game starts
21+
virtual void BeginPlay() override;
22+
23+
// Called every frame
24+
virtual void Tick(float DeltaSeconds) override;
25+
26+
UPROPERTY(EditAnywhere, meta = (Multiline = true), Category = "Python")
27+
FString PythonCode;
28+
29+
UPROPERTY(EditAnywhere , Category = "Python")
30+
FString PythonModule;
31+
32+
UPROPERTY(EditAnywhere, Category = "Python")
33+
FString PythonClass;
34+
35+
private:
36+
PyObject *py_actor_instance;
37+
};
38+
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
#include "UnrealEnginePythonPrivatePCH.h"
2+
#include "PyActorComponent.h"
3+
4+
5+
6+
UPyActorComponent::UPyActorComponent()
7+
{
8+
// Set this component to be initialized when the game starts, and to be ticked every frame. You can turn these features
9+
// off to improve performance if you don't need them.
10+
bWantsBeginPlay = true;
11+
PrimaryComponentTick.bCanEverTick = true;
12+
13+
// pre-generate PyUObject (for performance)
14+
ue_get_python_wrapper(this);
15+
}
16+
17+
18+
// Called when the game starts
19+
void UPyActorComponent::BeginPlay()
20+
{
21+
Super::BeginPlay();
22+
23+
// ...
24+
25+
const TCHAR *blob = *PythonCode;
26+
27+
int ret = PyRun_SimpleString(TCHAR_TO_UTF8(blob));
28+
29+
UE_LOG(LogPython, Warning, TEXT("Python ret = %d"), ret);
30+
31+
if (ret) {
32+
unreal_engine_py_log_error();
33+
}
34+
35+
if (PythonModule.IsEmpty())
36+
return;
37+
38+
PyObject *py_component_module = PyImport_ImportModule(TCHAR_TO_UTF8(*PythonModule));
39+
if (!py_component_module) {
40+
unreal_engine_py_log_error();
41+
return;
42+
}
43+
44+
// todo implement autoreload with a dictionary of mule timestamps
45+
py_component_module = PyImport_ReloadModule(py_component_module);
46+
if (!py_component_module) {
47+
unreal_engine_py_log_error();
48+
return;
49+
}
50+
51+
if (PythonClass.IsEmpty())
52+
return;
53+
54+
PyObject *py_component_module_dict = PyModule_GetDict(py_component_module);
55+
PyObject *py_component_class = PyDict_GetItemString(py_component_module_dict, TCHAR_TO_UTF8(*PythonClass));
56+
57+
if (!py_component_class) {
58+
unreal_engine_py_log_error();
59+
return;
60+
}
61+
62+
py_component_instance = PyObject_CallObject(py_component_class, NULL);
63+
if (!py_component_instance) {
64+
unreal_engine_py_log_error();
65+
return;
66+
}
67+
68+
PyObject *py_obj = (PyObject *) ue_get_python_wrapper(this);
69+
70+
if (py_obj) {
71+
PyObject_SetAttrString(py_component_instance, "uobject", py_obj);
72+
}
73+
else {
74+
UE_LOG(LogPython, Error, TEXT("Unable to set 'uobject' field in component wrapper class"));
75+
}
76+
77+
PyObject *bp_ret = PyObject_CallMethod(py_component_instance, "begin_play", NULL);
78+
if (!bp_ret) {
79+
unreal_engine_py_log_error();
80+
return;
81+
}
82+
Py_DECREF(bp_ret);
83+
}
84+
85+
86+
// Called every frame
87+
void UPyActorComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
88+
{
89+
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
90+
91+
if (!py_component_instance)
92+
return;
93+
94+
PyObject *ret = PyObject_CallMethod(py_component_instance, "tick", "f", DeltaTime);
95+
if (!ret) {
96+
unreal_engine_py_log_error();
97+
return;
98+
}
99+
Py_DECREF(ret);
100+
101+
}
102+
103+
UPyActorComponent::~UPyActorComponent()
104+
{
105+
Py_XDECREF(py_component_instance);
106+
UE_LOG(LogPython, Error, TEXT("Python UActorComponent wrapper XDECREF'ed"));
107+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#pragma once
2+
3+
#include "Components/ActorComponent.h"
4+
5+
#include "PyActorComponent.generated.h"
6+
7+
8+
9+
UCLASS(ClassGroup = (Python), meta = (BlueprintSpawnableComponent))
10+
class UPyActorComponent : public UActorComponent
11+
{
12+
GENERATED_BODY()
13+
14+
public:
15+
// Sets default values for this component's properties
16+
UPyActorComponent();
17+
~UPyActorComponent();
18+
19+
// Called when the game starts
20+
virtual void BeginPlay() override;
21+
22+
// Called every frame
23+
virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;
24+
25+
UPROPERTY(EditAnywhere, meta = (Multiline = true), Category = "Python")
26+
FString PythonCode;
27+
28+
UPROPERTY(EditAnywhere , Category = "Python")
29+
FString PythonModule;
30+
31+
UPROPERTY(EditAnywhere, Category = "Python")
32+
FString PythonClass;
33+
34+
35+
36+
private:
37+
PyObject *py_component_instance;
38+
};
39+

0 commit comments

Comments
 (0)