Skip to content

Commit 2e85560

Browse files
author
Roberto De Ioris
committed
added automatic property widgets, fixed arrayproperty in subclassing advanced api
1 parent 0955dd0 commit 2e85560

File tree

5 files changed

+138
-9
lines changed

5 files changed

+138
-9
lines changed

Source/UnrealEnginePython/Private/Slate/UEPySWindow.cpp

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11

22
#include "UnrealEnginePythonPrivatePCH.h"
33

4+
#if WITH_EDITOR
5+
#include "Editor/MainFrame/Public/Interfaces/IMainFrameModule.h"
6+
#endif
7+
48
#include "UEPySWindow.h"
59

610
#define sw_window StaticCastSharedRef<SWindow>(self->s_compound_widget.s_widget.s_widget)
@@ -41,7 +45,7 @@ static PyObject *py_ue_swindow_set_content(ue_PySWindow *self, PyObject * args)
4145
if (!py_swidget) {
4246
return PyErr_Format(PyExc_Exception, "argument is not a SWidget");
4347
}
44-
48+
4549
Py_XDECREF(self->s_compound_widget.s_widget.py_swidget_content);
4650
Py_INCREF(py_swidget);
4751
self->s_compound_widget.s_widget.py_swidget_content = py_swidget;
@@ -73,13 +77,35 @@ static PyObject *py_ue_swindow_get_handle(ue_PySWindow *self, PyObject * args) {
7377
return PyLong_FromLongLong((long long)sw_window->GetNativeWindow()->GetOSWindowHandle());
7478
}
7579

80+
static PyObject *py_ue_swindow_request_destroy(ue_PySWindow *self, PyObject * args) {
81+
82+
sw_window->RequestDestroyWindow();
83+
84+
Py_RETURN_NONE;
85+
}
86+
87+
#if WITH_EDITOR
88+
static PyObject *py_ue_swindow_add_modal(ue_PySWindow *self, PyObject * args) {
89+
TSharedPtr<SWindow> parent_window;
90+
if (FModuleManager::Get().IsModuleLoaded("MainFrame")) {
91+
parent_window = FModuleManager::LoadModuleChecked<IMainFrameModule>("MainFrame").GetParentWindow();
92+
}
93+
FSlateApplication::Get().AddModalWindow(StaticCastSharedRef<SWindow>(sw_window->AsShared()), parent_window, false);
94+
Py_RETURN_NONE;
95+
}
96+
#endif
97+
7698
static PyMethodDef ue_PySWindow_methods[] = {
7799
{ "set_title", (PyCFunction)py_ue_swindow_set_title, METH_VARARGS, "" },
78100
{ "set_sizing_rule", (PyCFunction)py_ue_swindow_set_sizing_rule, METH_VARARGS, "" },
79101
{ "resize", (PyCFunction)py_ue_swindow_resize, METH_VARARGS, "" },
80102
{ "set_client_size", (PyCFunction)py_ue_swindow_resize, METH_VARARGS, "" },
81103
{ "set_content", (PyCFunction)py_ue_swindow_set_content, METH_VARARGS, "" },
82104
{ "get_handle", (PyCFunction)py_ue_swindow_get_handle, METH_VARARGS, "" },
105+
{ "request_destroy", (PyCFunction)py_ue_swindow_request_destroy, METH_VARARGS, "" },
106+
#if WITH_EDITOR
107+
{ "add_modal", (PyCFunction)py_ue_swindow_add_modal, METH_VARARGS, "" },
108+
#endif
83109
{ NULL } /* Sentinel */
84110
};
85111

@@ -115,7 +141,7 @@ PyTypeObject ue_PySWindowType = {
115141
};
116142

