Python Module Example

The BP Function Library examples as one big module-style example


import json
import os
from pathlib import Path

import unreal


@unreal.uclass()
class PyDemoBPLibrary(unreal.BlueprintFunctionLibrary):
    """
    Blueprint functions declared in this class will be available in Editor
    """

    # ---------      standard options     --------- #

    @unreal.ufunction(static=True)
    def basic_function_test():
        """Python Blueprint Node -- run Python logic!"""
        print("Printed a message via Python!")


    @unreal.ufunction(static=True, params=[str])
    def input_test(user_input = "cool!"):
        """Python Blueprint Node -- print the text input"""
        print(f"Provided input: {user_input}")


    @unreal.ufunction(static=True, ret=str)
    def return_test():
        """Python Blueprint Node -- return a string!
        returns:
            str
        """
        return "cool!"


    @unreal.ufunction(static=True, params=[str, bool, int])
    def multiple_input_test(in_str, in_bool, in_int):
        """Python Blueprint Node -- multiple inputs (string, bool, int)"""
        print(f"{in_str} ({type(in_str)}) | {in_bool} ({type(in_bool)}) | {in_int} ({type(in_int)})")


    @unreal.ufunction(static=True, ret=(int, bool, str))
    def multiple_returns_test():
        """Python Blueprint Node -- Return (str, bool, int)

        NOTE: the 'ret' decorator arg is reversed from the actual python return
        """
        return "Awesome", True, 5


    @unreal.ufunction(static=True, ret=unreal.Array(str), params=[unreal.Array(str)])
    def sort_string_list_test(in_list):
        """
        Python Blueprint Node -- Sort a list of strings, useful for managing options in editor tools
        """
        return sorted(in_list)


    @unreal.ufunction(ret= str, pure=True, static=True)
    def pure_function_test() -> str:
        """
        Python Blueprint Node
        Pure functions have no execution flow pin connectors,
        intended for getter functions that do not change the state of assets in Unreal
        """
        return os.environ.get("USER", "unknown user")


    # ---------      metadata options     --------- #

    @unreal.ufunction(static=True, meta=dict(Category="demo | category | sorting"))
    def meta_category_test():
        """
        Python Blueprint Node
        Category organizes this node in the BP Graph right click menu
        Use | to create nested sub-groups
        """
        pass


    @unreal.ufunction(static=True, meta=dict(KeyWords="random arbitrary keywords"))
    def meta_keywords_test():
        """
        Python Blueprint Node
        KeyWords help the discovery of this node in the BP Graph right click menu
        """
        pass


    @unreal.ufunction(static=True, meta=dict(CompactNodeTitle="UEPY"))
    def meta_compact_name_test():
        """Python Blueprint Node -- CompactNodeTitle"""
        pass


    @unreal.ufunction(static=True, params=[unreal.Actor], meta=dict(DefaultToSelf="target_object"))
    def meta_default_to_self_test(target_object):
        """Python Blueprint Node -- DefaultToSelf (The BP Class calling this Function)"""
        print(f"target object: {target_object}")
        pass


    @unreal.ufunction(static=True, ret=(int, bool, str), meta=dict(HidePin="returnValue"))
    def multiple_returns_fixed_test():
        """Python Blueprint Node -- Return (str, bool, int)"""
        return "Awesome", True, 5


    @unreal.ufunction(
        static=True, 
        ret=unreal.Object,
        params=[unreal.Object],
        pure=True,
        meta=dict(DeterminesOutputType="object_to_match")
    )
    def match_object(object_to_match):
        """
        Python Blueprint Node
        the BP Graph will match our return's type to the provided
        input 'object_to_match', this helps inform the BP Graph
        when returning sub classes, such as Blueprint Assets
        created in the Editor
        """
        return object_to_match


    # ---------      practical examples     --------- #

    @unreal.ufunction(
        static=True, params=[str, unreal.Map(str, str)],
        meta=dict(Category="demo | EUW | prefs")
    )
    def save_user_prefs(prefs_name, prefs_data):
        """Python Blueprint Node -- save some basic prefs data"""

        # Convert the unreal Map to a json compliant dict
        prefs = {
            str(key): str(value)
            for key, value in prefs_data.items()
        }

        # we'll save this file to the users' tmp dir under 'unreal/unreal_prefs_<pref>.json'
        prefs_file = Path(
            unreal.Paths.project_saved_dir(),
            "pytemp",
            f"unreal_prefs_{prefs_name}.json"
        )

        if not prefs_file.exists():
            prefs_file.parent.mkdir(parents=True, exist_ok=True)

        with prefs_file.open("w", encoding="utf-8") as f:
            json.dump(prefs, f, indent=2)


    @unreal.ufunction(
        static=True, ret=unreal.Map(str, str), params=[str],
        pure=True, meta=dict(Category="demo | EUW | prefs")
    )
    def load_user_prefs(prefs_name) :
        """Python Blueprint Node -- load some basic prefs data"""

        # use the same path structure as the save and make sure it exists
        prefs_file = Path(
            unreal.Paths.project_saved_dir(),
            "pytemp",
            f"unreal_prefs_{prefs_name}.json"
        )
        if not prefs_file.exists():
            return {}

        # we can return the dict as-is, Unreal will convert it to a Map(str,str) for us
        return json.loads(prefs_file.read_text())

Last updated