FString FScriptCodeGeneratorBase::GenerateFunctionDispatch(UFunction* Function) { FString Params; const bool bHasParamsOrReturnValue = (Function->Children != NULL); if (bHasParamsOrReturnValue) { Params += TEXT("\tstruct FDispatchParams\r\n\t{\r\n"); for (TFieldIterator<UProperty> ParamIt(Function); ParamIt; ++ParamIt) { UProperty* Param = *ParamIt; Params += FString::Printf(TEXT("\t\t%s %s;\r\n"), *GetPropertyTypeCPP(Param, CPPF_ArgumentOrReturnValue), *Param->GetName()); } Params += TEXT("\t} Params;\r\n"); int32 ParamIndex = 0; for (TFieldIterator<UProperty> ParamIt(Function); ParamIt; ++ParamIt, ++ParamIndex) { UProperty* Param = *ParamIt; Params += FString::Printf(TEXT("\tParams.%s = %s;\r\n"), *Param->GetName(), *InitializeFunctionDispatchParam(Function, Param, ParamIndex)); } } Params += FString::Printf(TEXT("\tstatic UFunction* Function = Obj->FindFunctionChecked(TEXT(\"%s\"));\r\n"), *Function->GetName()); if (bHasParamsOrReturnValue) { Params += TEXT("\tcheck(Function->ParmsSize == sizeof(FDispatchParams));\r\n"); Params += TEXT("\tObj->ProcessEvent(Function, &Params);\r\n"); } else { Params += TEXT("\tObj->ProcessEvent(Function, NULL);\r\n"); } return Params; }
FString FScriptCodeGeneratorBase::InitializeFunctionDispatchParam(UFunction* Function, UProperty* Param, int32 ParamIndex) { if (Param->IsA(UObjectPropertyBase::StaticClass()) || Param->IsA(UClassProperty::StaticClass())) { return TEXT("NULL"); } else { return FString::Printf(TEXT("%s()"), *GetPropertyTypeCPP(Param, CPPF_ArgumentOrReturnValue)); } }
FString FLuaScriptCodeGenerator::ExportProperty(const FString& ClassNameCPP, UClass* Class, UProperty* Property, int32 PropertyIndex) { FString PropertyName = Property->GetName(); UProperty* ReturnValue = NULL; UClass* PropertySuper = NULL; if (Property->GetOwnerClass() != Class) { // Find the base class where this property was defined if (ExportedClasses.Contains(Property->GetOwnerClass()->GetFName())) { PropertySuper = Property->GetOwnerClass(); } } // Getter FString GetterName = FString::Printf(TEXT("Get_%s"), *PropertyName); FString GeneratedGlue = GenerateWrapperFunctionDeclaration(ClassNameCPP, Class, GetterName); GeneratedGlue += TEXT("\r\n{\r\n"); FString FunctionBody; if (PropertySuper == NULL) { FunctionBody += FString::Printf(TEXT("\t%s\r\n"), *GenerateObjectDeclarationFromContext(ClassNameCPP, Class)); FunctionBody += FString::Printf(TEXT("\tstatic UProperty* Property = FindScriptPropertyHelper(%s::StaticClass(), TEXT(\"%s\"));\r\n"), *ClassNameCPP, *Property->GetName()); FunctionBody += FString::Printf(TEXT("\t%s PropertyValue;\r\n"), *GetPropertyTypeCPP(Property, CPPF_ArgumentOrReturnValue)); FunctionBody += TEXT("\tProperty->CopyCompleteValue(&PropertyValue, Property->ContainerPtrToValuePtr<void>(Obj));\r\n"); FunctionBody += FString::Printf(TEXT("\t%s\r\n"), *GenerateReturnValueHandler(ClassNameCPP, Class, NULL, Property, TEXT("PropertyValue"))); } else { FunctionBody = FString::Printf(TEXT("\treturn %s_%s(InScriptContext);\r\n"), *PropertySuper->GetName(), *GetterName); } GeneratedGlue += FunctionBody; GeneratedGlue += TEXT("}\r\n\r\n"); FunctionBody.Empty(FunctionBody.Len()); // Store the name of this getter as well as the name of the wrapper function FPropertyAccessor Getter; Getter.AccessorName = GetterName; Getter.FunctionName = FString::Printf(TEXT("%s_%s"), *Class->GetName(), *GetterName); auto& Exports = ClassExportedProperties.FindOrAdd(Class); Exports.Add(Getter); // Setter FString SetterName = FString::Printf(TEXT("Set_%s"), *PropertyName); GeneratedGlue += GenerateWrapperFunctionDeclaration(ClassNameCPP, Class, SetterName); GeneratedGlue += TEXT("\r\n{\r\n"); if (PropertySuper == NULL) { FunctionBody += FString::Printf(TEXT("\t%s\r\n"), *GenerateObjectDeclarationFromContext(ClassNameCPP, Class)); FunctionBody += FString::Printf(TEXT("\tstatic UProperty* Property = FindScriptPropertyHelper(%s::StaticClass(), TEXT(\"%s\"));\r\n"), *ClassNameCPP, *Property->GetName()); FunctionBody += FString::Printf(TEXT("\t%s PropertyValue = %s;\r\n"), *GetPropertyTypeCPP(Property, CPPF_ArgumentOrReturnValue), *InitializeFunctionDispatchParam(NULL, Property, 0)); FunctionBody += TEXT("\tProperty->CopyCompleteValue(Property->ContainerPtrToValuePtr<void>(Obj), &PropertyValue);\r\n"); FunctionBody += TEXT("\treturn 0;\r\n"); } else { FunctionBody = FString::Printf(TEXT("\treturn %s_%s(InScriptContext);\r\n"), *PropertySuper->GetName(), *SetterName); } GeneratedGlue += FunctionBody; GeneratedGlue += TEXT("}\r\n\r\n"); // Store the name of this setter as well as the name of the wrapper function FPropertyAccessor Setter; Setter.AccessorName = SetterName; Setter.FunctionName = FString::Printf(TEXT("%s_%s"), *Class->GetName(), *SetterName); Exports.Add(Setter); return GeneratedGlue; }
FString FLuaScriptCodeGenerator::InitializeFunctionDispatchParam(UFunction* Function, UProperty* Param, int32 ParamIndex) { if (!(Param->GetPropertyFlags() & CPF_ReturnParm)) { FString Initializer; // In Lua, the first param index on the stack is 1 and it's the object we're invoking the function on ParamIndex += 2; if (Param->IsA(UIntProperty::StaticClass())) { Initializer = TEXT("(luaL_checkint"); } else if (Param->IsA(UFloatProperty::StaticClass())) { Initializer = TEXT("(float)(luaL_checknumber"); } else if (Param->IsA(UStrProperty::StaticClass())) { Initializer = TEXT("ANSI_TO_TCHAR(luaL_checkstring"); } else if (Param->IsA(UNameProperty::StaticClass())) { Initializer = TEXT("FName(luaL_checkstring"); } else if (Param->IsA(UBoolProperty::StaticClass())) { Initializer = TEXT("!!(lua_toboolean"); } else if (Param->IsA(UStructProperty::StaticClass())) { UStructProperty* StructProp = CastChecked<UStructProperty>(Param); if (StructProp->Struct->GetFName() == Name_Vector2D) { Initializer = TEXT("(FLuaVector2D::Get"); } else if (StructProp->Struct->GetFName() == Name_Vector) { Initializer = TEXT("(FLuaVector::Get"); } else if (StructProp->Struct->GetFName() == Name_Vector4) { Initializer = TEXT("(FLuaVector4::Get"); } else if (StructProp->Struct->GetFName() == Name_Quat) { Initializer = TEXT("(FLuaQuat::Get"); } else if (StructProp->Struct->GetFName() == Name_LinearColor) { Initializer = TEXT("(FLuaLinearColor::Get"); } else if (StructProp->Struct->GetFName() == Name_Color) { Initializer = TEXT("FColor(FLuaLinearColor::Get"); } else if (StructProp->Struct->GetFName() == Name_Transform) { Initializer = TEXT("(FLuaTransform::Get"); } else { FError::Throwf(TEXT("Unsupported function param struct type: %s"), *StructProp->Struct->GetName()); } } else if (Param->IsA(UClassProperty::StaticClass())) { Initializer = TEXT("(UClass*)(lua_touserdata"); } else if (Param->IsA(UObjectPropertyBase::StaticClass())) { Initializer = FString::Printf(TEXT("(%s)(lua_touserdata"), *GetPropertyTypeCPP(Param, CPPF_ArgumentOrReturnValue), ParamIndex); } else { FError::Throwf(TEXT("Unsupported function param type: %s"), *Param->GetClass()->GetName()); } return FString::Printf(TEXT("%s(InScriptContext, %d))"), *Initializer, ParamIndex); } else { return FScriptCodeGeneratorBase::InitializeFunctionDispatchParam(Function, Param, ParamIndex); } }