Skip to content

Commit

Permalink
added support for uobj.unbind_event
Browse files Browse the repository at this point in the history
  • Loading branch information
dfb committed Feb 19, 2019
1 parent b9fb929 commit dc6e93c
Show file tree
Hide file tree
Showing 7 changed files with 82 additions and 2 deletions.
9 changes: 8 additions & 1 deletion Source/UnrealEnginePython/Private/PythonDelegate.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@

#include "PythonDelegate.h"
#include "UEPyModule.h"
#include "UEPyCallable.h"

UPythonDelegate::UPythonDelegate()
{
Expand Down Expand Up @@ -101,6 +102,12 @@ void UPythonDelegate::PyInputAxisHandler(float value)
Py_DECREF(ret);
}

bool UPythonDelegate::UsesPyCallable(PyObject *other)
{
ue_PyCallable *other_callable = (ue_PyCallable*)other;
ue_PyCallable *this_callable = (ue_PyCallable*)py_callable;
return other_callable->u_function == this_callable->u_function && other_callable->u_target == this_callable->u_target;
}

UPythonDelegate::~UPythonDelegate()
{
Expand All @@ -110,4 +117,4 @@ UPythonDelegate::~UPythonDelegate()
#if defined(UEPY_MEMORY_DEBUG)
UE_LOG(LogPython, Warning, TEXT("PythonDelegate %p callable XDECREF'ed"), this);
#endif
}
}
40 changes: 40 additions & 0 deletions Source/UnrealEnginePython/Private/UEPyModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -607,6 +607,7 @@ static PyMethodDef ue_PyUObject_methods[] = {
{ "set_name", (PyCFunction)py_ue_set_name, METH_VARARGS, "" },

{ "bind_event", (PyCFunction)py_ue_bind_event, METH_VARARGS, "" },
{ "unbind_event", (PyCFunction)py_ue_unbind_event, METH_VARARGS, "" },
{ "delegate_bind_ufunction", (PyCFunction)py_ue_delegate_bind_ufunction, METH_VARARGS, "" },

{ "get_py_proxy", (PyCFunction)py_ue_get_py_proxy, METH_VARARGS, "" },
Expand Down Expand Up @@ -3044,6 +3045,45 @@ PyObject *py_ue_ufunction_call(UFunction *u_function, UObject *u_obj, PyObject *
Py_RETURN_NONE;
}

PyObject *ue_unbind_pyevent(ue_PyUObject *u_obj, FString event_name, PyObject *py_callable, bool fail_on_wrong_property)
{
UProperty *u_property = u_obj->ue_object->GetClass()->FindPropertyByName(FName(*event_name));
if (!u_property)
{
if (fail_on_wrong_property)
return PyErr_Format(PyExc_Exception, "unable to find event property %s", TCHAR_TO_UTF8(*event_name));
Py_RETURN_NONE;
}

if (auto casted_prop = Cast<UMulticastDelegateProperty>(u_property))
{
UPythonDelegate *py_delegate = FUnrealEnginePythonHouseKeeper::Get()->FindDelegate(u_obj->ue_object, py_callable);
if (py_delegate != nullptr)
{
FMulticastScriptDelegate multiscript_delegate = casted_prop->GetPropertyValue_InContainer(u_obj->ue_object);
multiscript_delegate.Remove(py_delegate, FName("PyFakeCallable"));

// re-assign multicast delegate
casted_prop->SetPropertyValue_InContainer(u_obj->ue_object, multiscript_delegate);
}
}
else if (auto casted_prop_delegate = Cast<UDelegateProperty>(u_property))
{
FScriptDelegate script_delegate = casted_prop_delegate->GetPropertyValue_InContainer(u_obj->ue_object);
script_delegate.Unbind();

// re-assign multicast delegate
casted_prop_delegate->SetPropertyValue_InContainer(u_obj->ue_object, script_delegate);
}
else
{
if (fail_on_wrong_property)
return PyErr_Format(PyExc_Exception, "property %s is not an event", TCHAR_TO_UTF8(*event_name));
}

Py_RETURN_NONE;
}

PyObject *ue_bind_pyevent(ue_PyUObject *u_obj, FString event_name, PyObject *py_callable, bool fail_on_wrong_property)
{

Expand Down
1 change: 1 addition & 0 deletions Source/UnrealEnginePython/Private/UEPyModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ void ue_bind_events_for_py_class_by_attribute(UObject *, PyObject *);

void ue_autobind_events_for_pyclass(ue_PyUObject *, PyObject *);
PyObject *ue_bind_pyevent(ue_PyUObject *, FString, PyObject *, bool);
PyObject *ue_unbind_pyevent(ue_PyUObject *, FString, PyObject *, bool);

PyObject *py_ue_ufunction_call(UFunction *, UObject *, PyObject *, int, PyObject *);

Expand Down
19 changes: 19 additions & 0 deletions Source/UnrealEnginePython/Private/UObject/UEPyObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1517,6 +1517,25 @@ PyObject *py_ue_bind_event(ue_PyUObject * self, PyObject * args)
return ue_bind_pyevent(self, FString(event_name), py_callable, true);
}

PyObject *py_ue_unbind_event(ue_PyUObject * self, PyObject * args)
{
ue_py_check(self);

char *event_name;
PyObject *py_callable;
if (!PyArg_ParseTuple(args, "sO:bind_event", &event_name, &py_callable))
{
return NULL;
}

if (!PyCallable_Check(py_callable))
{
return PyErr_Format(PyExc_Exception, "object is not callable");
}

return ue_unbind_pyevent(self, FString(event_name), py_callable, true);
}

PyObject *py_ue_delegate_bind_ufunction(ue_PyUObject * self, PyObject * args)
{
ue_py_check(self);
Expand Down
3 changes: 2 additions & 1 deletion Source/UnrealEnginePython/Private/UObject/UEPyObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ PyObject *py_ue_enum_user_defined_names(ue_PyUObject *, PyObject *);


PyObject *py_ue_bind_event(ue_PyUObject *, PyObject *);
PyObject *py_ue_unbind_event(ue_PyUObject *, PyObject *);
PyObject *py_ue_add_function(ue_PyUObject *, PyObject *);
PyObject *py_ue_add_property(ue_PyUObject *, PyObject *);

Expand Down Expand Up @@ -111,4 +112,4 @@ PyObject *py_ue_render_thumbnail(ue_PyUObject *, PyObject *);

PyObject *py_ue_to_bytes(ue_PyUObject *, PyObject *);
PyObject *py_ue_to_bytearray(ue_PyUObject *, PyObject *);
PyObject *py_ue_from_bytes(ue_PyUObject *, PyObject *);
PyObject *py_ue_from_bytes(ue_PyUObject *, PyObject *);
1 change: 1 addition & 0 deletions Source/UnrealEnginePython/Public/PythonDelegate.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ class UPythonDelegate : public UObject
~UPythonDelegate();
virtual void ProcessEvent(UFunction *function, void *Parms) override;
void SetPyCallable(PyObject *callable);
bool UsesPyCallable(PyObject *callable);
void SetSignature(UFunction *original_signature);

void PyInputHandler();
Expand Down
11 changes: 11 additions & 0 deletions Source/UnrealEnginePython/Public/PythonHouseKeeper.h
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,17 @@ class FUnrealEnginePythonHouseKeeper : public FGCObject
return Garbaged;
}

UPythonDelegate *FindDelegate(UObject *Owner, PyObject *PyCallable)
{
for (int32 i = PyDelegatesTracker.Num() - 1; i >= 0; --i)
{
FPythonDelegateTracker &Tracker = PyDelegatesTracker[i];
if (Tracker.Owner.Get() == Owner && Tracker.Delegate->UsesPyCallable(PyCallable))
return Tracker.Delegate;
}
return nullptr;
}

UPythonDelegate *NewDelegate(UObject *Owner, PyObject *PyCallable, UFunction *Signature)
{
UPythonDelegate *Delegate = NewObject<UPythonDelegate>();
Expand Down

0 comments on commit dc6e93c

Please sign in to comment.