• UnLua改进记录


    接上一回处理多个LUA状态机问题,暂时无法解决单个虚幻状态机对应多个LUA状态机问题,故先搁置,转而看看UnLua的设计,本文记录对其改进过程。

    UnLua里面有个非常便捷的功能,就是在蓝图编辑器界面可以直接生成LUA代码模板,开始以为是基于反射生成的,看了下发现其实是从内置的LUA文件复制的,
    非常不灵活,其内置了Actor,UserWidget等几种常用类型,但是对于有些自己项目中的C++反射类没法准确支持,只能机械地去复制Actor或UserWidget等父类LUA表。

    改动很简单,根据上一回的UClass相关描述,直接迭代UClass获取UFunction及其参数即可。代码如下:

    // Tencent is pleased to support the open source community by making UnLua available.
    // 
    // Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
    //
    // Licensed under the MIT License (the "License"); 
    // you may not use this file except in compliance with the License. You may obtain a copy of the License at
    //
    // http://opensource.org/licenses/MIT
    //
    // Unless required by applicable law or agreed to in writing, 
    // software distributed under the License is distributed on an "AS IS" BASIS, 
    // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
    // See the License for the specific language governing permissions and limitations under the License.
    
    #include "UnLuaPrivate.h"
    #include "Misc/FileHelper.h"
    #include "Engine/Blueprint.h"
    #include "Blueprint/UserWidget.h"
    #include "Animation/AnimInstance.h"
    #include "GameFramework/Actor.h"
    #include "Interfaces/IPluginManager.h"
    #include "PlatformFilemanager.h"
    
    void OpenLuaFileInTextEditor(FString InFileName);
    
    bool CreateLuaTemplateFileEx(UBlueprint* Blueprint);
    
    // create Lua template file for the selected blueprint
    bool CreateLuaTemplateFile(UBlueprint *Blueprint)
    {
        return CreateLuaTemplateFileEx(Blueprint);
    
        if (Blueprint)
        {
            UClass *Class = Blueprint->GeneratedClass;
            FString ClassName = Class->GetName();
            FString OuterPath = Class->GetPathName();
            int32 LastIndex;
            if (OuterPath.FindLastChar('/', LastIndex))
            {
                OuterPath = OuterPath.Left(LastIndex + 1);
            }
            OuterPath = OuterPath.RightChop(6);         // ignore "/Game/"
            FString FileName = FString::Printf(TEXT("%s%s%s.lua"), *GLuaSrcFullPath, *OuterPath, *ClassName);
            if (FPaths::FileExists(FileName))
            {
                UE_LOG(LogUnLua, Warning, TEXT("Lua file (%s) is already existed!"), *ClassName);
                return false;
            }
    
            static FString ContentDir = IPluginManager::Get().FindPlugin(TEXT("UnLua"))->GetContentDir();
    
            FString TemplateName;
            if (Class->IsChildOf(AActor::StaticClass()))
            {
                // default BlueprintEvents for Actor
                TemplateName = ContentDir + TEXT("/ActorTemplate.lua");
            }
            else if (Class->IsChildOf(UUserWidget::StaticClass()))
            {
                // default BlueprintEvents for UserWidget (UMG)
                TemplateName = ContentDir + TEXT("/UserWidgetTemplate.lua");
            }
            else if (Class->IsChildOf(UAnimInstance::StaticClass()))
            {
                // default BlueprintEvents for AnimInstance (animation blueprint)
                TemplateName = ContentDir + TEXT("/AnimInstanceTemplate.lua");
            }
            else if (Class->IsChildOf(UActorComponent::StaticClass()))
            {
                // default BlueprintEvents for ActorComponent
                TemplateName = ContentDir + TEXT("/ActorComponentTemplate.lua");
            }
    
            FString Content;
            FFileHelper::LoadFileToString(Content, *TemplateName);
            Content = Content.Replace(TEXT("TemplateName"), *ClassName);
    
            return FFileHelper::SaveStringToFile(Content, *FileName);
        }
        return false;
    }
    
    
    // create Lua template file for the selected blueprint
    bool CreateLuaTemplateFileEx(UBlueprint* Blueprint)
    {
    	if (Blueprint)
    	{
    		UClass* Class = Blueprint->GeneratedClass;
    		FString ClassName = Class->GetName();
    		FString OuterPath = Class->GetPathName();
    		int32 LastIndex;
    		if (OuterPath.FindLastChar('/', LastIndex))
    		{
    			OuterPath = OuterPath.Left(LastIndex + 1);
    		}
    		OuterPath = OuterPath.RightChop(6);         // ignore "/Game/"
    		FString FileName = FString::Printf(TEXT("%s%s%s.lua"), *GLuaSrcFullPath, *OuterPath, *ClassName);
    		if (FPlatformFileManager::Get().GetPlatformFile().FileSize(*FileName) > 1)
    		{
    			UE_LOG(LogUnLua, Warning, TEXT("Lua file (%s) is already existed!"), *ClassName);
                OpenLuaFileInTextEditor(FileName);
    			return false;
    		}
    
    		static FString ContentDir = IPluginManager::Get().FindPlugin(TEXT("UnLua"))->GetContentDir();
    		FString Content;
            FString CurrentTime = FDateTime::Now().ToString();
            FString ComputerUserName = FPlatformProcess::UserName(true);
            FString HeaderStr = FString::Printf(TEXT("
    --Author:%s
    --Date:%s
    
    require('UnLua')
    
    local %s = Class()
    "), *ComputerUserName, *CurrentTime, *ClassName);
            Content += HeaderStr;
            for (TFieldIterator<UFunction> Func(Class); Func; ++Func)
            {
                if (!Func->HasAnyFunctionFlags(FUNC_BlueprintEvent))
                {
                    continue;
                }
    
                FString ReturnType = FString("void");
                if (Func->GetReturnProperty())
                {
                    ReturnType = Func->GetReturnProperty()->GetCPPType();
                }
                FString FuncName = Func->GetName();
                FString ParamTypeList;
                FString ParamList;
    #if ENGINE_MINOR_VERSION < 25
                for (TFieldIterator<UProperty> Prop(*Func); Prop; ++Prop)
    #else
                for (TFieldIterator<FProperty> Prop(*Func); Prop; ++Prop)
    #endif
                {
                    if (!Prop->HasAnyPropertyFlags(CPF_OutParm))
                    {
                        if (ParamList.Len() > 0)
                        {
                            ParamList = ParamList + FString(", ") + Prop->GetName();
                            ParamTypeList = ParamTypeList + FString(", ") + Prop->GetCPPType();
                        }
                        else
                        {
                            ParamList = ParamList + Prop->GetName();
                            ParamTypeList = ParamTypeList + Prop->GetCPPType();
                        }
                    }
                }
    
                FString FuncStr = FString::Printf(TEXT("--%s(%s)
    --function %s:%s(%s)
    --end"),*ReturnType, *ParamTypeList, *ClassName, *FuncName, *ParamList);
                Content = Content + FString("
    ") + FuncStr + FString("
    ");
            }
    
            FString EndStr = FString::Printf(TEXT("
    return %s"), *ClassName);
            Content = Content + EndStr;
    
    		bool bValidFile = FFileHelper::SaveStringToFile(Content, *FileName);
            if (bValidFile)
            {
                OpenLuaFileInTextEditor(FileName);
            }
            return bValidFile;
    	}
    	return false;
    }
    
    
    void OpenLuaFileInTextEditor(FString InFileName)
    {
    #if PLATFORM_WINDOWS
    	TArray<FString> TextEditorPathList;
    	TextEditorPathList.Add(FString("C:\Program Files\Microsoft VS Code\Code.exe"));
    	TextEditorPathList.Add(FString("C:\Program Files\Notepad++\notepad++.exe"));
    	//fallback to windows notepad
    	TextEditorPathList.Add(FString("C:\Windows\notepad.exe"));
    	for (int32 Idx = 0; Idx < TextEditorPathList.Num(); ++Idx)
    	{
    		if (FPlatformFileManager::Get().GetPlatformFile().FileExists(*TextEditorPathList[Idx]))
    		{
    			uint32 OutPID = 0;
    			FPlatformProcess::CreateProc(*TextEditorPathList[Idx], *InFileName, true, false, false, &OutPID, 0, nullptr, nullptr);
    			break;
    		}
    	}
    
    #endif
    }
    
    

    修改点:
    1.新增了bool CreateLuaTemplateFileEx(UBlueprint* Blueprint)函数自动生成LUA文件,而不是机械复制几个固定的模板
    2.在判断目标文件已经存在时,改用判断文件大小,方便在VSCode清空文本并重新生成LUA文件
    3.目前只支持了BlueprintEvent标记的函数,包括BlueprintImplementation/BlueprintNativeEvent;可根据需要去掉限制
    4.为LUA函数生成对应c++函数签名,一眼便知函数返回值和各参数类型
    5.若在Windows系统,生成成功后会调用文本编辑器打开LUA文件

    效果如下:

    
    
    
    --Author:UserNameOnComputer
    --Date:2020.04.09-13.20.15
    
    require('UnLua')
    
    local BP_LuaCharacter_C = Class()
    
    --void(float)
    --function BP_LuaCharacter_C:OnWalkingOffLedge(TimeDelta)
    --end
    
    --void(FVector, bool, bool)
    --function BP_LuaCharacter_C:OnLaunched(LaunchVelocity, bXYOverride, bZOverride)
    --end
    
    --void()
    --function BP_LuaCharacter_C:OnLanded()
    --end
    
    --void()
    --function BP_LuaCharacter_C:OnJumped()
    --end
    
    --void(float)
    --function BP_LuaCharacter_C:K2_UpdateCustomMovement(DeltaTime)
    --end
    
    --void(float, float)
    --function BP_LuaCharacter_C:K2_OnStartCrouch(HalfHeightAdjust, ScaledHalfHeightAdjust)
    --end
    
    --void(TEnumAsByte<EMovementMode>, TEnumAsByte<EMovementMode>, uint8, uint8)
    --function BP_LuaCharacter_C:K2_OnMovementModeChanged(PrevMovementMode, NewMovementMode, PrevCustomMode, NewCustomMode)
    --end
    
    --void(float, float)
    --function BP_LuaCharacter_C:K2_OnEndCrouch(HalfHeightAdjust, ScaledHalfHeightAdjust)
    --end
    
    --bool()
    --function BP_LuaCharacter_C:CanJumpInternal()
    --end
    
    --void(AController*)
    --function BP_LuaCharacter_C:ReceiveUnpossessed(OldController)
    --end
    
    --void(AController*)
    --function BP_LuaCharacter_C:ReceivePossessed(NewController)
    --end
    
    --void()
    --function BP_LuaCharacter_C:UserConstructionScript()
    --end
    
    --void(float)
    --function BP_LuaCharacter_C:ReceiveTick(DeltaSeconds)
    --end
    
    --void(float, UDamageType*, FVector, AController*, AActor*)
    --function BP_LuaCharacter_C:ReceiveRadialDamage(DamageReceived, DamageType, Origin, InstigatedBy, DamageCauser)
    --end
    
    --void(float, UDamageType*, FVector, FVector, UPrimitiveComponent*, FName, FVector, AController*, AActor*)
    --function BP_LuaCharacter_C:ReceivePointDamage(Damage, DamageType, HitLocation, HitNormal, HitComponent, BoneName, ShotFromDirection, InstigatedBy, DamageCauser)
    --end
    
    --void(UPrimitiveComponent*, AActor*, UPrimitiveComponent*, bool, FVector, FVector, FVector)
    --function BP_LuaCharacter_C:ReceiveHit(MyComp, Other, OtherComp, bSelfMoved, HitLocation, HitNormal, NormalImpulse)
    --end
    
    --void(TEnumAsByte<EEndPlayReason::Type>)
    --function BP_LuaCharacter_C:ReceiveEndPlay(EndPlayReason)
    --end
    
    --void()
    --function BP_LuaCharacter_C:ReceiveDestroyed()
    --end
    
    --void()
    --function BP_LuaCharacter_C:ReceiveBeginPlay()
    --end
    
    --void(float, UDamageType*, AController*, AActor*)
    --function BP_LuaCharacter_C:ReceiveAnyDamage(Damage, DamageType, InstigatedBy, DamageCauser)
    --end
    
    --void(FKey)
    --function BP_LuaCharacter_C:ReceiveActorOnReleased(ButtonReleased)
    --end
    
    --void(TEnumAsByte<ETouchIndex::Type>)
    --function BP_LuaCharacter_C:ReceiveActorOnInputTouchLeave(FingerIndex)
    --end
    
    --void(TEnumAsByte<ETouchIndex::Type>)
    --function BP_LuaCharacter_C:ReceiveActorOnInputTouchEnter(FingerIndex)
    --end
    
    --void(TEnumAsByte<ETouchIndex::Type>)
    --function BP_LuaCharacter_C:ReceiveActorOnInputTouchEnd(FingerIndex)
    --end
    
    --void(TEnumAsByte<ETouchIndex::Type>)
    --function BP_LuaCharacter_C:ReceiveActorOnInputTouchBegin(FingerIndex)
    --end
    
    --void(FKey)
    --function BP_LuaCharacter_C:ReceiveActorOnClicked(ButtonPressed)
    --end
    
    --void(AActor*)
    --function BP_LuaCharacter_C:ReceiveActorEndOverlap(OtherActor)
    --end
    
    --void()
    --function BP_LuaCharacter_C:ReceiveActorEndCursorOver()
    --end
    
    --void(AActor*)
    --function BP_LuaCharacter_C:ReceiveActorBeginOverlap(OtherActor)
    --end
    
    --void()
    --function BP_LuaCharacter_C:ReceiveActorBeginCursorOver()
    --end
    
    --void()
    --function BP_LuaCharacter_C:K2_OnReset()
    --end
    
    --void(APlayerController*)
    --function BP_LuaCharacter_C:K2_OnEndViewTarget(PC)
    --end
    
    --void(APlayerController*)
    --function BP_LuaCharacter_C:K2_OnBecomeViewTarget(PC)
    --end
    
    --void(int32)
    --function BP_LuaCharacter_C:ExecuteUbergraph(EntryPoint)
    --end
    
    return BP_LuaCharacter_C
    
  • 相关阅读:
    memcached构建集群分析之一
    linux使用getopt解析参数
    setbuffer和freopen做一个简单的日志组件
    setbuf和freopen
    编码规范的重要性
    c++的操作符格式记录
    do{...}while(0)的作用
    CF div2 321 C
    CF div2 321 B
    CF div2 321 A
  • 原文地址:https://www.cnblogs.com/rpg3d/p/12666131.html
Copyright © 2020-2023  润新知