Skip to content

Commit 9a55002

Browse files
author
Roberto De Ioris
committed
Refactored SPythonWidget
1 parent 8c4d54a commit 9a55002

7 files changed

Lines changed: 303 additions & 100 deletions

File tree

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
#include "UnrealEnginePythonPrivatePCH.h"
2+
3+
#include "UEPyFCharacterEvent.h"
4+
5+
static PyObject *py_ue_fcharacter_event_get_character(ue_PyFCharacterEvent *self, PyObject * args)
6+
{
7+
TCHAR c = self->character_event.GetCharacter();
8+
FString s = FString(1, &c);
9+
return PyUnicode_FromString(TCHAR_TO_UTF8(*s));
10+
}
11+
12+
static PyMethodDef ue_PyFCharacterEvent_methods[] = {
13+
{ "get_character", (PyCFunction)py_ue_fcharacter_event_get_character, METH_VARARGS, "" },
14+
{ NULL } /* Sentinel */
15+
};
16+
17+
static PyObject *ue_PyFCharacterEvent_str(ue_PyFCharacterEvent *self)
18+
{
19+
TCHAR c = self->character_event.GetCharacter();
20+
FString s = FString(1, &c);
21+
return PyUnicode_FromFormat("<unreal_engine.FCharacterEvent '%s'>",
22+
TCHAR_TO_UTF8(*s));
23+
}
24+
25+
static PyTypeObject ue_PyFCharacterEventType = {
26+
PyVarObject_HEAD_INIT(NULL, 0)
27+
"unreal_engine.FCharacterEvent", /* tp_name */
28+
sizeof(ue_PyFCharacterEvent), /* tp_basicsize */
29+
0, /* tp_itemsize */
30+
0, /* tp_dealloc */
31+
0, /* tp_print */
32+
0, /* tp_getattr */
33+
0, /* tp_setattr */
34+
0, /* tp_reserved */
35+
0, /* tp_repr */
36+
0, /* tp_as_number */
37+
0, /* tp_as_sequence */
38+
0, /* tp_as_mapping */
39+
0, /* tp_hash */
40+
0, /* tp_call */
41+
(reprfunc)ue_PyFCharacterEvent_str, /* tp_str */
42+
0, /* tp_getattro */
43+
0, /* tp_setattro */
44+
0, /* tp_as_buffer */
45+
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
46+
"Unreal Engine FCharacterEvent", /* tp_doc */
47+
0, /* tp_traverse */
48+
0, /* tp_clear */
49+
0, /* tp_richcompare */
50+
0, /* tp_weaklistoffset */
51+
0, /* tp_iter */
52+
0, /* tp_iternext */
53+
ue_PyFCharacterEvent_methods, /* tp_methods */
54+
};
55+
56+
void ue_python_init_fcharacter_event(PyObject *ue_module)
57+
{
58+
59+
ue_PyFCharacterEventType.tp_base = &ue_PyFInputEventType;
60+
61+
if (PyType_Ready(&ue_PyFCharacterEventType) < 0)
62+
return;
63+
64+
Py_INCREF(&ue_PyFCharacterEventType);
65+
PyModule_AddObject(ue_module, "FCharacterEvent", (PyObject *)&ue_PyFCharacterEventType);
66+
}
67+
68+
PyObject *py_ue_new_fcharacter_event(FCharacterEvent key_event)
69+
{
70+
ue_PyFCharacterEvent *ret = (ue_PyFCharacterEvent *)PyObject_New(ue_PyFCharacterEvent, &ue_PyFCharacterEventType);
71+
new(&ret->character_event) FCharacterEvent(key_event);
72+
new(&ret->f_input.input) FInputEvent(key_event);
73+
return (PyObject *)ret;
74+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#pragma once
2+
3+
#include "UnrealEnginePython.h"
4+
5+
#include "UEPyFInputEvent.h"
6+
7+
extern PyTypeObject ue_PyFInputEventType;
8+
9+
typedef struct {
10+
/* Type-specific fields go here. */
11+
ue_PyFInputEvent f_input;
12+
FCharacterEvent character_event;
13+
} ue_PyFCharacterEvent;
14+
15+
void ue_python_init_fcharacter_event(PyObject *);
16+
17+
PyObject *py_ue_new_fcharacter_event(FCharacterEvent);

‎Source/UnrealEnginePython/Private/Slate/UEPySPythonWidget.cpp‎

Lines changed: 3 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -42,43 +42,13 @@ PyTypeObject ue_PySPythonWidgetType = {
4242

4343
static int ue_py_spython_widget_init(ue_PySPythonWidget *self, PyObject *args, PyObject *kwargs)
4444
{
45-
4645
ue_py_snew_simple(SPythonWidget, s_compound_widget.s_widget);
47-
48-
if (kwargs)
49-
{
50-
if (PyObject *py_tick = PyDict_GetItemString(kwargs, "tick"))
51-
{
52-
if (!PyCallable_Check(py_tick))
53-
{
54-
PyErr_SetString(PyExc_Exception, "tick must be a callable");
55-
return -1;
56-
}
57-
sw_python_widget->SetPythonTick(py_tick);
58-
}
59-
else
60-
{
61-
PyErr_Clear();
62-
}
63-
64-
if (PyObject *py_paint = PyDict_GetItemString(kwargs, "paint"))
65-
{
66-
if (!PyCallable_Check(py_paint))
67-
{
68-
PyErr_SetString(PyExc_Exception, "paint must be a callable");
69-
return -1;
70-
}
71-
sw_python_widget->SetPythonPaint(py_paint);
72-
}
73-
else
74-
{
75-
PyErr_Clear();
76-
}
77-
}
78-
46+
UE_LOG(LogPython, Warning, TEXT("Initializing World Widget!!!"));
47+
sw_python_widget->SetPyObject((PyObject *)self);
7948
return 0;
8049
}
8150

51+
8252
void ue_python_init_spython_widget(PyObject *ue_module)
8353
{
8454

‎Source/UnrealEnginePython/Private/Slate/UEPySPythonWidget.h‎

Lines changed: 97 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
#include "UEPySCompoundWidget.h"
66
#include "UEPyFGeometry.h"
77
#include "UEPyFPaintContext.h"
8+
#include "UEPyFCharacterEvent.h"
9+
#include "UEPyFKeyEvent.h"
810

911
extern PyTypeObject ue_PySPythonWidgetType;
1012

@@ -13,14 +15,80 @@ class SPythonWidget : public SCompoundWidget
1315
public:
1416

1517
SLATE_BEGIN_ARGS(SPythonWidget)
16-
{ }
18+
{
19+
}
1720
SLATE_END_ARGS();
1821

1922
void Construct(const FArguments& Args)
2023
{
2124

2225
}
2326

27+
virtual bool SupportsKeyboardFocus() const override
28+
{
29+
return true;
30+
}
31+
32+
virtual FReply OnKeyChar(const FGeometry & MyGeometry, const FCharacterEvent & InCharacterEvent) override
33+
{
34+
FScopePythonGIL gil;
35+
36+
if (!PyObject_HasAttrString(self, (char *)"on_key_char"))
37+
return FReply::Unhandled();
38+
39+
PyObject *py_callable_on_key_char = PyObject_GetAttrString(self, (char *)"on_key_char");
40+
if (!PyCallable_Check(py_callable_on_key_char))
41+
{
42+
UE_LOG(LogPython, Error, TEXT("on_key_char is not a callable"));
43+
return FReply::Unhandled();
44+
}
45+
46+
PyObject *ret = PyObject_CallFunction(py_callable_on_key_char, (char *)"OO", py_ue_new_fgeometry(MyGeometry), py_ue_new_fcharacter_event(InCharacterEvent));
47+
if (!ret)
48+
{
49+
unreal_engine_py_log_error();
50+
return FReply::Unhandled();
51+
}
52+
53+
if (ret == Py_False)
54+
{
55+
Py_DECREF(ret);
56+
return FReply::Unhandled();
57+
}
58+
Py_DECREF(ret);
59+
return FReply::Handled();
60+
}
61+
62+
virtual FReply OnKeyDown(const FGeometry & MyGeometry, const FKeyEvent & InKeyEvent) override
63+
{
64+
FScopePythonGIL gil;
65+
66+
if (!PyObject_HasAttrString(self, (char *)"on_key_down"))
67+
return FReply::Unhandled();
68+
69+
PyObject *py_callable_on_key_down = PyObject_GetAttrString(self, (char *)"on_key_down");
70+
if (!PyCallable_Check(py_callable_on_key_down))
71+
{
72+
UE_LOG(LogPython, Error, TEXT("on_key_down is not a callable"));
73+
return FReply::Unhandled();
74+
}
75+
76+
PyObject *ret = PyObject_CallFunction(py_callable_on_key_down, (char *)"OO", py_ue_new_fgeometry(MyGeometry), py_ue_new_fkey_event(InKeyEvent));
77+
if (!ret)
78+
{
79+
unreal_engine_py_log_error();
80+
return FReply::Unhandled();
81+
}
82+
83+
if (ret == Py_False)
84+
{
85+
Py_DECREF(ret);
86+
return FReply::Unhandled();
87+
}
88+
Py_DECREF(ret);
89+
return FReply::Handled();
90+
}
91+
2492
virtual int32 OnPaint(const FPaintArgs & Args,
2593
const FGeometry & AllottedGeometry,
2694
const FSlateRect & MyClippingRect,
@@ -30,23 +98,29 @@ class SPythonWidget : public SCompoundWidget
3098
bool bParentEnabled) const override
3199
{
32100

33-
if (py_callable_paint)
34-
{
35-
FPaintContext context(AllottedGeometry, MyClippingRect, OutDrawElements, LayerId, InWidgetStyle, bParentEnabled);
101+
FScopePythonGIL gil;
36102

37-
FScopePythonGIL gil;
103+
if (!PyObject_HasAttrString(self, (char *)"paint"))
104+
return LayerId + 1;
38105

39-
PyObject *ret = PyObject_CallFunction(py_callable_paint, (char *)"O", py_ue_new_fpaint_context(context));
40-
if (!ret)
41-
{
42-
unreal_engine_py_log_error();
43-
return LayerId + 1;
44-
}
106+
PyObject *py_callable_paint = PyObject_GetAttrString(self, (char *)"paint");
107+
if (!PyCallable_Check(py_callable_paint))
108+
{
109+
UE_LOG(LogPython, Error, TEXT("paint is not a callable"));
110+
return LayerId + 1;
111+
}
45112

46-
Py_DECREF(ret);
113+
FPaintContext context(AllottedGeometry, MyClippingRect, OutDrawElements, LayerId, InWidgetStyle, bParentEnabled);
47114

115+
PyObject *ret = PyObject_CallFunction(py_callable_paint, (char *)"O", py_ue_new_fpaint_context(context));
116+
if (!ret)
117+
{
118+
unreal_engine_py_log_error();
119+
return LayerId + 1;
48120
}
49121

122+
Py_DECREF(ret);
123+
50124
return LayerId + 1;
51125

52126
}
@@ -55,11 +129,17 @@ class SPythonWidget : public SCompoundWidget
55129
const double InCurrentTime,
56130
const float InDeltaTime) override
57131
{
132+
FScopePythonGIL gil;
58133

59-
if (!py_callable_tick)
134+
if (!PyObject_HasAttrString(self, (char *)"tick"))
60135
return;
61136

62-
FScopePythonGIL gil;
137+
PyObject *py_callable_tick = PyObject_GetAttrString(self, (char *)"tick");
138+
if (!PyCallable_Check(py_callable_tick))
139+
{
140+
UE_LOG(LogPython, Error, TEXT("tick is not a callable"));
141+
return;
142+
}
63143

64144
PyObject *ret = PyObject_CallFunction(py_callable_tick, (char *)"Off", py_ue_new_fgeometry(AllottedGeometry), InCurrentTime, InDeltaTime);
65145
if (!ret)
@@ -71,19 +151,13 @@ class SPythonWidget : public SCompoundWidget
71151
Py_DECREF(ret);
72152
}
73153

74-
void SetPythonPaint(PyObject *py_callable)
75-
{
76-
py_callable_paint = py_callable;
77-
}
78-
79-
void SetPythonTick(PyObject *py_callable)
154+
void SetPyObject(PyObject *py_obj)
80155
{
81-
py_callable_tick = py_callable;
156+
self = py_obj;
82157
}
83158

84159
protected:
85-
PyObject *py_callable_tick;
86-
PyObject *py_callable_paint;
160+
PyObject *self;
87161

88162
};
89163

0 commit comments

Comments
 (0)