private void ProcessCommon(EExprToken opcode) { switch (opcode) { case EExprToken.EX_PrimitiveCast: { // A type conversion. byte conversionType = ReadByte(); output.AppendLine(FmtOpcodeIndent(opcode) + "PrimitiveCast of type " + conversionType); AddIndent(); output.AppendLine(indents + " Argument:"); ProcessCastByte(conversionType); //@TODO: //Ar.Logf(TEXT("%s Expression:"), *Indents); //SerializeExpr( ScriptIndex ); break; } case EExprToken.EX_SetSet: { output.AppendLine(FmtOpcodeIndent(opcode) + "set set"); SerializeExpr(); ReadInt32(); while (SerializeExpr() != EExprToken.EX_EndSet) { // Set contents } break; } case EExprToken.EX_EndSet: { output.AppendLine(FmtOpcodeIndent(opcode) + "EX_EndSet"); break; } case EExprToken.EX_SetConst: { UProperty innerProp = ReadPointer <UProperty>(); int num = ReadInt32(); output.AppendLine(FmtOpcodeIndent(opcode) + "set set const - elements number: " + num + ", inner property: " + UObject.GetNameSafe(innerProp)); while (SerializeExpr() != EExprToken.EX_EndSetConst) { // Set contents } break; } case EExprToken.EX_EndSetConst: { output.AppendLine(FmtOpcodeIndent(opcode) + "EX_EndSetConst"); break; } case EExprToken.EX_SetMap: { output.AppendLine(FmtOpcodeIndent(opcode) + "set map"); SerializeExpr(); ReadInt32(); while (SerializeExpr() != EExprToken.EX_EndMap) { // Map contents } break; } case EExprToken.EX_EndMap: { output.AppendLine(FmtOpcodeIndent(opcode) + "EX_EndMap"); break; } case EExprToken.EX_MapConst: { UProperty keyProp = ReadPointer <UProperty>(); UProperty valProp = ReadPointer <UProperty>(); int num = ReadInt32(); output.AppendLine(FmtOpcodeIndent(opcode) + "set map const - elements number: " + num + ", key property: " + UObject.GetNameSafe(keyProp) + ", val property: " + UObject.GetNameSafe(valProp)); while (SerializeExpr() != EExprToken.EX_EndMapConst) { // Map contents } break; } case EExprToken.EX_ObjToInterfaceCast: { // A conversion from an object variable to a native interface variable. // We use a different bytecode to avoid the branching each time we process a cast token // the interface class to convert to UClass interfaceClass = ReadPointer <UClass>(); output.AppendLine(FmtOpcodeIndent(opcode) + "ObjToInterfaceCast to " + interfaceClass.GetName()); SerializeExpr(); break; } case EExprToken.EX_CrossInterfaceCast: { // A conversion from one interface variable to a different interface variable. // We use a different bytecode to avoid the branching each time we process a cast token // the interface class to convert to UClass interfaceClass = ReadPointer <UClass>(); output.AppendLine(FmtOpcodeIndent(opcode) + "InterfaceToInterfaceCast to " + interfaceClass.GetName()); SerializeExpr(); break; } case EExprToken.EX_InterfaceToObjCast: { // A conversion from an interface variable to a object variable. // We use a different bytecode to avoid the branching each time we process a cast token // the interface class to convert to UClass objectClass = ReadPointer <UClass>(); output.AppendLine(FmtOpcodeIndent(opcode) + "InterfaceToObjCast to " + objectClass.GetName()); SerializeExpr(); break; } case EExprToken.EX_Let: { output.AppendLine(FmtOpcodeIndent(opcode) + "Let (Variable = Expression)"); AddIndent(); ReadPointer <UProperty>(); // Variable expr. output.AppendLine(indents + " Variable:"); SerializeExpr(); // Assignment expr. output.AppendLine(indents + " Expression:"); SerializeExpr(); DropIndent(); break; } case EExprToken.EX_LetObj: case EExprToken.EX_LetWeakObjPtr: { if (opcode == EExprToken.EX_LetObj) { output.AppendLine(FmtOpcodeIndent(opcode) + "Let Obj (Variable = Expression)"); } else { output.AppendLine(FmtOpcodeIndent(opcode) + "Let WeakObjPtr (Variable = Expression)"); } AddIndent(); // Variable expr. output.AppendLine(indents + " Variable:"); SerializeExpr(); // Assignment expr. output.AppendLine(indents + " Expression:"); SerializeExpr(); DropIndent(); break; } case EExprToken.EX_LetBool: { output.AppendLine(FmtOpcodeIndent(opcode) + "LetBool (Variable = Expression)"); AddIndent(); // Variable expr. output.AppendLine(indents + " Variable:"); SerializeExpr(); // Assignment expr. output.AppendLine(indents + " Expression:"); SerializeExpr(); DropIndent(); break; } case EExprToken.EX_LetValueOnPersistentFrame: { output.AppendLine(FmtOpcodeIndent(opcode) + "LetValueOnPersistentFrame"); AddIndent(); UProperty prop = ReadPointer <UProperty>(); output.AppendLine(indents + " Destination variable: " + UObject.GetNameSafe(prop) + ", offset: " + (prop != null ? prop.GetOffset_ForDebug() : 0)); output.AppendLine(indents + " Expression:"); SerializeExpr(); DropIndent(); break; } case EExprToken.EX_StructMemberContext: { output.AppendLine(FmtOpcodeIndent(opcode) + "Struct member context"); AddIndent(); UProperty prop = ReadPointer <UProperty>(); // although that isn't a UFunction, we are not going to indirect the props of a struct, so this should be fine output.AppendLine(indents + " Expression within struct " + prop.GetName() + ", offset " + prop.GetOffset_ForDebug()); output.AppendLine(indents + " Expression to struct:"); SerializeExpr(); DropIndent(); break; } case EExprToken.EX_LetDelegate: { output.AppendLine(FmtOpcodeIndent(opcode) + "LetDelegate (Variable = Expression)"); AddIndent(); // Variable expr. output.AppendLine(indents + " Variable:"); SerializeExpr(); // Assignment expr. output.AppendLine(indents + " Expression:"); SerializeExpr(); DropIndent(); break; } case EExprToken.EX_LetMulticastDelegate: { output.AppendLine(FmtOpcodeIndent(opcode) + "LetMulticastDelegate (Variable = Expression)"); AddIndent(); // Variable expr. output.AppendLine(indents + " Variable:"); SerializeExpr(); // Assignment expr. output.AppendLine(indents + " Expression:"); SerializeExpr(); DropIndent(); break; } case EExprToken.EX_ComputedJump: { output.AppendLine(FmtOpcodeIndent(opcode) + "Computed Jump, offset specified by expression:"); AddIndent(); SerializeExpr(); DropIndent(); break; } case EExprToken.EX_Jump: { uint skipCount = ReadSkipCount(); output.AppendLine(FmtOpcodeIndent(opcode) + "Jump to offset " + FmtSkipCount(skipCount)); break; } case EExprToken.EX_LocalVariable: { UProperty property = ReadPointer <UProperty>(); output.AppendLine(FmtOpcodeIndent(opcode) + "Local variable named " + FmtObjNameOrNull(property)); break; } case EExprToken.EX_DefaultVariable: { UProperty property = ReadPointer <UProperty>(); output.AppendLine(FmtOpcodeIndent(opcode) + "Default variable named " + FmtObjNameOrNull(property)); break; } case EExprToken.EX_InstanceVariable: { UProperty property = ReadPointer <UProperty>(); output.AppendLine(FmtOpcodeIndent(opcode) + "Instance variable named " + FmtObjNameOrNull(property)); break; } case EExprToken.EX_LocalOutVariable: { UProperty property = ReadPointer <UProperty>(); output.AppendLine(FmtOpcodeIndent(opcode) + "Local out variable named " + FmtObjNameOrNull(property)); break; } case EExprToken.EX_InterfaceContext: { output.AppendLine(FmtOpcodeIndent(opcode) + "EX_InterfaceContext:"); SerializeExpr(); break; } case EExprToken.EX_DeprecatedOp4A: { output.AppendLine(FmtOpcodeIndent(opcode) + "This opcode has been removed and does nothing."); break; } case EExprToken.EX_Nothing: case EExprToken.EX_EndOfScript: case EExprToken.EX_EndFunctionParms: case EExprToken.EX_EndStructConst: case EExprToken.EX_EndArray: case EExprToken.EX_EndArrayConst: case EExprToken.EX_IntZero: case EExprToken.EX_IntOne: case EExprToken.EX_True: case EExprToken.EX_False: case EExprToken.EX_NoObject: case EExprToken.EX_NoInterface: case EExprToken.EX_Self: case EExprToken.EX_EndParmValue: { output.AppendLine(FmtOpcodeIndent(opcode) + opcode.ToString()); break; } case EExprToken.EX_Return: { output.AppendLine(FmtOpcodeIndent(opcode) + opcode.ToString()); SerializeExpr(); // Return expression. break; } case EExprToken.EX_CallMath: { UStruct stackNode = ReadPointer <UStruct>(); output.AppendLine(FmtOpcodeIndent(opcode) + "Call Math (stack node " + UObject.GetNameSafe(stackNode != null ? stackNode.GetOuter() : null) + "::" + UObject.GetNameSafe(stackNode) + ")"); while (SerializeExpr() != EExprToken.EX_EndFunctionParms) { // Params } break; } case EExprToken.EX_FinalFunction: { UStruct stackNode = ReadPointer <UStruct>(); output.AppendLine(FmtOpcodeIndent(opcode) + "Final Function (stack node " + FmtObjOuterNameOrNull(stackNode) + "::" + FmtObjNameOrNull(stackNode) + ")"); while (SerializeExpr() != EExprToken.EX_EndFunctionParms) { // Params } break; } case EExprToken.EX_CallMulticastDelegate: { UStruct stackNode = ReadPointer <UStruct>(); output.AppendLine(FmtOpcodeIndent(opcode) + "CallMulticastDelegate (signature " + FmtObjOuterNameOrNull(stackNode) + "::" + FmtObjNameOrNull(stackNode) + ") delegate:"); SerializeExpr(); output.AppendLine(FmtOpcodeIndent(opcode) + "Params:"); while (SerializeExpr() != EExprToken.EX_EndFunctionParms) { // Params } break; } case EExprToken.EX_VirtualFunction: { string functionName = ReadName(); output.AppendLine(FmtOpcodeIndent(opcode) + "Virtual Function named " + functionName); while (SerializeExpr() != EExprToken.EX_EndFunctionParms) { } break; } case EExprToken.EX_ClassContext: case EExprToken.EX_Context: case EExprToken.EX_Context_FailSilent: { output.AppendLine(FmtOpcodeIndent(opcode) + (opcode == EExprToken.EX_ClassContext ? "Class Context" : "Context")); AddIndent(); // Object expression. output.AppendLine(indents + " ObjectExpression:"); SerializeExpr(); if (opcode == EExprToken.EX_Context_FailSilent) { output.AppendLine(indents + " Can fail silently on access none "); } // Code offset for NULL expressions. uint skipCount = ReadSkipCount(); output.AppendLine(indents + " Skip Bytes: " + FmtSkipCount(skipCount)); // Property corresponding to the r-value data, in case the l-value needs to be mem-zero'd UField field = ReadPointer <UField>(); output.AppendLine(indents + " R-Value Property: " + FmtObjNameOrNull(field)); // Context expression. output.AppendLine(indents + " ContextExpression:"); SerializeExpr(); DropIndent(); break; } case EExprToken.EX_IntConst: { int constValue = ReadInt32(); output.AppendLine(FmtOpcodeIndent(opcode) + "literal int32 " + constValue); break; } case EExprToken.EX_SkipOffsetConst: { uint constValue = ReadSkipCount(); output.AppendLine(FmtOpcodeIndent(opcode) + "literal CodeSkipSizeType " + FmtSkipCount(constValue)); break; } case EExprToken.EX_FloatConst: { float constValue = ReadFloat(); output.AppendLine(FmtOpcodeIndent(opcode) + "literal float " + constValue); break; } case EExprToken.EX_StringConst: { string constValue = ReadString8(); output.AppendLine(FmtOpcodeIndent(opcode) + "literal ansi string \"" + constValue + "\""); break; } case EExprToken.EX_UnicodeStringConst: { string constValue = ReadString16(); output.AppendLine(FmtOpcodeIndent(opcode) + "literal unicode string \"" + constValue + "\""); break; } case EExprToken.EX_TextConst: { // What kind of text are we dealing with? EBlueprintTextLiteralType textLiteralType = (EBlueprintTextLiteralType)script[scriptIndex++]; switch (textLiteralType) { case EBlueprintTextLiteralType.Empty: { output.AppendLine(FmtOpcodeIndent(opcode) + "literal text - empty"); break; } case EBlueprintTextLiteralType.LocalizedText: { string sourceString = ReadString(); string keyString = ReadString(); string namespaceString = ReadString(); output.AppendLine(FmtOpcodeIndent(opcode) + "literal text - localized text { namespace: \"" + namespaceString + "\", key: \"" + keyString + "\", source: \"" + sourceString + "\" }"); break; } case EBlueprintTextLiteralType.InvariantText: { string sourceString = ReadString(); output.AppendLine(FmtOpcodeIndent(opcode) + "literal text - invariant text: \"" + sourceString + "\""); break; } case EBlueprintTextLiteralType.LiteralString: { string sourceString = ReadString(); output.AppendLine(FmtOpcodeIndent(opcode) + "literal text - literal string: \"" + sourceString + "\""); break; } case EBlueprintTextLiteralType.StringTableEntry: { ReadPointer <UObject>(); // String Table asset (if any) string tableIdString = ReadString(); string keyString = ReadString(); output.AppendLine(FmtOpcodeIndent(opcode) + "literal text - string table entry { tableid: \"" + tableIdString + "\", key: \"" + keyString + "\" }"); break; } default: throw new Exception("Unknown EBlueprintTextLiteralType! Please update ProcessCommon() to handle this type of text."); } break; } case EExprToken.EX_ObjectConst: { UObject pointer = ReadPointer <UObject>(); output.AppendLine(FmtOpcodeIndent(opcode) + "EX_ObjectConst (" + FmtPtr(pointer) + ":" + pointer.GetFullName()); break; } case EExprToken.EX_SoftObjectConst: { output.AppendLine(FmtOpcodeIndent(opcode) + "EX_SoftObjectConst"); SerializeExpr(); break; } case EExprToken.EX_NameConst: { string constValue = ReadName(); output.AppendLine(FmtOpcodeIndent(opcode) + "literal name " + constValue); break; } case EExprToken.EX_RotationConst: { float pitch = ReadFloat(); float yaw = ReadFloat(); float roll = ReadFloat(); output.AppendLine(FmtOpcodeIndent(opcode) + "literal rotation (" + pitch + "," + yaw + "," + roll + ")"); break; } case EExprToken.EX_VectorConst: { float x = ReadFloat(); float y = ReadFloat(); float z = ReadFloat(); output.AppendLine(FmtOpcodeIndent(opcode) + "literal vector (" + x + "," + y + "," + z + ")"); break; } case EExprToken.EX_TransformConst: { float rotX = ReadFloat(); float rotY = ReadFloat(); float rotZ = ReadFloat(); float rotW = ReadFloat(); float transX = ReadFloat(); float transY = ReadFloat(); float transZ = ReadFloat(); float scaleX = ReadFloat(); float scaleY = ReadFloat(); float scaleZ = ReadFloat(); output.AppendLine(FmtOpcodeIndent(opcode) + "literal transform " + "R(" + rotX + "," + rotY + "," + rotZ + "," + rotW + "," + ") " + "T(" + transX + "," + transY + "," + transZ + ") " + "T(" + scaleX + "," + scaleY + "," + scaleZ + ")"); break; } case EExprToken.EX_StructConst: { UScriptStruct unrealStruct = ReadPointer <UScriptStruct>(); int serializedSize = ReadInt32(); output.AppendLine(FmtOpcodeIndent(opcode) + "literal struct " + unrealStruct.GetName() + " (serialized size: " + serializedSize + ")"); break; } case EExprToken.EX_SetArray: { output.AppendLine(FmtOpcodeIndent(opcode) + "set array"); SerializeExpr(); while (SerializeExpr() != EExprToken.EX_EndArray) { // Array contents } break; } case EExprToken.EX_ArrayConst: { UProperty innerProp = ReadPointer <UProperty>(); int num = ReadInt32(); output.AppendLine(FmtOpcodeIndent(opcode) + "set array const - elements number: " + num + ", inner property: " + UObject.GetNameSafe(innerProp)); break; } case EExprToken.EX_ByteConst: { byte constValue = ReadByte(); output.AppendLine(FmtOpcodeIndent(opcode) + "literal byte " + constValue); break; } case EExprToken.EX_IntConstByte: { int constValue = ReadByte(); output.AppendLine(FmtOpcodeIndent(opcode) + "literal int " + constValue); break; } case EExprToken.EX_MetaCast: { UClass unrealClass = ReadPointer <UClass>(); output.AppendLine(FmtOpcodeIndent(opcode) + "MetaCast to " + unrealClass.GetName() + " of expr:"); SerializeExpr(); break; } case EExprToken.EX_DynamicCast: { UClass unrealClass = ReadPointer <UClass>(); output.AppendLine(FmtOpcodeIndent(opcode) + "DynamicCast to " + unrealClass.GetName() + " of expr:"); SerializeExpr(); break; } case EExprToken.EX_JumpIfNot: { // Code offset. uint skipCount = ReadSkipCount(); output.AppendLine(FmtOpcodeIndent(opcode) + "Jump to offset " + FmtSkipCount(skipCount) + " if not expr:"); // Boolean expr. SerializeExpr(); break; } case EExprToken.EX_Assert: { ushort lineNumber = ReadUInt16(); byte inDebugMode = ReadByte(); output.AppendLine(FmtOpcodeIndent(opcode) + "assert at line " + lineNumber + ", in debug mode = " + inDebugMode + " with expr:"); SerializeExpr(); // Assert expr. break; } case EExprToken.EX_Skip: { uint w = ReadSkipCount(); output.AppendLine(FmtOpcodeIndent(opcode) + "possibly skip " + FmtSkipCount(w) + " bytes of expr:"); // Expression to possibly skip. SerializeExpr(); break; } case EExprToken.EX_InstanceDelegate: { // the name of the function assigned to the delegate. string funcName = ReadName(); output.AppendLine(FmtOpcodeIndent(opcode) + "instance delegate function named " + funcName); break; } case EExprToken.EX_AddMulticastDelegate: { output.AppendLine(FmtOpcodeIndent(opcode) + "Add MC delegate"); SerializeExpr(); SerializeExpr(); break; } case EExprToken.EX_RemoveMulticastDelegate: { output.AppendLine(FmtOpcodeIndent(opcode) + "Remove MC delegate"); SerializeExpr(); SerializeExpr(); break; } case EExprToken.EX_ClearMulticastDelegate: { output.AppendLine(FmtOpcodeIndent(opcode) + "Clear MC delegate"); SerializeExpr(); break; } case EExprToken.EX_BindDelegate: { // the name of the function assigned to the delegate. string funcName = ReadName(); output.AppendLine(FmtOpcodeIndent(opcode) + "BindDelegate '" + funcName + "'"); output.AppendLine(indents + " Delegate:"); SerializeExpr(); output.AppendLine(indents + " Object:"); SerializeExpr(); break; } case EExprToken.EX_PushExecutionFlow: { uint skipCount = ReadSkipCount(); output.AppendLine(FmtOpcodeIndent(opcode) + "FlowStack.Push(" + FmtSkipCount(skipCount) + ");"); break; } case EExprToken.EX_PopExecutionFlow: { output.AppendLine(FmtOpcodeIndent(opcode) + "if (FlowStack.Num()) { jump to statement at FlowStack.Pop(); } else { ERROR!!! }"); break; } case EExprToken.EX_PopExecutionFlowIfNot: { output.AppendLine(FmtOpcodeIndent(opcode) + "if (!condition) { if (FlowStack.Num()) { jump to statement at FlowStack.Pop(); } else { ERROR!!! } }"); // Boolean expr. SerializeExpr(); break; } case EExprToken.EX_Breakpoint: { output.AppendLine(FmtOpcodeIndent(opcode) + "<<< BREAKPOINT >>>"); break; } case EExprToken.EX_WireTracepoint: { output.AppendLine(FmtOpcodeIndent(opcode) + ".. wire debug site .."); break; } case EExprToken.EX_InstrumentationEvent: { EScriptInstrumentation eventType = (EScriptInstrumentation)ReadByte(); switch (eventType) { case EScriptInstrumentation.InlineEvent: output.AppendLine(FmtOpcodeIndent(opcode) + ".. instrumented inline event .."); break; case EScriptInstrumentation.Stop: output.AppendLine(FmtOpcodeIndent(opcode) + ".. instrumented event stop .."); break; case EScriptInstrumentation.PureNodeEntry: output.AppendLine(FmtOpcodeIndent(opcode) + ".. instrumented pure node entry site .."); break; case EScriptInstrumentation.NodeDebugSite: output.AppendLine(FmtOpcodeIndent(opcode) + ".. instrumented debug site .."); break; case EScriptInstrumentation.NodeEntry: output.AppendLine(FmtOpcodeIndent(opcode) + ".. instrumented wire entry site .."); break; case EScriptInstrumentation.NodeExit: output.AppendLine(FmtOpcodeIndent(opcode) + ".. instrumented wire exit site .."); break; case EScriptInstrumentation.PushState: output.AppendLine(FmtOpcodeIndent(opcode) + ".. push execution state .."); break; case EScriptInstrumentation.RestoreState: output.AppendLine(FmtOpcodeIndent(opcode) + ".. restore execution state .."); break; case EScriptInstrumentation.ResetState: output.AppendLine(FmtOpcodeIndent(opcode) + ".. reset execution state .."); break; case EScriptInstrumentation.SuspendState: output.AppendLine(FmtOpcodeIndent(opcode) + ".. suspend execution state .."); break; case EScriptInstrumentation.PopState: output.AppendLine(FmtOpcodeIndent(opcode) + ".. pop execution state .."); break; case EScriptInstrumentation.TunnelEndOfThread: output.AppendLine(FmtOpcodeIndent(opcode) + ".. tunnel end of thread .."); break; } break; } case EExprToken.EX_Tracepoint: { output.AppendLine(FmtOpcodeIndent(opcode) + ".. debug site .."); break; } case EExprToken.EX_SwitchValue: { ushort numCases = ReadUInt16(); uint afterSkip = ReadSkipCount(); output.AppendLine(FmtOpcodeIndent(opcode) + "Switch Value " + numCases + " cases, end in " + FmtSkipCount(afterSkip)); AddIndent(); output.AppendLine(indents + " Index:"); SerializeExpr(); for (ushort caseIndex = 0; caseIndex < numCases; ++caseIndex) { output.AppendLine(indents + " [" + caseIndex + "] Case Index (label: " + FmtScriptIndex(scriptIndex) + ")"); SerializeExpr(); // case index value term uint offsetToNextCase = ReadSkipCount(); output.AppendLine(indents + " [" + caseIndex + "] Offset to the next case: " + FmtSkipCount(offsetToNextCase)); output.AppendLine(indents + " [" + caseIndex + "] Case Result:"); SerializeExpr(); // case term } output.AppendLine(indents + " Default result (label: " + FmtScriptIndex(scriptIndex) + ")"); SerializeExpr(); output.AppendLine(indents + " (label: " + FmtScriptIndex(scriptIndex) + ")"); DropIndent(); break; } case EExprToken.EX_ArrayGetByRef: { output.AppendLine(FmtOpcodeIndent(opcode) + "Array Get-by-Ref Index"); AddIndent(); SerializeExpr(); SerializeExpr(); DropIndent(); break; } default: { string error = "Unknown bytecode 0x" + ((byte)opcode).ToString("X2") + "; ignoring it"; output.AppendLine(FmtOpcodeIndent(opcode) + "!!!" + error); FMessage.Log(ELogVerbosity.Warning, error); } break; } }
/// <summary> /// Appends property info in the native type info loader function used to get the offsets / addresses of members /// </summary> private void AppendPropertyOffsetNativeTypeLoader(CSharpTextBuilder offsetsBuilder, string propertyName, UProperty property, string functionName) { string ownerAddressName = null; if (!string.IsNullOrEmpty(functionName)) { ownerAddressName = functionName + Settings.VarNames.FunctionAddress; } else { ownerAddressName = Settings.VarNames.ClassAddress; } if (RequiresNativePropertyField(property)) { // XXXX_PropertyAddress (addres of the property) // NativeReflection.GetPropertyRef(ref XXXX_PropertyAddress, classAddress, "propertyName"); offsetsBuilder.AppendLine(Names.NativeReflectionCached_GetPropertyRef + "(ref " + propertyName + Settings.VarNames.PropertyAddress + ", " + ownerAddressName + ", \"" + property.GetName() + "\");"); } // XXXX_Offset (offset of the property) offsetsBuilder.AppendLine(propertyName + Settings.VarNames.MemberOffset + " = " + Names.NativeReflectionCached_GetPropertyOffset + "(" + ownerAddressName + ", \"" + property.GetName() + "\");"); if (Settings.GenerateIsValidSafeguards) { string propertyClassName; if (!NativeReflection.TryGetPropertyClassName(property.PropertyType, out propertyClassName)) { propertyClassName = "UNKNOWN"; } // XXXX_IsValid = NativeReflection.ValidatePropertyClass(classAddress, "propertyName", Classes.UXXXXProperty); offsetsBuilder.AppendLine(propertyName + Settings.VarNames.IsValid + " = " + Names.NativeReflectionCached_ValidatePropertyClass + "(" + ownerAddressName + ", \"" + property.GetName() + "\", " + Names.Classes + "." + propertyClassName + ");"); } }
private string GetFunctionSignature(UnrealModuleInfo module, UFunction function, UStruct owner, string customFunctionName, string customModifiers, bool stripAdditionalText, bool isImplementationMethod, List <string> namespaces) { bool isInterface = owner != null && owner.IsChildOf <UInterface>(); bool isDelegate = function.HasAnyFunctionFlags(EFunctionFlags.Delegate | EFunctionFlags.MulticastDelegate); bool isStatic = function.HasAnyFunctionFlags(EFunctionFlags.Static); bool isBlueprintType = owner != null && owner.IsA <UBlueprintGeneratedClass>(); StringBuilder modifiers = new StringBuilder(); if (!string.IsNullOrEmpty(customModifiers)) { modifiers.Append(customModifiers); } else if (isInterface) { // Don't provide any modifiers for interfaces if there isn't one already provided } else { UFunction originalFunction; // NOTE: "isImplementationMethod" is talking about "_Implementation" methods. // "isInterfaceImplementation" is talking about regular methods which are implementations for a interface. bool isInterfaceImplementation; UClass originalOwner = GetOriginalFunctionOwner(function, out originalFunction, out isInterfaceImplementation); // All interface functions in the chain need to be public bool isInterfaceFunc = originalOwner != owner && originalOwner.HasAnyClassFlags(EClassFlags.Interface); if (isImplementationMethod || (function.HasAnyFunctionFlags(EFunctionFlags.Protected) && !isInterfaceFunc && !isDelegate)) { modifiers.Append("protected"); } else { modifiers.Append("public"); } if (isDelegate) { modifiers.Append(" delegate"); } if (isStatic) { modifiers.Append(" static"); } if (!isDelegate && !isStatic) { if (function.HasAnyFunctionFlags(EFunctionFlags.BlueprintEvent)) { UFunction superFunc = function.GetSuperFunction(); if (superFunc != null) { modifiers.Append(" override"); } else { // This have should been filtered out in CanExportFunction() Debug.Assert(originalOwner == owner || isInterfaceImplementation); // Explicit will have the _Implementation as virtual and the function declaration as // non-virtual (which is the same as C++) if (!Settings.UseExplicitImplementationMethods || isImplementationMethod) { modifiers.Append(" virtual"); } } } else { if (originalOwner != owner && !isInterfaceFunc) { // Add "new" if the parent class has a function with the same name but not BlueprintEvent. // (don't do this for interface functions as we are implementing the function not redefining it) modifiers.Append(" new"); } } } } string returnType = "void"; int numReturns = 0; StringBuilder parameters = new StringBuilder(); // index is the index into parameters string Dictionary <int, string> parameterDefaultsByIndex = new Dictionary <int, string>(); // Once this is true all parameters from that point should also have defaults bool hasDefaultParameters = false; // Blueprint can define ref/out parameters with default values, this can't be translated to code bool invalidDefaultParams = false; // Info so we can avoid param name conflicts Dictionary <UProperty, string> paramNames = GetParamNames(function); // Generic array parameters string[] arrayParamNames = function.GetCommaSeperatedMetaData("ArrayParam"); // Generic parameters depending on array type string[] arrayTypeDependentParamNames = function.GetCommaSeperatedMetaData("ArrayTypeDependentParams"); // AutoCreateRefTerm will force ref on given parameter names (comma seperated) string[] autoRefParamNames = function.GetCommaSeperatedMetaData("AutoCreateRefTerm"); // If this is a blueprint type try and getting the return value from the first out param (if there is only one out) UProperty blueprintReturnProperty = function.GetBlueprintReturnProperty(); bool firstParameter = true; foreach (KeyValuePair <UProperty, string> param in paramNames) { UProperty parameter = param.Key; string paramName = param.Value; string rawParamName = parameter.GetName(); if (!parameter.HasAnyPropertyFlags(EPropertyFlags.Parm)) { continue; } if (parameter.HasAnyPropertyFlags(EPropertyFlags.ReturnParm) || parameter == blueprintReturnProperty) { returnType = GetTypeName(parameter, namespaces); numReturns++; } else { if (firstParameter) { firstParameter = false; } else { parameters.Append(", "); } if (!parameter.HasAnyPropertyFlags(EPropertyFlags.ConstParm)) { if (parameter.HasAnyPropertyFlags(EPropertyFlags.ReferenceParm) || autoRefParamNames.Contains(rawParamName)) { parameters.Append("ref "); } else if (parameter.HasAnyPropertyFlags(EPropertyFlags.OutParm)) { parameters.Append("out "); } } string paramTypeName = GetTypeName(parameter, namespaces); if (arrayParamNames.Contains(rawParamName)) { int genericsIndex = paramTypeName.IndexOf('<'); if (genericsIndex >= 0) { paramTypeName = paramTypeName.Substring(0, genericsIndex) + "<T>"; } } else if (arrayTypeDependentParamNames.Contains(rawParamName)) { paramTypeName = "T"; } parameters.Append(paramTypeName + " " + paramName); if (!invalidDefaultParams) { string defaultValue = GetParamDefaultValue(function, parameter, paramTypeName, ref hasDefaultParameters, ref invalidDefaultParams); if (!string.IsNullOrEmpty(defaultValue) && !invalidDefaultParams) { if (isBlueprintType && (parameter.HasAnyPropertyFlags(EPropertyFlags.ReferenceParm | EPropertyFlags.OutParm) || autoRefParamNames.Contains(rawParamName))) { invalidDefaultParams = true; } else { if (!hasDefaultParameters) { hasDefaultParameters = true; } parameterDefaultsByIndex[parameters.Length] = " = " + defaultValue; } } } } } if (numReturns > 1) { FMessage.Log(ELogVerbosity.Error, "More than 1 return on function '" + function.GetPathName() + "'"); } // Insert the default parameters if they aren't invalid if (!invalidDefaultParams) { int offset = 0; foreach (KeyValuePair <int, string> parameterDefault in parameterDefaultsByIndex) { parameters.Insert(parameterDefault.Key + offset, parameterDefault.Value); offset += parameterDefault.Value.Length; } } string functionName = GetFunctionName(function); string additionalStr = string.Empty; if (isDelegate) { functionName = GetTypeNameDelegate(function); additionalStr = ";"; } //if (isInterface) //{ // additionalStr = ";"; //} if (isImplementationMethod) { functionName += Settings.VarNames.ImplementationMethod; } if (!string.IsNullOrEmpty(customFunctionName)) { functionName = customFunctionName; } if (stripAdditionalText) { additionalStr = string.Empty; } string generics = string.Empty; if (arrayParamNames.Length > 0 || arrayTypeDependentParamNames.Length > 0) { generics = "<T>"; } if (modifiers.Length > 0) { modifiers.Append(' '); } return(string.Format("{0}{1} {2}{3}({4}){5}", modifiers, returnType, functionName, generics, parameters, additionalStr)); }