“初始化俯视角工程,带puerts,未编过”

This commit is contained in:
2024-12-01 02:11:25 +08:00
parent 04698dd585
commit 850d76173c
1491 changed files with 271579 additions and 0 deletions
@@ -0,0 +1,392 @@
/*
* Tencent is pleased to support the open source community by making Puerts available.
* Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved.
* Puerts is licensed under the BSD 3-Clause License, except for the third-party components listed in the file 'LICENSE' which may
* be subject to their corresponding license terms. This file is subject to the terms and conditions defined in file 'LICENSE',
* which is part of this source code package.
*/
#include "JSClassRegister.h"
#if USING_IN_UNREAL_ENGINE
#include "UObject/Class.h"
#endif
#include <map>
#include <cstring>
namespace PUERTS_NAMESPACE
{
template <class T>
static T* PropertyInfoDuplicate(T* Arr)
{
if (Arr == nullptr)
return nullptr;
int Count = 0;
;
while (true)
{
if (Arr[Count++].Name == nullptr)
break;
}
T* Ret = new T[Count];
::memcpy(Ret, Arr, sizeof(T) * Count);
return Ret;
}
JSClassDefinition* JSClassDefinitionDuplicate(const JSClassDefinition* ClassDefinition)
{
auto Ret = new JSClassDefinition;
::memcpy(Ret, ClassDefinition, sizeof(JSClassDefinition));
Ret->Methods = PropertyInfoDuplicate(ClassDefinition->Methods);
Ret->Functions = PropertyInfoDuplicate(ClassDefinition->Functions);
Ret->Properties = PropertyInfoDuplicate(ClassDefinition->Properties);
Ret->Variables = PropertyInfoDuplicate(ClassDefinition->Variables);
Ret->ConstructorInfos = PropertyInfoDuplicate(ClassDefinition->ConstructorInfos);
Ret->MethodInfos = PropertyInfoDuplicate(ClassDefinition->MethodInfos);
Ret->FunctionInfos = PropertyInfoDuplicate(ClassDefinition->FunctionInfos);
Ret->PropertyInfos = PropertyInfoDuplicate(ClassDefinition->PropertyInfos);
Ret->VariableInfos = PropertyInfoDuplicate(ClassDefinition->VariableInfos);
return Ret;
}
void JSClassDefinitionDelete(JSClassDefinition* ClassDefinition)
{
delete[] ClassDefinition->Methods;
delete[] ClassDefinition->Functions;
delete[] ClassDefinition->Properties;
delete[] ClassDefinition->Variables;
delete[] ClassDefinition->ConstructorInfos;
delete[] ClassDefinition->MethodInfos;
delete[] ClassDefinition->FunctionInfos;
delete[] ClassDefinition->PropertyInfos;
delete[] ClassDefinition->VariableInfos;
delete ClassDefinition;
}
class JSClassRegister
{
public:
JSClassRegister();
~JSClassRegister();
void RegisterClass(const JSClassDefinition& ClassDefinition);
void SetClassTypeInfo(const void* TypeId, const NamedFunctionInfo* ConstructorInfos, const NamedFunctionInfo* MethodInfos,
const NamedFunctionInfo* FunctionInfos, const NamedPropertyInfo* PropertyInfos, const NamedPropertyInfo* VariableInfos);
void ForeachRegisterClass(std::function<void(const JSClassDefinition* ClassDefinition)>);
const JSClassDefinition* FindClassByID(const void* TypeId);
void OnClassNotFound(pesapi_class_not_found_callback InCallback)
{
ClassNotFoundCallback = InCallback;
}
const JSClassDefinition* LoadClassByID(const void* TypeId)
{
if (!TypeId)
{
return nullptr;
}
auto clsDef = FindClassByID(TypeId);
if (!clsDef && ClassNotFoundCallback)
{
if (!ClassNotFoundCallback(TypeId))
{
return nullptr;
}
clsDef = FindClassByID(TypeId);
}
return clsDef;
}
const JSClassDefinition* FindCppTypeClassByName(const std::string& Name);
#if USING_IN_UNREAL_ENGINE
void RegisterAddon(const std::string& Name, AddonRegisterFunc RegisterFunc);
AddonRegisterFunc FindAddonRegisterFunc(const std::string& Name);
const JSClassDefinition* FindClassByType(UStruct* Type);
#endif
private:
std::map<const void*, JSClassDefinition*> CDataIdToClassDefinition;
std::map<std::string, JSClassDefinition*> CDataNameToClassDefinition;
pesapi_class_not_found_callback ClassNotFoundCallback = nullptr;
#if USING_IN_UNREAL_ENGINE
std::map<std::string, AddonRegisterFunc> AddonRegisterInfos;
std::map<FString, JSClassDefinition*> StructNameToClassDefinition;
#endif
};
JSClassRegister::JSClassRegister()
{
}
JSClassRegister::~JSClassRegister()
{
for (auto& KV : CDataIdToClassDefinition)
{
JSClassDefinitionDelete(KV.second);
}
CDataIdToClassDefinition.clear();
#if USING_IN_UNREAL_ENGINE
for (auto& KV : StructNameToClassDefinition)
{
JSClassDefinitionDelete(KV.second);
}
StructNameToClassDefinition.clear();
#endif
}
void JSClassRegister::RegisterClass(const JSClassDefinition& ClassDefinition)
{
if (ClassDefinition.TypeId && ClassDefinition.ScriptName)
{
auto cd_iter = CDataIdToClassDefinition.find(ClassDefinition.TypeId);
if (cd_iter != CDataIdToClassDefinition.end())
{
JSClassDefinitionDelete(cd_iter->second);
}
CDataIdToClassDefinition[ClassDefinition.TypeId] = JSClassDefinitionDuplicate(&ClassDefinition);
std::string SN = ClassDefinition.ScriptName;
CDataNameToClassDefinition[SN] = CDataIdToClassDefinition[ClassDefinition.TypeId];
CDataIdToClassDefinition[ClassDefinition.TypeId]->ScriptName = CDataNameToClassDefinition.find(SN)->first.c_str();
}
#if USING_IN_UNREAL_ENGINE
else if (ClassDefinition.UETypeName)
{
FString SN = UTF8_TO_TCHAR(ClassDefinition.UETypeName);
auto ud_iter = StructNameToClassDefinition.find(SN);
if (ud_iter != StructNameToClassDefinition.end())
{
JSClassDefinitionDelete(ud_iter->second);
}
StructNameToClassDefinition[SN] = JSClassDefinitionDuplicate(&ClassDefinition);
}
#endif
}
void SetReflectoinInfo(JSFunctionInfo* Methods, const NamedFunctionInfo* MethodInfos)
{
std::map<std::string, std::tuple<int, const NamedFunctionInfo*>> InfoMap;
const NamedFunctionInfo* MethodInfo = MethodInfos;
while (MethodInfo->Name)
{
auto Iter = InfoMap.find(MethodInfo->Name);
if (Iter == InfoMap.end())
{
InfoMap[MethodInfo->Name] = std::make_tuple(1, MethodInfo);
}
else
{
std::get<0>(Iter->second) = 2;
}
++MethodInfo;
}
JSFunctionInfo* Method = Methods;
while (Method->Name)
{
auto Iter = InfoMap.find(Method->Name);
if (Iter != InfoMap.end() && std::get<0>(Iter->second) == 1)
{
Method->ReflectionInfo = std::get<1>(Iter->second)->Type;
}
++Method;
}
}
void JSClassRegister::SetClassTypeInfo(const void* TypeId, const NamedFunctionInfo* ConstructorInfos,
const NamedFunctionInfo* MethodInfos, const NamedFunctionInfo* FunctionInfos, const NamedPropertyInfo* PropertyInfos,
const NamedPropertyInfo* VariableInfos)
{
auto ClassDef = const_cast<JSClassDefinition*>(FindClassByID(TypeId));
if (ClassDef)
{
ClassDef->ConstructorInfos = PropertyInfoDuplicate(const_cast<NamedFunctionInfo*>(ConstructorInfos));
ClassDef->MethodInfos = PropertyInfoDuplicate(const_cast<NamedFunctionInfo*>(MethodInfos));
ClassDef->FunctionInfos = PropertyInfoDuplicate(const_cast<NamedFunctionInfo*>(FunctionInfos));
ClassDef->PropertyInfos = PropertyInfoDuplicate(const_cast<NamedPropertyInfo*>(PropertyInfos));
ClassDef->VariableInfos = PropertyInfoDuplicate(const_cast<NamedPropertyInfo*>(VariableInfos));
SetReflectoinInfo(ClassDef->Methods, ClassDef->MethodInfos);
SetReflectoinInfo(ClassDef->Functions, ClassDef->FunctionInfos);
}
}
const JSClassDefinition* JSClassRegister::FindClassByID(const void* TypeId)
{
if (!TypeId)
{
return nullptr;
}
auto Iter = CDataIdToClassDefinition.find(TypeId);
if (Iter == CDataIdToClassDefinition.end())
{
return nullptr;
}
else
{
return Iter->second;
}
}
const JSClassDefinition* JSClassRegister::FindCppTypeClassByName(const std::string& Name)
{
auto Iter = CDataNameToClassDefinition.find(Name);
if (Iter == CDataNameToClassDefinition.end())
{
return nullptr;
}
else
{
return Iter->second;
}
}
#if USING_IN_UNREAL_ENGINE
void JSClassRegister::RegisterAddon(const std::string& Name, AddonRegisterFunc RegisterFunc)
{
AddonRegisterInfos[Name] = RegisterFunc;
}
AddonRegisterFunc JSClassRegister::FindAddonRegisterFunc(const std::string& Name)
{
auto Iter = AddonRegisterInfos.find(Name);
if (Iter == AddonRegisterInfos.end())
{
return nullptr;
}
else
{
return Iter->second;
}
}
const JSClassDefinition* JSClassRegister::FindClassByType(UStruct* Type)
{
auto Iter = StructNameToClassDefinition.find(Type->GetName());
if (Iter == StructNameToClassDefinition.end())
{
return nullptr;
}
else
{
return Iter->second;
}
}
#endif
void JSClassRegister::ForeachRegisterClass(std::function<void(const JSClassDefinition* ClassDefinition)> Callback)
{
for (auto& KV : CDataNameToClassDefinition)
{
Callback(KV.second);
}
#if USING_IN_UNREAL_ENGINE
for (auto& KV : StructNameToClassDefinition)
{
Callback(KV.second);
}
#endif
}
JSClassRegister* GetJSClassRegister()
{
static JSClassRegister S_JSClassRegister;
return &S_JSClassRegister;
}
void RegisterJSClass(const JSClassDefinition& ClassDefinition)
{
GetJSClassRegister()->RegisterClass(ClassDefinition);
}
void SetClassTypeInfo(const void* TypeId, const NamedFunctionInfo* ConstructorInfos, const NamedFunctionInfo* MethodInfos,
const NamedFunctionInfo* FunctionInfos, const NamedPropertyInfo* PropertyInfos, const NamedPropertyInfo* VariableInfos)
{
GetJSClassRegister()->SetClassTypeInfo(TypeId, ConstructorInfos, MethodInfos, FunctionInfos, PropertyInfos, VariableInfos);
}
void ForeachRegisterClass(std::function<void(const JSClassDefinition* ClassDefinition)> Callback)
{
GetJSClassRegister()->ForeachRegisterClass(Callback);
}
const JSClassDefinition* FindClassByID(const void* TypeId)
{
return GetJSClassRegister()->FindClassByID(TypeId);
}
void OnClassNotFound(pesapi_class_not_found_callback Callback)
{
GetJSClassRegister()->OnClassNotFound(Callback);
}
const JSClassDefinition* LoadClassByID(const void* TypeId)
{
return GetJSClassRegister()->LoadClassByID(TypeId);
}
const JSClassDefinition* FindCppTypeClassByName(const std::string& Name)
{
return GetJSClassRegister()->FindCppTypeClassByName(Name);
}
bool TraceObjectLifecycle(const void* TypeId, pesapi_on_native_object_enter OnEnter, pesapi_on_native_object_exit OnExit)
{
if (auto clsDef = const_cast<JSClassDefinition*>(GetJSClassRegister()->FindClassByID(TypeId)))
{
clsDef->OnEnter = OnEnter;
clsDef->OnExit = OnExit;
return true;
}
return false;
}
#if USING_IN_UNREAL_ENGINE
bool IsEditorOnlyUFunction(const UFunction* Func)
{
// a simplified version of IsEditorOnlyObject(), sadly it's a EditorOnly Function so I have to reimplement a toy one
if (!Func)
{
return false;
}
if (Func->HasAnyFunctionFlags(FUNC_EditorOnly))
{
return true;
}
auto InObject = Func;
if (InObject->HasAnyMarks(OBJECTMARK_EditorOnly) || InObject->IsEditorOnly())
{
return true;
}
auto Package = Func->GetPackage();
if (Package && Package->HasAnyPackageFlags(PKG_EditorOnly))
{
return true;
}
return false;
}
void RegisterAddon(const char* Name, AddonRegisterFunc RegisterFunc)
{
GetJSClassRegister()->RegisterAddon(Name, RegisterFunc);
}
AddonRegisterFunc FindAddonRegisterFunc(const std::string& Name)
{
return GetJSClassRegister()->FindAddonRegisterFunc(Name);
}
const JSClassDefinition* FindClassByType(UStruct* Type)
{
return GetJSClassRegister()->FindClassByType(Type);
}
#endif
} // namespace PUERTS_NAMESPACE