4.8 KiB
Raw Blame History

ScriptMethod

  • 功能描述: 把静态函数导出变成第一个参数的成员函数。
  • 使用位置: UFUNCTION
  • 引擎模块: Script
  • 元数据类型: string="a;b;c"
  • 限制类型: static function
  • 关联项: ScriptMethodMutable, ScriptMethodSelfReturn
  • 常用程度: ★★★

把静态函数导出变成第一个参数的成员函数。

  • 把func(AB)变成A.func(B)这样就可以给A对象添加成员函数方法。有点像C#里的扩展方法。
  • 也可以直接再提供一个名字来改变包装后的成员函数的名称。注意与ScriptName区分ScriptName改变的是本身导出到脚本的名字而ScriptMethod改变的是结果成员函数的名字。把func(AB)改成A.OtherFunc(B)。

测试代码:

UCLASS(Blueprintable, BlueprintType)
class INSIDER_API UMyPython_ScriptMethod :public UObject
{
	GENERATED_BODY()
public:
};

USTRUCT(BlueprintType)
struct INSIDER_API FMyPythonStruct_ScriptMethod
{
	GENERATED_BODY()
};

UCLASS(Blueprintable, BlueprintType)
class INSIDER_API UMyPython_ScriptMethod_Test :public UObject
{
	GENERATED_BODY()
public:
	UFUNCTION(BlueprintCallable, meta = (ScriptMethod))
	static void MyFuncOnObject(UMyPython_ScriptMethod* obj, FString val);

	UFUNCTION(BlueprintCallable, meta = (ScriptMethod = "MySuperFuncOnObject;MyOtherFuncOnObject"))
	static void MyFuncOnObject2(UMyPython_ScriptMethod* obj, FString val);

public:
	UFUNCTION(BlueprintCallable, meta = (ScriptMethod))
	static void MyFuncOnStruct(const FMyPythonStruct_ScriptMethod& myStruct, FString val);;
};

测试效果:

可见在MyPythonStruct_ScriptMethod里增加了my_func_on_struct的方法而MyPython_ScriptMethod里增加了my_func_on_object的方法。因此如果在py里你就可以把这两个函数当作成员函数一样调用。

另外MyFuncOnObject2上面设置了两个ScriptMethod 别称也可以在MyPython_ScriptMethod里见到。

class MyPythonStruct_ScriptMethod(StructBase):
    r"""
    My Python Struct Script Method
    
    **C++ Source:**
    
    - **Module**: Insider
    - **File**: MyPython_ScriptMethod.h
    
    """
    def __init__(self) -> None:
        ...
    def my_func_on_struct(self, val: str) -> None:
        r"""
        x.my_func_on_struct(val) -> None
        My Func on Struct
        
        Args:
            val (str):
        """
        ...

class MyPython_ScriptMethod(Object):
    r"""
    My Python Script Method
    
    **C++ Source:**
    
    - **Module**: Insider
    - **File**: MyPython_ScriptMethod.h
    
    """
    def my_super_func_on_object(self, val: str) -> None:
        r"""
        x.my_super_func_on_object(val) -> None
        My Func on Object 2
        
        Args:
            val (str):
        """
        ...
     def my_other_func_on_object(self, val: str) -> None:
        r"""
        deprecated: 'my_other_func_on_object' was renamed to 'my_super_func_on_object'.
        """
        ...
    def my_func_on_object(self, val: str) -> None:
        r"""
        x.my_func_on_object(val) -> None
        My Func on Object
        
        Args:
            val (str):
        """
        ...
class MyPython_ScriptMethod_Test(Object):
    r"""
    My Python Script Method Test
    
    **C++ Source:**
    
    - **Module**: Insider
    - **File**: MyPython_ScriptMethod.h
    
    """
    @classmethod
    def my_func_on_struct(cls, my_struct: MyPythonStruct_ScriptMethod, val: str) -> None:
        r"""
        X.my_func_on_struct(my_struct, val) -> None
        My Func on Struct
        
        Args:
            my_struct (MyPythonStruct_ScriptMethod): 
            val (str):
        """
        ...
    @classmethod
    def my_func_on_object2(cls, obj: MyPython_ScriptMethod, val: str) -> None:
        r"""
        X.my_func_on_object2(obj, val) -> None
        My Func on Object 2
        
        Args:
            obj (MyPython_ScriptMethod): 
            val (str):
        """
        ...
    @classmethod
    def my_func_on_object(cls, obj: MyPython_ScriptMethod, val: str) -> None:
        r"""
        X.my_func_on_object(obj, val) -> None
        My Func on Object
        
        Args:
            obj (MyPython_ScriptMethod): 
            val (str):
        """
        ...

原理:

在GenerateWrappedDynamicMethod中有详细的如何把静态函数包装成成员函数的过程。感兴趣的可以去细看。

PyTypeObject* FPyWrapperTypeRegistry::GenerateWrappedClassType(const UClass* InClass, FGeneratedWrappedTypeReferences& OutGeneratedWrappedTypeReferences, TSet<FName>& OutDirtyModules, const EPyTypeGenerationFlags InGenerationFlags)
{
	// Should this function also be hoisted as a struct method or operator?
	if (InFunc->HasMetaData(PyGenUtil::ScriptMethodMetaDataKey))
	{
		GenerateWrappedDynamicMethod(InFunc, GeneratedWrappedMethodCopy);
	}
}