Skip to content

Commit 9b20b3d

Browse files
committed
Merge branch 'pr/16'
2 parents d6cf725 + 038192d commit 9b20b3d

23 files changed

Lines changed: 624 additions & 358 deletions

‎.gitignore‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,8 @@ Binaries/
9292

9393
#don't update this file again
9494
Content/Scripts/upyconfig.json
95+
Intermediate/
96+
9597
python35/
9698
python27/
9799
*.un~

‎README.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ Once the plugin is installed and enabled, you get access to the 'PythonConsole'
3636

3737
All of the exposed engine features are under the 'unreal_engine' virtual module (it is completely coded in c into the plugin, so do not expect to run 'import unreal_engine' from a standard python shell)
3838

39-
The currently supported Unreal Engine versions are 4.12, 4.13, 4.14, 4.15, 4.16, 4.17, 4.18, 4.19, 4.20 and 4.21
39+
The minimal supported Unreal Engine version is 4.12, while the latest is 4.23
4040

4141
We support official python.org releases as well as IntelPython and Anaconda distributions.
4242

‎Source/PythonAutomation/Public/PythonAutomationModule.h‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,11 @@
33
#pragma once
44

55
#include "CoreMinimal.h"
6+
#if ENGINE_MAJOR_VERSION==4 && ENGINE_MINOR_VERSION>=22
7+
#include "Modules/ModuleInterface.h"
8+
#else
69
#include "ModuleInterface.h"
10+
#endif
711

812
class FPythonAutomationModule : public IModuleInterface
913
{

‎Source/UnrealEnginePython/Private/Blueprint/UEPyEdGraph.cpp‎

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,127 @@ PyObject *py_ue_graph_add_node(ue_PyUObject * self, PyObject * args)
381381
Py_RETURN_UOBJECT(node);
382382
}
383383

