|
11 | 11 | ''' |
12 | 12 | from . common import * |
13 | 13 | import _fmsubclassing as fms |
| 14 | +import types |
14 | 15 | from unreal_engine import classes as engine_classes |
15 | 16 |
|
| 17 | +# Define the flags you can use with the ufunction decorator - see Runtime\CoreUObject\Public\UObject\Script.h to add more |
| 18 | +class FuncFlag(int): pass |
| 19 | +Event = FuncFlag(0x00000800 | 0x08000000) |
| 20 | +Static = FuncFlag(0x00002000) |
| 21 | +Reliable = FuncFlag(0x00000080) |
| 22 | +Multicast = FuncFlag(0x00004000) |
| 23 | +Server = FuncFlag(0x00200000) |
| 24 | +Client = FuncFlag(0x01000000) |
| 25 | +Pure = BlueprintPure = FuncFlag(0x10000000) |
| 26 | + |
16 | 27 | # decorator that is roughly equivalent to UFUNCTION() in C++ - use this on a method in a subclass to cause it to |
17 | | -# be exposed as callable |
18 | | -# TODO: add support for pure=True, etc. |
19 | | -def ufunction(f): |
20 | | - f.ufunction = True |
21 | | - return f |
| 28 | +# be exposed as callable. Anything the decorator is used on is automatically marked as native, public, and BlueprintCallable, |
| 29 | +# so those flags are never needed. The decorator can be used in two ways: |
| 30 | +# @ufunction |
| 31 | +# @ufunction(...one or more FuncFlags...) |
| 32 | +def ufunction(f, *args): |
| 33 | + if isinstance(f, types.FunctionType): |
| 34 | + # Used without params |
| 35 | + assert not args, args |
| 36 | + f.ufunc_flags = () # the presence of this function member is enough |
| 37 | + return f |
| 38 | + else: |
| 39 | + # With params |
| 40 | + def wrap(f): |
| 41 | + for arg in args: |
| 42 | + assert isinstance(arg, FuncFlag), 'Invalid ufunction param %s for %s' % (arg, f) |
| 43 | + f.ufunc_flags = args |
| 44 | + return f |
| 45 | + return wrap |
22 | 46 |
|
23 | 47 | # used for declaring UPROPERTYs. Use when creating class vars: myVar = uproperty(FVector, FVector(1,2,3)). By default, implies BlueprintReadWrite. |
24 | 48 | # TODO: add support for replication, editanywhere, BPReadOnly, repnotify, and other flags. myVar = uproperty(default, *kwFlags) |
@@ -133,16 +157,23 @@ def ProcessBridgeDescendentClassMethods(metaclass, newPyClass): |
133 | 157 | for k,v in list(newPyClass.__dict__.items()): |
134 | 158 | if k.startswith('__') or k in ('engineClass',): |
135 | 159 | continue |
136 | | - if not callable(v) or not getattr(v, 'ufunction', None): |
| 160 | + if not callable(v): |
| 161 | + continue |
| 162 | + flags = getattr(v, 'ufunc_flags', None) |
| 163 | + if flags is None: |
137 | 164 | continue |
138 | 165 | funcName, func = k,v |
139 | 166 |
|
| 167 | + funcFlags = 0 |
| 168 | + for flag in flags: |
| 169 | + funcFlags |= flag |
| 170 | + |
140 | 171 | # Add the method to the class but under a different name so it doesn't get stomped by the stuff below |
141 | 172 | hiddenFuncName = '_orig_' + funcName |
142 | 173 | setattr(newPyClass, hiddenFuncName, func) |
143 | 174 |
|
144 | 175 | # Expose a UFUNCTION in C++ that calls this method |
145 | | - fms.add_ufunction(newPyClass.engineClass, funcName, func) |
| 176 | + fms.add_ufunction(newPyClass.engineClass, funcName, func, funcFlags) |
146 | 177 |
|
147 | 178 | # Make it so that from Python you can use that name to call the UFUNCTION version in UE4 (so that things |
148 | 179 | # like replication work) |
|
0 commit comments