Skip to content

Commit 74e6f3f

Browse files
author
Roberto De Ioris
committed
added SScrollBox
1 parent e6edbff commit 74e6f3f

File tree

7 files changed

+195
-75
lines changed

7 files changed

+195
-75
lines changed

Source/UnrealEnginePython/Private/Slate/UEPySPythonComboBox.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ static int ue_py_spython_combo_box_init(ue_PySPythonComboBox *self, PyObject *ar
8484
ue_py_slate_setup_farguments(SPythonComboBox);
8585

8686
// first of all check for values
87-
PyObject *values = ue_py_dict_get_item(kwargs, "values");
87+
PyObject *values = ue_py_dict_get_item(kwargs, "options_source");
8888
if (!values) {
8989
PyErr_SetString(PyExc_Exception, "you must specify the combo box items");
9090
return -1;

Source/UnrealEnginePython/Private/Slate/UEPySPythonListView.cpp

Lines changed: 24 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -77,42 +77,44 @@ PyTypeObject ue_PySPythonListViewType = {
7777
};
7878

7979
static int ue_py_spython_list_view_init(ue_PySPythonListView *self, PyObject *args, PyObject *kwargs) {
80-
PyObject *py_iterable;
81-
PyObject *py_callable;
82-
if (!PyArg_ParseTuple(args, "OO", &py_iterable, &py_callable)) {
83-
return -1;
84-
}
8580

86-
py_iterable = PyObject_GetIter(py_iterable);
81+
ue_py_slate_setup_farguments(SPythonListView);
8782

88-
if (!py_iterable || !PyIter_Check(py_iterable)) {
89-
PyErr_SetString(PyExc_Exception, "argument is not an iterable");
83+
// first of all check for values
84+
PyObject *values = ue_py_dict_get_item(kwargs, "list_items_source");
85+
if (!values) {
86+
PyErr_SetString(PyExc_Exception, "you must specify list items");
9087
return -1;
9188
}
9289

93-
if (!PyCallable_Check(py_callable)) {
94-
PyErr_SetString(PyExc_Exception, "argument is not a callable");
90+
values = PyObject_GetIter(values);
91+
if (!values) {
92+
PyErr_SetString(PyExc_Exception, "values field is not an iterable");
9593
return -1;
9694
}
9795

98-
// this will be destroyed by the SPythonListView
99-
auto items = new TArray<TSharedPtr<FPythonItem>>();
100-
101-
while (PyObject *item = PyIter_Next(py_iterable)) {
96+
TArray<TSharedPtr<FPythonItem>> *items = new TArray<TSharedPtr<FPythonItem>>();
97+
while (PyObject *item = PyIter_Next(values)) {
10298
Py_INCREF(item);
99+
// keep track of items
100+
self->s_list_view.s_table_view_base.s_compound_widget.s_widget.py_refs.Add(item);
103101
items->Add(TSharedPtr<FPythonItem>(new FPythonItem(item)));
104102
}
103+
Py_DECREF(values);
105104

106-
Py_DECREF(py_iterable);
105+
arguments.ListItemsSource(items);
107106

108-
SPythonListView::FOnGenerateRow handler;
109-
UPythonSlateDelegate *py_delegate = NewObject<UPythonSlateDelegate>();
110-
py_delegate->SetPyCallable(py_callable);
111-
py_delegate->AddToRoot();
112-
handler.BindUObject(py_delegate, &UPythonSlateDelegate::GenerateRow);
113-
self->s_list_view.s_table_view_base.s_compound_widget.s_widget.delegates.Add(py_delegate);
107+
ue_py_slate_farguments_optional_enum("allow_overscroll", AllowOverscroll, EAllowOverscroll);
108+
ue_py_slate_farguments_optional_bool("clear_selection_on_click", ClearSelectionOnClick);
109+
ue_py_slate_farguments_optional_enum("consume_mouse_wheel", ConsumeMouseWheel, EConsumeMouseWheel);
110+
ue_py_slate_farguments_optional_bool("handle_gamepad_events", HandleGamepadEvents);
111+
ue_py_slate_farguments_float("item_height", ItemHeight);
112+
ue_py_slate_farguments_event("on_generate_row", OnGenerateRow, TSlateDelegates<TSharedPtr<FPythonItem>>::FOnGenerateRow, GenerateRow);
113+
ue_py_slate_farguments_event("on_selection_changed", OnSelectionChanged, TSlateDelegates<TSharedPtr<FPythonItem>>::FOnSelectionChanged, OnSelectionChanged);
114+
ue_py_slate_farguments_enum("selection_mode", SelectionMode, ESelectionMode::Type);
115+
ue_py_slate_farguments_optional_float("wheel_scroll_multiplier", WheelScrollMultiplier);
114116

115-
new (&self->s_list_view.s_table_view_base.s_compound_widget.s_widget.s_widget) TSharedRef<SWidget>(SNew(SPythonListView).ListItemsSource(items).OnGenerateRow(handler));
117+
ue_py_snew(SPythonListView, s_list_view.s_table_view_base.s_compound_widget.s_widget);
116118
return 0;
117119
}
118120

Source/UnrealEnginePython/Private/Slate/UEPySPythonTreeView.cpp

Lines changed: 24 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -45,55 +45,44 @@ PyTypeObject ue_PySPythonTreeViewType = {
4545
};
4646

4747
static int ue_py_spython_tree_view_init(ue_PySPythonTreeView *self, PyObject *args, PyObject *kwargs) {
48-
PyObject *py_iterable;
49-
PyObject *py_callable;
50-
PyObject *py_callable_children;
51-
if (!PyArg_ParseTuple(args, "OOO", &py_iterable, &py_callable, &py_callable_children)) {
52-
return -1;
53-
}
5448

55-
py_iterable = PyObject_GetIter(py_iterable);
49+
ue_py_slate_setup_farguments(SPythonTreeView);
5650

57-
if (!py_iterable || !PyIter_Check(py_iterable)) {
58-
PyErr_SetString(PyExc_Exception, "argument is not an iterable");
51+
// first of all check for values
52+
PyObject *values = ue_py_dict_get_item(kwargs, "tree_items_source");
53+
if (!values) {
54+
PyErr_SetString(PyExc_Exception, "you must specify tree items");
5955
return -1;
6056
}
6157

62-
if (!PyCallable_Check(py_callable)) {
63-
PyErr_SetString(PyExc_Exception, "argument is not a callable");
58+
values = PyObject_GetIter(values);
59+
if (!values) {
60+
PyErr_SetString(PyExc_Exception, "values field is not an iterable");
6461
return -1;
6562
}
6663

67-
if (!PyCallable_Check(py_callable_children)) {
68-
PyErr_SetString(PyExc_Exception, "argument is not a callable");
69-
return -1;
70-
}
71-
72-
// this will be destroyed by the SPythonListView
73-
auto items = new TArray<TSharedPtr<FPythonItem>>();
74-
75-
while (PyObject *item = PyIter_Next(py_iterable)) {
64+
TArray<TSharedPtr<FPythonItem>> *items = new TArray<TSharedPtr<FPythonItem>>();
65+
while (PyObject *item = PyIter_Next(values)) {
7666
Py_INCREF(item);
67+
// keep track of items
68+
self->s_tree_view.s_list_view.s_table_view_base.s_compound_widget.s_widget.py_refs.Add(item);
7769
items->Add(TSharedPtr<FPythonItem>(new FPythonItem(item)));
7870
}
71+
Py_DECREF(values);
7972

80-
Py_DECREF(py_iterable);
81-
82-
SPythonTreeView::FOnGenerateRow handler;
83-
UPythonSlateDelegate *py_delegate = NewObject<UPythonSlateDelegate>();
84-
py_delegate->SetPyCallable(py_callable);
85-
py_delegate->AddToRoot();
86-
handler.BindUObject(py_delegate, &UPythonSlateDelegate::GenerateRow);
87-
self->s_tree_view.s_list_view.s_table_view_base.s_compound_widget.s_widget.delegates.Add(py_delegate);
73+
arguments.TreeItemsSource(items);
8874

89-
SPythonTreeView::FOnGetChildren handler_children;
90-
UPythonSlateDelegate *py_delegate_children = NewObject<UPythonSlateDelegate>();
91-
py_delegate_children->SetPyCallable(py_callable_children);
92-
py_delegate_children->AddToRoot();
93-
handler_children.BindUObject(py_delegate_children, &UPythonSlateDelegate::GetChildren);
94-
self->s_tree_view.s_list_view.s_table_view_base.s_compound_widget.s_widget.delegates.Add(py_delegate);
75+
ue_py_slate_farguments_optional_enum("allow_overscroll", AllowOverscroll, EAllowOverscroll);
76+
ue_py_slate_farguments_optional_bool("clear_selection_on_click", ClearSelectionOnClick);
77+
ue_py_slate_farguments_optional_enum("consume_mouse_wheel", ConsumeMouseWheel, EConsumeMouseWheel);
78+
ue_py_slate_farguments_float("item_height", ItemHeight);
79+
ue_py_slate_farguments_event("on_generate_row", OnGenerateRow, TSlateDelegates<TSharedPtr<FPythonItem>>::FOnGenerateRow, GenerateRow);
80+
ue_py_slate_farguments_event("on_selection_changed", OnSelectionChanged, TSlateDelegates<TSharedPtr<FPythonItem>>::FOnSelectionChanged, OnSelectionChanged);
81+
ue_py_slate_farguments_enum("selection_mode", SelectionMode, ESelectionMode::Type);
82+
ue_py_slate_farguments_optional_float("wheel_scroll_multiplier", WheelScrollMultiplier);
83+
ue_py_slate_farguments_event("on_get_children", OnGetChildren, TSlateDelegates<TSharedPtr<FPythonItem>>::FOnGetChildren, GetChildren);
9584

96-
new(&self->s_tree_view.s_list_view.s_table_view_base.s_compound_widget.s_widget.s_widget) TSharedRef<SWidget>(SNew(SPythonTreeView).TreeItemsSource(items).OnGenerateRow(handler).OnGetChildren(handler_children));
85+
ue_py_snew(SPythonTreeView, s_tree_view.s_list_view.s_table_view_base.s_compound_widget.s_widget);
9786
return 0;
9887
}
9988

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
2+
#include "UnrealEnginePythonPrivatePCH.h"
3+
4+
#include "UEPySScrollBox.h"
5+
6+
7+
#define sw_scroll_box StaticCastSharedRef<SScrollBox>(self->s_compound_widget.s_widget.s_widget)
8+
9+
static PyObject *py_ue_sscroll_box_add_slot(ue_PySScrollBox *self, PyObject * args, PyObject *kwargs) {
10+
PyObject *py_content;
11+
int h_align = 0;
12+
int v_align = 0;
13+
14+
char *kwlist[] = { (char *)"widget",
15+
(char *)"h_align",
16+
(char *)"v_align",
17+
nullptr };
18+
19+
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|ii:add_slot", kwlist,
20+
&py_content,
21+
&h_align,
22+
&v_align)) {
23+
return NULL;
24+
}
25+
26+
ue_PySWidget *py_swidget = py_ue_is_swidget(py_content);
27+
if (!py_swidget) {
28+
return PyErr_Format(PyExc_Exception, "argument is not a SWidget");
29+
}
30+
31+
Py_INCREF(py_swidget);
32+
self->s_compound_widget.s_widget.py_swidget_slots.Add(py_swidget);
33+
34+
SScrollBox::FSlot &fslot = sw_scroll_box->AddSlot();
35+
fslot.AttachWidget(py_swidget->s_widget->AsShared());
36+
fslot.HAlign((EHorizontalAlignment)h_align);
37+
fslot.VAlign((EVerticalAlignment)v_align);
38+
39+
Py_INCREF(self);
40+
return (PyObject *)self;
41+
}
42+
43+
static PyMethodDef ue_PySScrollBox_methods[] = {
44+
#pragma warning(suppress: 4191)
45+
{ "add_slot", (PyCFunction)py_ue_sscroll_box_add_slot, METH_VARARGS | METH_KEYWORDS, "" },
46+
{ NULL } /* Sentinel */
47+
};
48+
49+
PyTypeObject ue_PySScrollBoxType = {
50+
PyVarObject_HEAD_INIT(NULL, 0)
51+
"unreal_engine.SScrollBox", /* tp_name */
52+
sizeof(ue_PySNumericEntryBox), /* tp_basicsize */
53+
0, /* tp_itemsize */
54+
0, /* tp_dealloc */
55+
0, /* tp_print */
56+
0, /* tp_getattr */
57+
0, /* tp_setattr */
58+
0, /* tp_reserved */
59+
0, /* tp_repr */
60+
0, /* tp_as_number */
61+
0, /* tp_as_sequence */
62+
0, /* tp_as_mapping */
63+
0, /* tp_hash */
64+
0, /* tp_call */
65+
0, /* tp_str */
66+
0, /* tp_getattro */
67+
0, /* tp_setattro */
68+
0, /* tp_as_buffer */
69+
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
70+
"Unreal Engine SScrollBox", /* tp_doc */
71+
0, /* tp_traverse */
72+
0, /* tp_clear */
73+
0, /* tp_richcompare */
74+
0, /* tp_weaklistoffset */
75+
0, /* tp_iter */
76+
0, /* tp_iternext */
77+
ue_PySScrollBox_methods, /* tp_methods */
78+
};
79+
80+
static int ue_py_sscroll_box_init(ue_PySScrollBox *self, PyObject *args, PyObject *kwargs) {
81+
82+
ue_py_slate_setup_farguments(SScrollBox);
83+
84+
ue_py_slate_farguments_optional_enum("allow_overscroll", AllowOverscroll, EAllowOverscroll);
85+
ue_py_slate_farguments_optional_enum("consume_mouse_wheel", ConsumeMouseWheel, EConsumeMouseWheel);
86+
ue_py_slate_farguments_optional_enum("orientation", Orientation, EOrientation);
87+
ue_py_slate_farguments_optional_bool("scroll_bar_always_visible", ScrollBarAlwaysVisible);
88+
ue_py_slate_farguments_optional_struct_ptr("scroll_bar_style", ScrollBarStyle, FScrollBarStyle);
89+
ue_py_slate_farguments_optional_fvector2d("scroll_bar_thickness", ScrollBarThickness);
90+
ue_py_slate_farguments_optional_struct_ptr("style", Style, FScrollBoxStyle);
91+
92+
ue_py_snew(SScrollBox, s_compound_widget.s_widget);
93+
94+
return 0;
95+
}
96+
97+
void ue_python_init_sscroll_box(PyObject *ue_module) {
98+
99+
ue_PySScrollBoxType.tp_init = (initproc)ue_py_sscroll_box_init;
100+
101+
ue_PySScrollBoxType.tp_base = &ue_PySCompoundWidgetType;
102+
103+
if (PyType_Ready(&ue_PySScrollBoxType) < 0)
104+
return;
105+
106+
Py_INCREF(&ue_PySScrollBoxType);
107+
PyModule_AddObject(ue_module, "SScrollBox", (PyObject *)&ue_PySScrollBoxType);
108+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#pragma once
2+
3+
#include "UnrealEnginePython.h"
4+
5+
#include "UEPySCompoundWidget.h"
6+
7+
#include "Runtime/Slate/Public/Widgets/Layout/SScrollBox.h"
8+
9+
extern PyTypeObject ue_PySScrollBoxType;
10+
11+
typedef struct {
12+
ue_PySCompoundWidget s_compound_widget;
13+
/* Type-specific fields go here. */
14+
} ue_PySScrollBox;
15+
16+
void ue_python_init_sscroll_box(PyObject *);

Source/UnrealEnginePython/Private/Slate/UEPySlate.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -458,7 +458,7 @@ TSharedRef<ITableRow> UPythonSlateDelegate::GenerateRow(TSharedPtr<FPythonItem>
458458
}
459459
ue_PySWidget *s_widget = py_ue_is_swidget(ret);
460460
if (!s_widget) {
461-
UE_LOG(LogPython, Error, TEXT("python callable did not return a SDockTab object"));
461+
UE_LOG(LogPython, Error, TEXT("python callable did not return a SWidget"));
462462
return SNew(STableRow<TSharedPtr<FPythonItem>>, OwnerTable);
463463
}
464464

@@ -476,6 +476,7 @@ void UPythonSlateDelegate::GetChildren(TSharedPtr<FPythonItem> InItem, TArray<TS
476476
UE_LOG(LogPython, Error, TEXT("returned value is not iterable"));
477477
Py_XDECREF(py_iterable);
478478
Py_DECREF(ret);
479+
return;
479480
}
480481

481482
while (PyObject *item = PyIter_Next(py_iterable)) {
@@ -563,6 +564,7 @@ void ue_python_init_slate(PyObject *module) {
563564
ue_python_init_svector_input_box(module);
564565
ue_python_init_srotator_input_box(module);
565566
ue_python_init_spython_combo_box(module);
567+
ue_python_init_sscroll_box(module);
566568

567569

568570
#if WITH_EDITOR

Source/UnrealEnginePython/Private/Slate/UEPySlate.h

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
#include "UEPySVectorInputBox.h"
4949
#include "UEPySRotatorInputBox.h"
5050
#include "UEPySPythonComboBox.h"
51+
#include "UEPySScrollBox.h"
5152

5253

5354

@@ -249,28 +250,30 @@ ue_PySWidget *ue_py_get_swidget(TSharedRef<SWidget> s_widget);
249250
}
250251

251252

252-
253-
254253
#define ue_py_slate_farguments_optional_fvector2d(param, attribute) { PyObject *value = ue_py_dict_get_item(kwargs, param);\
255-
if (value) {\
256-
if (PyTuple_Check(value)) {\
257-
if (PyTuple_Size(value) == 2) {\
258-
PyObject *py_first = PyTuple_GetItem(value, 0);\
259-
PyObject *py_second = PyTuple_GetItem(value, 1);\
260-
if (PyNumber_Check(py_first)) {\
261-
PyObject *py_x = PyNumber_Float(py_first);\
262-
PyObject *py_y = PyNumber_Float(py_second);\
263-
arguments.attribute(FVector2D(PyFloat_AsDouble(py_x), PyFloat_AsDouble(py_y)));\
264-
Py_DECREF(py_x);\
265-
Py_DECREF(py_y);\
254+
if (value) {\
255+
if (PyTuple_Check(value)) {\
256+
if (PyTuple_Size(value) == 2) {\
257+
PyObject *py_first = PyTuple_GetItem(value, 0);\
258+
PyObject *py_second = PyTuple_GetItem(value, 1);\
259+
if (PyNumber_Check(py_first)) {\
260+
PyObject *py_x = PyNumber_Float(py_first);\
261+
PyObject *py_y = PyNumber_Float(py_second);\
262+
arguments.attribute(FVector2D(PyFloat_AsDouble(py_x), PyFloat_AsDouble(py_y)));\
263+
Py_DECREF(py_x);\
264+
Py_DECREF(py_y);\
265+
}\
266+
}\
267+
else {\
268+
PyErr_SetString(PyExc_TypeError, "unsupported type for attribute " param); \
269+
return -1;\
266270
}\
267271
}\
268-
}\
269-
else {\
272+
else {\
270273
PyErr_SetString(PyExc_TypeError, "unsupported type for attribute " param); \
271274
return -1;\
275+
}\
272276
}\
273-
}\
274277
}
275278

276279

0 commit comments

Comments
 (0)