384+
PyObject *py_ue_graph_remove_node(ue_PyUObject * self, PyObject * args)
385+
{
386+
387+
ue_py_check(self);
388+
389+
PyObject *py_node_class;
390+
int x = 0;
391+
int y = 0;
392+
393+
char *metadata = nullptr;
394+
PyObject *py_data = nullptr;
395+
396+
if (!PyArg_ParseTuple(args, "O|iisO:graph_remove_node", &py_node_class, &x, &y, &metadata, &py_data))
397+
{
398+
return nullptr;
399+
}
400+
401+
UEdGraph *graph = ue_py_check_type<UEdGraph>(self);
402+
if (!graph)
403+
return PyErr_Format(PyExc_Exception, "uobject is not a UEdGraph");
404+
405+
UObject *u_obj = ue_py_check_type<UObject>(py_node_class);
406+
if (!u_obj)
407+
return PyErr_Format(PyExc_Exception, "argument is not a UObject");
408+
409+
UEdGraphNode *node = nullptr;
410+
411+
if (UClass *u_class = Cast<UClass>(u_obj))
412+
{
413+
if (!u_class->IsChildOf<UEdGraphNode>())
414+
{
415+
return PyErr_Format(PyExc_Exception, "argument is not a child of UEdGraphNode");
416+
}
417+
node = NewObject<UEdGraphNode>(graph, u_class);
418+
node->PostLoad();
419+
}
420+
else
421+
{
422+
node = Cast<UEdGraphNode>(u_obj);
423+
if (node)
424+
{
425+
if (node->GetOuter() != graph)
426+
427+
node->Rename(*node->GetName(), graph);
428+
}
429+
}
430+
431+
if (!node)
432+
return PyErr_Format(PyExc_Exception, "argument is not a supported type");
433+
434+
graph->RemoveNode(node);
435+
436+
if (UBlueprint *bp = Cast<UBlueprint>(node->GetGraph()->GetOuter()))
437+
{
438+
FBlueprintEditorUtils::MarkBlueprintAsStructurallyModified(bp);
439+
}
440+
441+
Py_RETURN_NONE;
442+
}
443+
444+
PyObject *py_ue_graph_reconstruct_node(ue_PyUObject * self, PyObject * args)
445+
{
446+
447+
ue_py_check(self);
448+
449+
PyObject *py_node_class;
450+
int x = 0;
451+
int y = 0;
452+
453+
char *metadata = nullptr;
454+
PyObject *py_data = nullptr;
455+
456+
if (!PyArg_ParseTuple(args, "O|iisO:graph_reconstruct_node", &py_node_class, &x, &y, &metadata, &py_data))
457+
{
458+
return nullptr;
459+
}
460+
461+
UEdGraph *graph = ue_py_check_type<UEdGraph>(self);
462+
if (!graph)
463+
return PyErr_Format(PyExc_Exception, "uobject is not a UEdGraph");
464+
465+
UObject *u_obj = ue_py_check_type<UObject>(py_node_class);
466+
if (!u_obj)
467+
return PyErr_Format(PyExc_Exception, "argument is not a UObject");
468+
469+
UEdGraphNode *node = nullptr;
470+
471+
if (UClass *u_class = Cast<UClass>(u_obj))
472+
{
473+
if (!u_class->IsChildOf<UEdGraphNode>())
474+
{
475+
return PyErr_Format(PyExc_Exception, "argument is not a child of UEdGraphNode");
476+
}
477+
node = NewObject<UEdGraphNode>(graph, u_class);
478+
node->PostLoad();
479+
}
480+
else
481+
{
482+
node = Cast<UEdGraphNode>(u_obj);
483+
if (node)
484+
{
485+
if (node->GetOuter() != graph)
486+
487+
node->Rename(*node->GetName(), graph);
488+
}
489+
}
490+
491+
if (!node)
492+
return PyErr_Format(PyExc_Exception, "argument is not a supported type");
493+
494+
//graph->RemoveNode(node);
495+
node->ReconstructNode();
496+
497+
if (UBlueprint *bp = Cast<UBlueprint>(node->GetGraph()->GetOuter()))
498+
{
499+
FBlueprintEditorUtils::MarkBlueprintAsStructurallyModified(bp);
500+
}
501+
502+
Py_RETURN_NONE;
503+
}
504+
384505
PyObject *py_ue_graph_add_node_dynamic_cast(ue_PyUObject * self, PyObject * args)
385506
{
386507

‎Source/UnrealEnginePython/Private/Blueprint/UEPyEdGraph.h‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ PyObject *py_ue_graph_add_node(ue_PyUObject *, PyObject *);
1616
PyObject *py_ue_graph_add_node_dynamic_cast(ue_PyUObject *, PyObject *);
1717
PyObject *py_ue_graph_add_node_event(ue_PyUObject *, PyObject *);
1818

19+
PyObject *py_ue_graph_reconstruct_node(ue_PyUObject *, PyObject *);
20+
PyObject *py_ue_graph_remove_node(ue_PyUObject *, PyObject *);
21+
1922
PyObject *py_ue_graph_get_good_place_for_new_node(ue_PyUObject *, PyObject *);
2023

2124
PyObject *py_ue_node_pins(ue_PyUObject *, PyObject *);

‎Source/UnrealEnginePython/Private/PythonHouseKeeper.cpp‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
#pragma once
21

32
#include "PythonHouseKeeper.h"
43

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

Lines changed: 42 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22

33
#include "Wrappers/UEPyESlateEnums.h"
44

5-
static PyObject *py_ue_fmenu_builder_begin_section(ue_PyFMenuBuilder *self, PyObject * args)
5+
static PyObject* py_ue_fmenu_builder_begin_section(ue_PyFMenuBuilder* self, PyObject* args)
66
{
7-
char *name;
8-
char *text;
7+
char* name;
8+
char* text;
99
if (!PyArg_ParseTuple(args, "ss:begin_section", &name, &text))
1010
return nullptr;
1111

@@ -14,27 +14,31 @@ static PyObject *py_ue_fmenu_builder_begin_section(ue_PyFMenuBuilder *self, PyOb
1414
Py_RETURN_NONE;
1515
}
1616

17-
static PyObject *py_ue_fmenu_builder_end_section(ue_PyFMenuBuilder *self, PyObject * args)
17+
static PyObject* py_ue_fmenu_builder_end_section(ue_PyFMenuBuilder* self, PyObject* args)
1818
{
1919
self->menu_builder.EndSection();
2020

2121
Py_RETURN_NONE;
2222
}
2323

24-
static PyObject *py_ue_fmenu_builder_make_widget(ue_PyFMenuBuilder *self, PyObject * args)
24+
static PyObject* py_ue_fmenu_builder_make_widget(ue_PyFMenuBuilder* self, PyObject* args)
2525
{
26-
ue_PySWidget *ret = (ue_PySWidget *)PyObject_New(ue_PySWidget, &ue_PySWidgetType);
26+
ue_PySWidget* ret = (ue_PySWidget*)PyObject_New(ue_PySWidget, &ue_PySWidgetType);
2727
new (&ret->Widget) TSharedRef<SWidget>(self->menu_builder.MakeWidget());
28-
return (PyObject *)ret;
28+
return (PyObject*)ret;
2929
}
3030

31-
static PyObject *py_ue_fmenu_builder_add_menu_entry(ue_PyFMenuBuilder *self, PyObject * args)
31+
static PyObject* py_ue_fmenu_builder_add_menu_entry(ue_PyFMenuBuilder* self, PyObject* args)
3232
{
33-
char *label;
34-
char *tooltip;
35-
PyObject *py_callable;
36-
PyObject *py_obj = nullptr;
33+
char* label;
34+
char* tooltip;
35+
PyObject* py_callable;
36+
PyObject* py_obj = nullptr;
37+
#if ENGINE_MINOR_VERSION >= 23
38+
int ui_action_type = (int)EUserInterfaceActionType::Button;
39+
#else
3740
int ui_action_type = EUserInterfaceActionType::Button;
41+
#endif
3842
if (!PyArg_ParseTuple(args, "ssO|Oi:add_menu_entry", &label, &tooltip, &py_callable, &py_obj, &ui_action_type))
3943
return nullptr;
4044

@@ -58,17 +62,21 @@ static PyObject *py_ue_fmenu_builder_add_menu_entry(ue_PyFMenuBuilder *self, PyO
5862
}
5963

6064
self->menu_builder.AddMenuEntry(FText::FromString(UTF8_TO_TCHAR(label)), FText::FromString(UTF8_TO_TCHAR(tooltip)), FSlateIcon(), FUIAction(handler), NAME_None,
65+
#if ENGINE_MINOR_VERSION >= 23
66+
(EUserInterfaceActionType)ui_action_type);
67+
#else
6168
(EUserInterfaceActionType::Type)ui_action_type);
69+
#endif
6270

6371
Py_RETURN_NONE;
6472
}
6573

66-
static PyObject *py_ue_fmenu_builder_add_sub_menu(ue_PyFMenuBuilder *self, PyObject * args)
74+
static PyObject* py_ue_fmenu_builder_add_sub_menu(ue_PyFMenuBuilder* self, PyObject* args)
6775
{
68-
char *label;
69-
char *tooltip;
70-
PyObject *py_callable;
71-
PyObject *py_bool = nullptr;
76+
char* label;
77+
char* tooltip;
78+
PyObject* py_callable;
79+
PyObject* py_bool = nullptr;
7280
if (!PyArg_ParseTuple(args, "ssO|O:add_sub_menu", &label, &tooltip, &py_callable, &py_bool))
7381
return nullptr;
7482

@@ -77,7 +85,7 @@ static PyObject *py_ue_fmenu_builder_add_sub_menu(ue_PyFMenuBuilder *self, PyObj
7785
return PyErr_Format(PyExc_Exception, "argument is not callable");
7886
}
7987

80-
88+
8189
TSharedRef<FPythonSlateDelegate> py_delegate = FUnrealEnginePythonHouseKeeper::Get()->NewStaticSlateDelegate(py_callable);
8290

8391
FNewMenuDelegate menu_delegate;
@@ -89,9 +97,9 @@ static PyObject *py_ue_fmenu_builder_add_sub_menu(ue_PyFMenuBuilder *self, PyObj
8997
Py_RETURN_NONE;
9098
}
9199

92-
static PyObject *py_ue_fmenu_builder_add_menu_separator(ue_PyFMenuBuilder *self, PyObject * args)
100+
static PyObject* py_ue_fmenu_builder_add_menu_separator(ue_PyFMenuBuilder* self, PyObject* args)
93101
{
94-
char *name = nullptr;
102+
char* name = nullptr;
95103

96104
if (!PyArg_ParseTuple(args, "|s:add_menu_separator", &name))
97105
return nullptr;
@@ -107,9 +115,9 @@ static PyObject *py_ue_fmenu_builder_add_menu_separator(ue_PyFMenuBuilder *self,
107115
}
108116

109117
#if WITH_EDITOR
110-
static PyObject *py_ue_fmenu_builder_add_asset_actions(ue_PyFMenuBuilder *self, PyObject * args)
118+
static PyObject* py_ue_fmenu_builder_add_asset_actions(ue_PyFMenuBuilder* self, PyObject* args)
111119
{
112-
PyObject *py_assets;
120+
PyObject* py_assets;
113121

114122
if (!PyArg_ParseTuple(args, "O:add_asset_actions", &py_assets))
115123
return nullptr;
@@ -120,10 +128,10 @@ static PyObject *py_ue_fmenu_builder_add_asset_actions(ue_PyFMenuBuilder *self,
120128
return PyErr_Format(PyExc_Exception, "argument is not iterable");
121129
}
122130

123-
TArray<UObject *> u_objects;
124-
while (PyObject *item = PyIter_Next(py_assets))
131+
TArray<UObject*> u_objects;
132+
while (PyObject * item = PyIter_Next(py_assets))
125133
{
126-
UObject *u_object = ue_py_check_type<UObject>(item);
134+
UObject* u_object = ue_py_check_type<UObject>(item);
127135
if (u_object)
128136
{
129137
u_objects.Add(u_object);
@@ -142,7 +150,7 @@ static PyObject *py_ue_fmenu_builder_add_asset_actions(ue_PyFMenuBuilder *self,
142150
}
143151
#endif
144152

145-
static PyObject *py_ue_fmenu_builder_add_search_widget(ue_PyFMenuBuilder *self, PyObject * args)
153+
static PyObject* py_ue_fmenu_builder_add_search_widget(ue_PyFMenuBuilder* self, PyObject* args)
146154
{
147155
self->menu_builder.AddSearchWidget();
148156

@@ -164,13 +172,13 @@ static PyMethodDef ue_PyFMenuBuilder_methods[] = {
164172
};
165173

166174

167-
static PyObject *ue_PyFMenuBuilder_str(ue_PyFMenuBuilder *self)
175+
static PyObject* ue_PyFMenuBuilder_str(ue_PyFMenuBuilder* self)
168176
{
169177
return PyUnicode_FromFormat("<unreal_engine.FMenuBuilder '%p'}>",
170178
&self->menu_builder);
171179
}
172180

173-
static void ue_py_fmenu_builder_dealloc(ue_PyFMenuBuilder *self)
181+
static void ue_py_fmenu_builder_dealloc(ue_PyFMenuBuilder* self)
174182
{
175183
#if PY_MAJOR_VERSION < 3
176184
self->ob_type->tp_free((PyObject*)self);
@@ -210,14 +218,14 @@ static PyTypeObject ue_PyFMenuBuilderType = {
210218
ue_PyFMenuBuilder_methods, /* tp_methods */
211219
};
212220

213-
static int ue_py_fmenu_builder_init(ue_PyFMenuBuilder *self, PyObject *args, PyObject *kwargs)
221+
static int ue_py_fmenu_builder_init(ue_PyFMenuBuilder* self, PyObject* args, PyObject* kwargs)
214222
{
215223
new(&self->menu_builder) FMenuBuilder(true, nullptr);
216224
return 0;
217225
}
218226

219227

220-
void ue_python_init_fmenu_builder(PyObject *ue_module)
228+
void ue_python_init_fmenu_builder(PyObject* ue_module)
221229
{
222230
ue_PyFMenuBuilderType.tp_new = PyType_GenericNew;
223231

@@ -227,12 +235,12 @@ void ue_python_init_fmenu_builder(PyObject *ue_module)
227235
return;
228236

229237
Py_INCREF(&ue_PyFMenuBuilderType);
230-
PyModule_AddObject(ue_module, "FMenuBuilder", (PyObject *)&ue_PyFMenuBuilderType);
238+
PyModule_AddObject(ue_module, "FMenuBuilder", (PyObject*)& ue_PyFMenuBuilderType);
231239
}
232240

233-
PyObject *py_ue_new_fmenu_builder(FMenuBuilder menu_builder)
241+
PyObject* py_ue_new_fmenu_builder(FMenuBuilder menu_builder)
234242
{
235-
ue_PyFMenuBuilder *ret = (ue_PyFMenuBuilder *)PyObject_New(ue_PyFMenuBuilder, &ue_PyFMenuBuilderType);
243+
ue_PyFMenuBuilder* ret = (ue_PyFMenuBuilder*)PyObject_New(ue_PyFMenuBuilder, &ue_PyFMenuBuilderType);
236244
new(&ret->menu_builder) FMenuBuilder(menu_builder);
237-
return (PyObject *)ret;
245+
return (PyObject*)ret;
238246
}

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,11 @@ static int ue_py_stext_block_init(ue_PySTextBlock *self, PyObject *args, PyObjec
7070
ue_py_slate_farguments_float("line_height_percentage", LineHeightPercentage);
7171
ue_py_slate_farguments_struct("margin", Margin, FMargin);
7272
ue_py_slate_farguments_float("min_desired_width", MinDesiredWidth);
73+
#if ENGINE_MINOR_VERSION >= 23
74+
ue_py_slate_farguments_event("on_double_clicked", OnDoubleClicked, FPointerEventHandler, OnMouseEvent);
75+
#else
7376
ue_py_slate_farguments_event("on_double_clicked", OnDoubleClicked, FOnClicked, OnClicked);
77+
#endif
7478
ue_py_slate_farguments_flinear_color("shadow_color_and_opacity", ShadowColorAndOpacity);
7579
ue_py_slate_farguments_fvector2d("shadow_offset", ShadowOffset);
7680
ue_py_slate_farguments_text("text", Text);

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1020,8 +1020,11 @@ class FPythonSlateCommands : public TCommands<FPythonSlateCommands>
10201020
virtual void RegisterCommands() override
10211021
{
10221022
commands = MakeShareable(new FUICommandList);
1023-
1023+
#if ENGINE_MINOR_VERSION >= 23
1024+
MakeUICommand_InternalUseOnly(this, command, nullptr, *name, *name, TCHAR_TO_UTF8(*name), *name, *name, EUserInterfaceActionType::Button, FInputGesture());
1025+
#else
10241026
UI_COMMAND_Function(this, command, nullptr, *name, *name, TCHAR_TO_UTF8(*name), *name, *name, EUserInterfaceActionType::Button, FInputGesture());
1027+
#endif
10251028
commands->MapAction(command, FExecuteAction::CreateRaw(this, &FPythonSlateCommands::Callback), FCanExecuteAction());
10261029
}
10271030

0 commit comments

Comments
 (0)