1+ #include " UnrealEnginePythonPrivatePCH.h"
2+ #include " PyPawn.h"
3+
4+
5+
6+ APyPawn::APyPawn ()
7+ {
8+ PrimaryActorTick.bCanEverTick = true ;
9+
10+ this ->OnActorBeginOverlap .AddDynamic (this , &APyPawn::PyOnActorBeginOverlap);
11+ this ->OnClicked .AddDynamic (this , &APyPawn::PyOnActorClicked);
12+
13+ // pre-generate PyUObject (for performance)
14+ ue_get_python_wrapper (this );
15+ }
16+
17+
18+ // Called when the game starts
19+ void APyPawn::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_pawn_module = PyImport_ImportModule (TCHAR_TO_UTF8 (*PythonModule));
39+ if (!py_pawn_module) {
40+ unreal_engine_py_log_error ();
41+ return ;
42+ }
43+
44+ #if WITH_EDITOR
45+ // todo implement autoreload with a dictionary of module timestamps
46+ py_pawn_module = PyImport_ReloadModule (py_pawn_module);
47+ if (!py_pawn_module) {
48+ unreal_engine_py_log_error ();
49+ return ;
50+ }
51+ #endif
52+
53+ if (PythonClass.IsEmpty ())
54+ return ;
55+
56+ PyObject *py_pawn_module_dict = PyModule_GetDict (py_pawn_module);
57+ PyObject *py_pawn_class = PyDict_GetItemString (py_pawn_module_dict, TCHAR_TO_UTF8 (*PythonClass));
58+
59+ if (!py_pawn_class) {
60+ unreal_engine_py_log_error ();
61+ return ;
62+ }
63+
64+ py_pawn_instance = PyObject_CallObject (py_pawn_class, NULL );
65+ if (!py_pawn_instance) {
66+ unreal_engine_py_log_error ();
67+ return ;
68+ }
69+
70+ PyObject *py_obj = (PyObject *) ue_get_python_wrapper (this );
71+
72+ if (py_obj) {
73+ PyObject_SetAttrString (py_pawn_instance, " uobject" , py_obj);
74+ }
75+ else {
76+ UE_LOG (LogPython, Error, TEXT (" Unable to set 'uobject' field in pawn wrapper class" ));
77+ }
78+
79+ PyObject *bp_ret = PyObject_CallMethod (py_pawn_instance, " begin_play" , NULL );
80+ if (!bp_ret) {
81+ unreal_engine_py_log_error ();
82+ return ;
83+ }
84+ Py_DECREF (bp_ret);
85+ }
86+
87+
88+ // Called every frame
89+ void APyPawn::Tick (float DeltaTime)
90+ {
91+ Super::Tick (DeltaTime);
92+
93+ if (!py_pawn_instance)
94+ return ;
95+
96+ PyObject *ret = PyObject_CallMethod (py_pawn_instance, " tick" , " f" , DeltaTime);
97+ if (!ret) {
98+ unreal_engine_py_log_error ();
99+ return ;
100+ }
101+ Py_DECREF (ret);
102+
103+ }
104+
105+
106+ void APyPawn::PyOnActorBeginOverlap (AActor *overlapped, AActor *other)
107+ {
108+ if (!py_pawn_instance)
109+ return ;
110+
111+ PyObject *ret = PyObject_CallMethod (py_pawn_instance, " on_actor_begin_overlap" , " O" , (PyObject *)ue_get_python_wrapper (other));
112+ if (!ret) {
113+ unreal_engine_py_log_error ();
114+ return ;
115+ }
116+ Py_DECREF (ret);
117+ }
118+
119+ void APyPawn::PyOnActorClicked (AActor *touched_actor, FKey button_pressed)
120+ {
121+ if (!py_pawn_instance)
122+ return ;
123+
124+ PyObject *ret = PyObject_CallMethod (py_pawn_instance, " on_actor_clicked" , " Os" , (PyObject *)ue_get_python_wrapper (touched_actor), TCHAR_TO_UTF8 (*button_pressed.ToString ()));
125+ if (!ret) {
126+ unreal_engine_py_log_error ();
127+ return ;
128+ }
129+ Py_DECREF (ret);
130+ }
131+
132+ void APyPawn::CallPythonPawnMethod (FString method_name)
133+ {
134+ if (!py_pawn_instance)
135+ return ;
136+
137+ PyObject *ret = PyObject_CallMethod (py_pawn_instance, TCHAR_TO_UTF8 (*method_name), NULL );
138+ if (!ret) {
139+ unreal_engine_py_log_error ();
140+ return ;
141+ }
142+ Py_DECREF (ret);
143+ }
144+
145+ bool APyPawn::CallPythonPawnMethodBool (FString method_name)
146+ {
147+ if (!py_pawn_instance)
148+ return false ;
149+
150+ PyObject *ret = PyObject_CallMethod (py_pawn_instance, TCHAR_TO_UTF8 (*method_name), NULL );
151+ if (!ret) {
152+ unreal_engine_py_log_error ();
153+ return false ;
154+ }
155+
156+ if (PyObject_IsTrue (ret)) {
157+ Py_DECREF (ret);
158+ return true ;
159+ }
160+
161+ Py_DECREF (ret);
162+ return false ;
163+ }
164+
165+ FString APyPawn::CallPythonPawnMethodString (FString method_name)
166+ {
167+ if (!py_pawn_instance)
168+ return FString ();
169+
170+ PyObject *ret = PyObject_CallMethod (py_pawn_instance, TCHAR_TO_UTF8 (*method_name), NULL );
171+ if (!ret) {
172+ unreal_engine_py_log_error ();
173+ return FString ();
174+ }
175+
176+ PyObject *py_str = PyObject_Str (ret);
177+ if (!py_str) {
178+ Py_DECREF (ret);
179+ return FString ();
180+ }
181+
182+ char *str_ret = PyUnicode_AsUTF8 (py_str);
183+
184+ FString ret_fstring = FString (UTF8_TO_TCHAR (str_ret));
185+
186+ Py_DECREF (py_str);
187+
188+ return ret_fstring;
189+ }
190+
191+
192+ APyPawn::~APyPawn ()
193+ {
194+ Py_XDECREF (py_pawn_instance);
195+ UE_LOG (LogPython, Warning, TEXT (" Python APawn wrapper XDECREF'ed" ));
196+ }
0 commit comments