117143
static int ue_py_swindow_init(ue_PySWindow *self, PyObject *args, PyObject *kwargs) {
118-
144+
119145
ue_py_slate_setup_farguments(SWindow);
120146

121147
ue_py_slate_farguments_optional_bool("activate_when_first_shown", ActivateWhenFirstShown);
@@ -158,6 +184,14 @@ static int ue_py_swindow_init(ue_PySWindow *self, PyObject *args, PyObject *kwar
158184

159185
ue_py_snew(SWindow, s_compound_widget.s_widget);
160186

187+
#if WITH_EDITOR
188+
// is it a modal window ?
189+
PyObject *is_modal = ue_py_dict_get_item(kwargs, "modal");
190+
if (is_modal && PyObject_IsTrue(is_modal)) {
191+
return 0;
192+
}
193+
#endif
194+
161195
FSlateApplication::Get().AddWindow(StaticCastSharedRef<SWindow>(sw_window->AsShared()), true);
162196

163197
return 0;

Source/UnrealEnginePython/Private/Slate/UEPySlate.cpp

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
#include "Editor/Persona/Public/PersonaModule.h"
88
#include "Editor/AnimationEditor/Public/IAnimationEditorModule.h"
99
#include "Editor/StaticMeshEditor/Public/StaticMeshEditorModule.h"
10+
#include "Editor/PropertyEditor/Public/PropertyEditorModule.h"
11+
#include "Editor/PropertyEditor/Public/ISinglePropertyView.h"
1012
#endif
1113

1214
#include "Runtime/Slate/Public/Framework/Commands/UICommandList.h"
@@ -194,6 +196,8 @@ TSharedPtr<SWidget> UPythonSlateDelegate::OnGetAssetContextMenu(const TArray<FAs
194196
Py_DECREF(ret);
195197
return value;
196198
}
199+
200+
197201
#endif
198202

199203
TSharedRef<SWidget> UPythonSlateDelegate::OnGenerateWidget(TSharedPtr<FPythonItem> py_item) {
@@ -699,6 +703,73 @@ class FPythonSlateCommands : public TCommands<FPythonSlateCommands>
699703
};
700704

701705
#if WITH_EDITOR
706+
707+
PyObject *py_unreal_engine_create_detail_view(PyObject *self, PyObject * args, PyObject *kwargs) {
708+
709+
PyObject *py_object;
710+
PyObject *py_allow_search = nullptr;
711+
712+
char *kwlist[] = {
713+
(char *)"uobject",
714+
(char *)"allow_search",
715+
nullptr };
716+
717+
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:create_detail_view", kwlist,
718+
&py_object, &py_allow_search)) {
719+
return nullptr;
720+
}
721+
722+
UObject *u_object = ue_py_check_type<UObject>(py_object);
723+
if (!u_object) {
724+
return PyErr_Format(PyExc_Exception, "argument is not a UObject");
725+
}
726+
727+
FPropertyEditorModule& PropertyEditorModule = FModuleManager::GetModuleChecked<FPropertyEditorModule>("PropertyEditor");
728+
FDetailsViewArgs view_args;
729+
view_args.bAllowSearch = (py_allow_search && PyObject_IsTrue(py_allow_search));
730+
731+
TSharedPtr<IDetailsView> view = PropertyEditorModule.CreateDetailView(view_args);
732+
view->SetObject(u_object);
733+
734+
return (PyObject *)py_ue_new_swidget<ue_PySWidget>(view->AsShared(), &ue_PySWidgetType);
735+
}
736+
737+
PyObject *py_unreal_engine_create_property_view(PyObject *self, PyObject * args, PyObject *kwargs) {
738+
739+
PyObject *py_object;
740+
char *name;
741+
char *name_override = nullptr;
742+
743+
char *kwlist[] = {
744+
(char*)"uobject",
745+
(char *)"name",
746+
(char *)"name_override",
747+
nullptr };
748+
749+
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Os|s:create_property_view", kwlist,
750+
&py_object, &name, &name_override)) {
751+
return nullptr;
752+
}
753+
754+
UObject *u_object = ue_py_check_type<UObject>(py_object);
755+
if (!u_object) {
756+
return PyErr_Format(PyExc_Exception, "argument is not a UObject");
757+
}
758+
759+
FPropertyEditorModule& PropertyEditorModule = FModuleManager::GetModuleChecked<FPropertyEditorModule>("PropertyEditor");
760+
FSinglePropertyParams params;
761+
if (name_override)
762+
params.NameOverride = FText::FromString(UTF8_TO_TCHAR(name_override));
763+
764+
auto view_widget = PropertyEditorModule.CreateSingleProperty(u_object, FName(name), params);
765+
766+
if (!view_widget.IsValid())
767+
return PyErr_Format(PyExc_Exception, "unable to create SingleProperty widget");
768+
769+
return (PyObject *)py_ue_new_swidget<ue_PySWidget>(view_widget->AsShared(), &ue_PySWidgetType);
770+
}
771+
772+
702773
PyObject *py_unreal_engine_add_menu_extension(PyObject * self, PyObject * args) {
703774

704775
char *command_name;

Source/UnrealEnginePython/Private/Slate/UEPySlate.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,8 @@ PyObject *py_unreal_engine_get_editor_window(PyObject *, PyObject *);
8787
PyObject *py_unreal_engine_add_menu_extension(PyObject *, PyObject *);
8888
PyObject *py_unreal_engine_add_menu_bar_extension(PyObject *, PyObject *);
8989
PyObject *py_unreal_engine_add_tool_bar_extension(PyObject *, PyObject *);
90+
PyObject *py_unreal_engine_create_detail_view(PyObject *, PyObject *, PyObject *);
91+
PyObject *py_unreal_engine_create_property_view(PyObject *, PyObject *, PyObject *);
9092
#endif
9193

9294
PyObject *py_unreal_engine_invoke_tab(PyObject *, PyObject *);

Source/UnrealEnginePython/Private/UEPyModule.cpp

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,11 @@ static PyMethodDef unreal_engine_methods[] = {
176176
{ "add_menu_bar_extension", py_unreal_engine_add_menu_bar_extension, METH_VARARGS, "" },
177177
{ "add_tool_bar_extension", py_unreal_engine_add_tool_bar_extension, METH_VARARGS, "" },
178178

179+
#pragma warning(suppress: 4191)
180+
{ "create_detail_view", (PyCFunction)py_unreal_engine_create_detail_view, METH_VARARGS | METH_KEYWORDS, "" },
181+
#pragma warning(suppress: 4191)
182+
{ "create_property_view", (PyCFunction)py_unreal_engine_create_property_view, METH_VARARGS | METH_KEYWORDS, "" },
183+
179184
{ "open_editor_for_asset", py_unreal_engine_open_editor_for_asset, METH_VARARGS, "" },
180185
{ "close_editor_for_asset", py_unreal_engine_close_editor_for_asset, METH_VARARGS, "" },
181186
{ "close_all_asset_editors", py_unreal_engine_close_all_asset_editors, METH_VARARGS, "" },
@@ -1162,7 +1167,7 @@ static int unreal_engine_py_init(ue_PyUObject *self, PyObject *args, PyObject *k
11621167
if (PyList_Size(value) == 1) {
11631168
PyObject *first_item = PyList_GetItem(value, 0);
11641169
if (ue_is_pyuobject(first_item)) {
1165-
ue_PyUObject *py_obj = (ue_PyUObject *)value;
1170+
ue_PyUObject *py_obj = (ue_PyUObject *)first_item;
11661171
if (py_obj->ue_object->IsA<UClass>()) {
11671172
UClass *p_class = (UClass *)py_obj->ue_object;
11681173
if (p_class->IsChildOf<UProperty>()) {
@@ -1172,6 +1177,13 @@ static int unreal_engine_py_init(ue_PyUObject *self, PyObject *args, PyObject *k
11721177
}
11731178
prop_added = true;
11741179
}
1180+
else {
1181+
if (!py_ue_add_property(self, Py_BuildValue("([O]sO)", (PyObject *)ue_get_python_wrapper(UObjectProperty::StaticClass()), class_key, first_item))) {
1182+
unreal_engine_py_log_error();
1183+
return -1;
1184+
}
1185+
prop_added = true;
1186+
}
11751187
}
11761188
}
11771189
}
@@ -1535,7 +1547,7 @@ void unreal_engine_py_log_error() {
15351547
}
15361548

15371549
PyErr_Clear();
1538-
}
1550+
}
15391551

15401552
// retrieve a UWorld from a generic UObject (if possible)
15411553
UWorld *ue_get_uworld(ue_PyUObject *py_obj) {

Source/UnrealEnginePython/Private/UObject/UEPyObject.cpp

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -615,13 +615,13 @@ PyObject *py_ue_get_uproperty(ue_PyUObject *self, PyObject * args) {
615615
UProperty *u_property = u_struct->FindPropertyByName(FName(UTF8_TO_TCHAR(property_name)));
616616
if (!u_property)
617617
return PyErr_Format(PyExc_Exception, "unable to find property %s", property_name);
618-
618+
619619
ue_PyUObject *ret = ue_get_python_wrapper(u_property);
620620
if (!ret)
621621
return PyErr_Format(PyExc_Exception, "PyUObject is in invalid state");
622622
Py_INCREF(ret);
623623
return (PyObject *)ret;
624-
624+
625625
}
626626

627627
PyObject *py_ue_has_property(ue_PyUObject *self, PyObject * args) {
@@ -836,6 +836,7 @@ PyObject *py_ue_add_property(ue_PyUObject * self, PyObject * args) {
836836
}
837837
}
838838

839+
839840
if (!scope) {
840841
return PyErr_Format(PyExc_Exception, "argument is not a UObject or a single item list");
841842
}
@@ -859,6 +860,12 @@ PyObject *py_ue_add_property(ue_PyUObject * self, PyObject * args) {
859860
UArrayProperty *u_array = (UArrayProperty *)scope;
860861
u_array->AddCppProperty(u_property);
861862
u_property->SetPropertyFlags(flags);
863+
if (u_property->GetClass() == UObjectProperty::StaticClass()) {
864+
UObjectProperty *obj_prop = (UObjectProperty *)u_property;
865+
if (u_prop_class) {
866+
obj_prop->SetPropertyClass(u_prop_class);
867+
}
868+
}
862869
u_property = u_array;
863870
}
864871

@@ -879,9 +886,12 @@ PyObject *py_ue_add_property(ue_PyUObject * self, PyObject * args) {
879886
}
880887

881888
else if (u_class == UObjectProperty::StaticClass()) {
882-
UObjectProperty *obj_prop = (UObjectProperty *)u_property;
883-
if (u_prop_class) {
884-
obj_prop->SetPropertyClass(u_prop_class);
889+
// ensure it is not an arry as we have already managed it !
890+
if (!is_array) {
891+
UObjectProperty *obj_prop = (UObjectProperty *)u_property;
892+
if (u_prop_class) {
893+
obj_prop->SetPropertyClass(u_prop_class);
894+
}
885895
}
886896
}
887897

0 commit comments

Comments
 (0)