“初始化俯视角工程,带puerts,未编过”
This commit is contained in:
@@ -0,0 +1,162 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using EpicGames.UHT.Tables;
|
||||
using EpicGames.UHT.Types;
|
||||
using EpicGames.UHT.Utils;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using EpicGames.Core;
|
||||
|
||||
namespace CSharpParamDefaultValueMetas
|
||||
{
|
||||
[UnrealHeaderTool]
|
||||
class CSharpParamDefaultValueMetas
|
||||
{
|
||||
[UhtExporter(Name = "Puerts", Description = "Puerts Default Values Collector", Options = UhtExporterOptions.Default, ModuleName = "JsEnv")]
|
||||
private static void UnLuaDefaultParamCollectorUbtPluginExporter(IUhtExportFactory factory)
|
||||
{
|
||||
var paramDefaultValueMetas = new CSharpParamDefaultValueMetas(factory);
|
||||
|
||||
paramDefaultValueMetas.Generate();
|
||||
|
||||
bool bHasGameRuntime = (from package in factory.Session.Packages where package.Module.ModuleType == UHTModuleType.GameRuntime select package).Any();
|
||||
paramDefaultValueMetas.OutputIfNeeded(bHasGameRuntime);
|
||||
}
|
||||
|
||||
private IUhtExportFactory Factory;
|
||||
private BorrowStringBuilder BSB;
|
||||
private StringBuilder GeneratedContentBuilder => BSB.StringBuilder;
|
||||
|
||||
public CSharpParamDefaultValueMetas(IUhtExportFactory factory)
|
||||
{
|
||||
Factory = factory;
|
||||
BSB = new BorrowStringBuilder(StringBuilderCache.Big);
|
||||
}
|
||||
|
||||
IEnumerable<UhtType> TraverseTree(UhtType parentNode)
|
||||
{
|
||||
yield return parentNode;
|
||||
|
||||
if (parentNode.Children != null)
|
||||
{
|
||||
foreach (UhtType childNode in parentNode.Children.SelectMany(TraverseTree))
|
||||
{
|
||||
yield return childNode;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void Generate()
|
||||
{
|
||||
GeneratedContentBuilder.Append("// Generated By C# UbtPlugin\r\n");
|
||||
|
||||
var packages = (from package in Factory.Session.Packages
|
||||
where (package.Module.ModuleType == UHTModuleType.EngineRuntime || package.Module.ModuleType == UHTModuleType.GameRuntime)
|
||||
select package);
|
||||
|
||||
var classes = packages
|
||||
.SelectMany(TraverseTree)
|
||||
.Where(t => t is UhtClass).Cast<UhtClass>()
|
||||
.Where(c => !c.ClassFlags.HasAnyFlags(EClassFlags.Interface));
|
||||
|
||||
classes.Distinct().OrderBy(c => c.SourceName).ToList().ForEach(ExportClass);
|
||||
}
|
||||
|
||||
private void ExportClass(UhtClass uhtClass)
|
||||
{
|
||||
bool declared = false;
|
||||
|
||||
Action declareOnce = () => {
|
||||
if (!declared)
|
||||
{
|
||||
GeneratedContentBuilder.AppendFormat("PC = &ParamDefaultMetas.Add(TEXT(\"{0}\"));\r\n", uhtClass.EngineName);
|
||||
declared = true;
|
||||
}
|
||||
};
|
||||
|
||||
foreach (UhtFunction uhtFunction in uhtClass.Functions.OrderBy(Func => Func.SourceName))
|
||||
{
|
||||
if (!uhtFunction.MetaData.IsEmpty())
|
||||
{
|
||||
ExportFunction(uhtFunction, declareOnce);
|
||||
}
|
||||
}
|
||||
|
||||
if (declared)
|
||||
{
|
||||
GeneratedContentBuilder.Append("\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
private static bool TryGetDefaultValue(UhtMetaData metaData, UhtProperty property, out string value)
|
||||
{
|
||||
var hasValue = metaData.TryGetValue(property.SourceName, out string? tempValue);
|
||||
if (!hasValue)
|
||||
{
|
||||
var cppKey = "CPP_Default_" + property.SourceName;
|
||||
hasValue = metaData.TryGetValue(cppKey, out tempValue);
|
||||
}
|
||||
value = tempValue ?? string.Empty;
|
||||
return hasValue;
|
||||
}
|
||||
|
||||
private void ExportFunction(UhtFunction uhtFunction, Action declareClassOnce)
|
||||
{
|
||||
bool declared = false;
|
||||
|
||||
var properties = uhtFunction.Children
|
||||
.Where(c => c is UhtProperty)
|
||||
.Cast<UhtProperty>()
|
||||
.Where(p => p.PropertyFlags.HasAnyFlags(EPropertyFlags.Parm) && !p.PropertyFlags.HasAnyFlags(EPropertyFlags.ReturnParm));
|
||||
|
||||
foreach (var property in properties.OrderBy(Property => Property.SourceName))
|
||||
{
|
||||
if (TryGetDefaultValue(uhtFunction.MetaData, property, out string defaultValue))
|
||||
{
|
||||
declareClassOnce();
|
||||
if (!declared)
|
||||
{
|
||||
GeneratedContentBuilder.AppendFormat("PF = &PC->Add(TEXT(\"{0}\"));\r\n", uhtFunction.SourceName);
|
||||
declared = true;
|
||||
}
|
||||
|
||||
string escapeDefaultValue = defaultValue.Replace("\"", "\\\"");
|
||||
if (property is UhtBoolProperty)
|
||||
{
|
||||
escapeDefaultValue = escapeDefaultValue.Replace("true", "True").Replace("false", "False");
|
||||
}
|
||||
GeneratedContentBuilder.AppendFormat("PF->Add(TEXT(\"{0}\"), TEXT(\"{1}\"));\r\n", property.SourceName, escapeDefaultValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OutputIfNeeded(bool bHasGameRuntime)
|
||||
{
|
||||
string filePath = Factory.MakePath("InitParamDefaultMetas", ".inl");
|
||||
|
||||
if (File.Exists(filePath))
|
||||
{
|
||||
var fileContent = File.ReadAllText(filePath);
|
||||
if (bHasGameRuntime ? (!fileContent.Equals(GeneratedContentBuilder.ToString())) : (fileContent.Length != 0))
|
||||
{
|
||||
Factory.CommitOutput(filePath, GeneratedContentBuilder);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Factory.CommitOutput(filePath, GeneratedContentBuilder);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Import Project="CSharpParamDefaultValueMetas.ubtplugin.csproj.props" Condition="Exists('CSharpParamDefaultValueMetas.ubtplugin.csproj.props')" />
|
||||
<Import Project="$(EngineDir)\Source\Programs\Shared\UnrealEngine.csproj.props" />
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Development</Configuration>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<GenerateTargetFrameworkAttribute>false</GenerateTargetFrameworkAttribute>
|
||||
<Configurations>Debug;Release;Development</Configurations>
|
||||
<RootNamespace>CSharpParamDefaultValueMetas</RootNamespace>
|
||||
<AssemblyName>CSharpParamDefaultValueMetas</AssemblyName>
|
||||
<OutputPath>..\..\..\..\Binaries\DotNET\UnrealBuildTool\Plugins\CSharpParamDefaultValueMetas\</OutputPath>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Development|AnyCPU' ">
|
||||
<DefineConstants>$(DefineConstants);TRACE</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DefineConstants>$(DefineConstants);TRACE</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DefineConstants>$(DefineConstants);DEBUG;TRACE</DefineConstants>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="EpicGames.Build">
|
||||
<HintPath>$(EngineDir)\Binaries\DotNET\UnrealBuildTool\EpicGames.Build.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="EpicGames.Core">
|
||||
<HintPath>$(EngineDir)\Binaries\DotNET\UnrealBuildTool\EpicGames.Core.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="EpicGames.UHT">
|
||||
<HintPath>$(EngineDir)\Binaries\DotNET\UnrealBuildTool\EpicGames.UHT.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="UnrealBuildTool">
|
||||
<HintPath>$(EngineDir)\Binaries\DotNET\UnrealBuildTool\UnrealBuildTool.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<EngineDir Condition="'$(EngineDir)' == ''">D:\MiceCola\UE_5.5\Engine</EngineDir>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
+93
@@ -0,0 +1,93 @@
|
||||
{
|
||||
"format": 1,
|
||||
"restore": {
|
||||
"D:\\MiceCola\\MingSimulator\\Plugins\\Puerts\\Source\\CSharpParamDefaultValueMetas\\CSharpParamDefaultValueMetas.ubtplugin.csproj": {}
|
||||
},
|
||||
"projects": {
|
||||
"D:\\MiceCola\\MingSimulator\\Plugins\\Puerts\\Source\\CSharpParamDefaultValueMetas\\CSharpParamDefaultValueMetas.ubtplugin.csproj": {
|
||||
"version": "1.0.0",
|
||||
"restore": {
|
||||
"projectUniqueName": "D:\\MiceCola\\MingSimulator\\Plugins\\Puerts\\Source\\CSharpParamDefaultValueMetas\\CSharpParamDefaultValueMetas.ubtplugin.csproj",
|
||||
"projectName": "CSharpParamDefaultValueMetas",
|
||||
"projectPath": "D:\\MiceCola\\MingSimulator\\Plugins\\Puerts\\Source\\CSharpParamDefaultValueMetas\\CSharpParamDefaultValueMetas.ubtplugin.csproj",
|
||||
"packagesPath": "C:\\Users\\张青\\.nuget\\packages\\",
|
||||
"outputPath": "D:\\MiceCola\\MingSimulator\\Plugins\\Puerts\\Source\\CSharpParamDefaultValueMetas\\obj\\",
|
||||
"projectStyle": "PackageReference",
|
||||
"fallbackFolders": [
|
||||
"C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages"
|
||||
],
|
||||
"configFilePaths": [
|
||||
"C:\\Users\\张青\\AppData\\Roaming\\NuGet\\NuGet.Config",
|
||||
"C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.FallbackLocation.config",
|
||||
"C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.Offline.config"
|
||||
],
|
||||
"originalTargetFrameworks": [
|
||||
"net6.0"
|
||||
],
|
||||
"sources": {
|
||||
"C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\": {},
|
||||
"https://api.nuget.org/v3/index.json": {}
|
||||
},
|
||||
"frameworks": {
|
||||
"net6.0": {
|
||||
"targetAlias": "net6.0",
|
||||
"projectReferences": {}
|
||||
}
|
||||
},
|
||||
"warningProperties": {
|
||||
"allWarningsAsErrors": true,
|
||||
"warnAsError": [
|
||||
"NU1605"
|
||||
]
|
||||
},
|
||||
"restoreAuditProperties": {
|
||||
"enableAudit": "true",
|
||||
"auditLevel": "low",
|
||||
"auditMode": "direct"
|
||||
}
|
||||
},
|
||||
"frameworks": {
|
||||
"net6.0": {
|
||||
"targetAlias": "net6.0",
|
||||
"dependencies": {
|
||||
"Microsoft.CSharp": {
|
||||
"target": "Package",
|
||||
"version": "[4.7.0, )"
|
||||
}
|
||||
},
|
||||
"imports": [
|
||||
"net461",
|
||||
"net462",
|
||||
"net47",
|
||||
"net471",
|
||||
"net472",
|
||||
"net48",
|
||||
"net481"
|
||||
],
|
||||
"assetTargetFallback": true,
|
||||
"warn": true,
|
||||
"downloadDependencies": [
|
||||
{
|
||||
"name": "Microsoft.AspNetCore.App.Ref",
|
||||
"version": "[6.0.30, 6.0.30]"
|
||||
},
|
||||
{
|
||||
"name": "Microsoft.NETCore.App.Ref",
|
||||
"version": "[6.0.30, 6.0.30]"
|
||||
},
|
||||
{
|
||||
"name": "Microsoft.WindowsDesktop.App.Ref",
|
||||
"version": "[6.0.30, 6.0.30]"
|
||||
}
|
||||
],
|
||||
"frameworkReferences": {
|
||||
"Microsoft.NETCore.App": {
|
||||
"privateAssets": "all"
|
||||
}
|
||||
},
|
||||
"runtimeIdentifierGraphPath": "D:\\MiceCola\\UE_5.5\\Engine\\Binaries\\ThirdParty\\DotNet\\8.0.300\\win-x64\\sdk\\8.0.300\\RuntimeIdentifierGraph.json"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
||||
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
|
||||
<RestoreSuccess Condition=" '$(RestoreSuccess)' == '' ">True</RestoreSuccess>
|
||||
<RestoreTool Condition=" '$(RestoreTool)' == '' ">NuGet</RestoreTool>
|
||||
<ProjectAssetsFile Condition=" '$(ProjectAssetsFile)' == '' ">$(MSBuildThisFileDirectory)project.assets.json</ProjectAssetsFile>
|
||||
<NuGetPackageRoot Condition=" '$(NuGetPackageRoot)' == '' ">$(UserProfile)\.nuget\packages\</NuGetPackageRoot>
|
||||
<NuGetPackageFolders Condition=" '$(NuGetPackageFolders)' == '' ">C:\Users\张青\.nuget\packages\;C:\Program Files (x86)\Microsoft Visual Studio\Shared\NuGetPackages</NuGetPackageFolders>
|
||||
<NuGetProjectStyle Condition=" '$(NuGetProjectStyle)' == '' ">PackageReference</NuGetProjectStyle>
|
||||
<NuGetToolVersion Condition=" '$(NuGetToolVersion)' == '' ">6.10.0</NuGetToolVersion>
|
||||
</PropertyGroup>
|
||||
<ItemGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
|
||||
<SourceRoot Include="C:\Users\张青\.nuget\packages\" />
|
||||
<SourceRoot Include="C:\Program Files (x86)\Microsoft Visual Studio\Shared\NuGetPackages\" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
||||
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" />
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
is_global = true
|
||||
build_property.TargetFramework = net6.0
|
||||
build_property.TargetPlatformMinVersion =
|
||||
build_property.UsingMicrosoftNETSdkWeb =
|
||||
build_property.ProjectTypeGuids =
|
||||
build_property.InvariantGlobalization =
|
||||
build_property.PlatformNeutralAssembly =
|
||||
build_property.EnforceExtendedAnalyzerRules =
|
||||
build_property._SupportedPlatformList = Linux,macOS,Windows
|
||||
build_property.RootNamespace = CSharpParamDefaultValueMetas
|
||||
build_property.ProjectDir = D:\MiceCola\MingSimulator\Plugins\Puerts\Source\CSharpParamDefaultValueMetas\
|
||||
build_property.EnableComHosting =
|
||||
build_property.EnableGeneratedComInterfaceComImportInterop =
|
||||
build_property.EffectiveAnalysisLevelStyle = 6.0
|
||||
build_property.EnableCodeStyleSeverity =
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
+1
@@ -0,0 +1 @@
|
||||
acfc2ce6c21e11e243f1beb848c668c5ad8317be9df7ed1ce1347befd4c57e75
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
D:\MiceCola\MingSimulator\Plugins\Puerts\Source\CSharpParamDefaultValueMetas\obj\Development\CSharpParamDefaultValueMetas.ubtplugin.csproj.AssemblyReference.cache
|
||||
D:\MiceCola\MingSimulator\Plugins\Puerts\Source\CSharpParamDefaultValueMetas\obj\Development\CSharpParamDefaultValueMetas.ubtplugin.GeneratedMSBuildEditorConfig.editorconfig
|
||||
D:\MiceCola\MingSimulator\Plugins\Puerts\Source\CSharpParamDefaultValueMetas\obj\Development\CSharpParamDefaultValueMetas.ubtplugin.csproj.CoreCompileInputs.cache
|
||||
@@ -0,0 +1,181 @@
|
||||
{
|
||||
"version": 3,
|
||||
"targets": {
|
||||
"net6.0": {
|
||||
"Microsoft.CSharp/4.7.0": {
|
||||
"type": "package",
|
||||
"compile": {
|
||||
"ref/netcoreapp2.0/_._": {}
|
||||
},
|
||||
"runtime": {
|
||||
"lib/netcoreapp2.0/_._": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"libraries": {
|
||||
"Microsoft.CSharp/4.7.0": {
|
||||
"sha512": "pTj+D3uJWyN3My70i2Hqo+OXixq3Os2D1nJ2x92FFo6sk8fYS1m1WLNTs0Dc1uPaViH0YvEEwvzddQ7y4rhXmA==",
|
||||
"type": "package",
|
||||
"path": "microsoft.csharp/4.7.0",
|
||||
"files": [
|
||||
".nupkg.metadata",
|
||||
".signature.p7s",
|
||||
"LICENSE.TXT",
|
||||
"THIRD-PARTY-NOTICES.TXT",
|
||||
"lib/MonoAndroid10/_._",
|
||||
"lib/MonoTouch10/_._",
|
||||
"lib/net45/_._",
|
||||
"lib/netcore50/Microsoft.CSharp.dll",
|
||||
"lib/netcoreapp2.0/_._",
|
||||
"lib/netstandard1.3/Microsoft.CSharp.dll",
|
||||
"lib/netstandard2.0/Microsoft.CSharp.dll",
|
||||
"lib/netstandard2.0/Microsoft.CSharp.xml",
|
||||
"lib/portable-net45+win8+wp8+wpa81/_._",
|
||||
"lib/uap10.0.16299/_._",
|
||||
"lib/win8/_._",
|
||||
"lib/wp80/_._",
|
||||
"lib/wpa81/_._",
|
||||
"lib/xamarinios10/_._",
|
||||
"lib/xamarinmac20/_._",
|
||||
"lib/xamarintvos10/_._",
|
||||
"lib/xamarinwatchos10/_._",
|
||||
"microsoft.csharp.4.7.0.nupkg.sha512",
|
||||
"microsoft.csharp.nuspec",
|
||||
"ref/MonoAndroid10/_._",
|
||||
"ref/MonoTouch10/_._",
|
||||
"ref/net45/_._",
|
||||
"ref/netcore50/Microsoft.CSharp.dll",
|
||||
"ref/netcore50/Microsoft.CSharp.xml",
|
||||
"ref/netcore50/de/Microsoft.CSharp.xml",
|
||||
"ref/netcore50/es/Microsoft.CSharp.xml",
|
||||
"ref/netcore50/fr/Microsoft.CSharp.xml",
|
||||
"ref/netcore50/it/Microsoft.CSharp.xml",
|
||||
"ref/netcore50/ja/Microsoft.CSharp.xml",
|
||||
"ref/netcore50/ko/Microsoft.CSharp.xml",
|
||||
"ref/netcore50/ru/Microsoft.CSharp.xml",
|
||||
"ref/netcore50/zh-hans/Microsoft.CSharp.xml",
|
||||
"ref/netcore50/zh-hant/Microsoft.CSharp.xml",
|
||||
"ref/netcoreapp2.0/_._",
|
||||
"ref/netstandard1.0/Microsoft.CSharp.dll",
|
||||
"ref/netstandard1.0/Microsoft.CSharp.xml",
|
||||
"ref/netstandard1.0/de/Microsoft.CSharp.xml",
|
||||
"ref/netstandard1.0/es/Microsoft.CSharp.xml",
|
||||
"ref/netstandard1.0/fr/Microsoft.CSharp.xml",
|
||||
"ref/netstandard1.0/it/Microsoft.CSharp.xml",
|
||||
"ref/netstandard1.0/ja/Microsoft.CSharp.xml",
|
||||
"ref/netstandard1.0/ko/Microsoft.CSharp.xml",
|
||||
"ref/netstandard1.0/ru/Microsoft.CSharp.xml",
|
||||
"ref/netstandard1.0/zh-hans/Microsoft.CSharp.xml",
|
||||
"ref/netstandard1.0/zh-hant/Microsoft.CSharp.xml",
|
||||
"ref/netstandard2.0/Microsoft.CSharp.dll",
|
||||
"ref/netstandard2.0/Microsoft.CSharp.xml",
|
||||
"ref/portable-net45+win8+wp8+wpa81/_._",
|
||||
"ref/uap10.0.16299/_._",
|
||||
"ref/win8/_._",
|
||||
"ref/wp80/_._",
|
||||
"ref/wpa81/_._",
|
||||
"ref/xamarinios10/_._",
|
||||
"ref/xamarinmac20/_._",
|
||||
"ref/xamarintvos10/_._",
|
||||
"ref/xamarinwatchos10/_._",
|
||||
"useSharedDesignerContext.txt",
|
||||
"version.txt"
|
||||
]
|
||||
}
|
||||
},
|
||||
"projectFileDependencyGroups": {
|
||||
"net6.0": [
|
||||
"Microsoft.CSharp >= 4.7.0"
|
||||
]
|
||||
},
|
||||
"packageFolders": {
|
||||
"C:\\Users\\张青\\.nuget\\packages\\": {},
|
||||
"C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages": {}
|
||||
},
|
||||
"project": {
|
||||
"version": "1.0.0",
|
||||
"restore": {
|
||||
"projectUniqueName": "D:\\MiceCola\\MingSimulator\\Plugins\\Puerts\\Source\\CSharpParamDefaultValueMetas\\CSharpParamDefaultValueMetas.ubtplugin.csproj",
|
||||
"projectName": "CSharpParamDefaultValueMetas",
|
||||
"projectPath": "D:\\MiceCola\\MingSimulator\\Plugins\\Puerts\\Source\\CSharpParamDefaultValueMetas\\CSharpParamDefaultValueMetas.ubtplugin.csproj",
|
||||
"packagesPath": "C:\\Users\\张青\\.nuget\\packages\\",
|
||||
"outputPath": "D:\\MiceCola\\MingSimulator\\Plugins\\Puerts\\Source\\CSharpParamDefaultValueMetas\\obj\\",
|
||||
"projectStyle": "PackageReference",
|
||||
"fallbackFolders": [
|
||||
"C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages"
|
||||
],
|
||||
"configFilePaths": [
|
||||
"C:\\Users\\张青\\AppData\\Roaming\\NuGet\\NuGet.Config",
|
||||
"C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.FallbackLocation.config",
|
||||
"C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.Offline.config"
|
||||
],
|
||||
"originalTargetFrameworks": [
|
||||
"net6.0"
|
||||
],
|
||||
"sources": {
|
||||
"C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\": {},
|
||||
"https://api.nuget.org/v3/index.json": {}
|
||||
},
|
||||
"frameworks": {
|
||||
"net6.0": {
|
||||
"targetAlias": "net6.0",
|
||||
"projectReferences": {}
|
||||
}
|
||||
},
|
||||
"warningProperties": {
|
||||
"allWarningsAsErrors": true,
|
||||
"warnAsError": [
|
||||
"NU1605"
|
||||
]
|
||||
},
|
||||
"restoreAuditProperties": {
|
||||
"enableAudit": "true",
|
||||
"auditLevel": "low",
|
||||
"auditMode": "direct"
|
||||
}
|
||||
},
|
||||
"frameworks": {
|
||||
"net6.0": {
|
||||
"targetAlias": "net6.0",
|
||||
"dependencies": {
|
||||
"Microsoft.CSharp": {
|
||||
"target": "Package",
|
||||
"version": "[4.7.0, )"
|
||||
}
|
||||
},
|
||||
"imports": [
|
||||
"net461",
|
||||
"net462",
|
||||
"net47",
|
||||
"net471",
|
||||
"net472",
|
||||
"net48",
|
||||
"net481"
|
||||
],
|
||||
"assetTargetFallback": true,
|
||||
"warn": true,
|
||||
"downloadDependencies": [
|
||||
{
|
||||
"name": "Microsoft.AspNetCore.App.Ref",
|
||||
"version": "[6.0.30, 6.0.30]"
|
||||
},
|
||||
{
|
||||
"name": "Microsoft.NETCore.App.Ref",
|
||||
"version": "[6.0.30, 6.0.30]"
|
||||
},
|
||||
{
|
||||
"name": "Microsoft.WindowsDesktop.App.Ref",
|
||||
"version": "[6.0.30, 6.0.30]"
|
||||
}
|
||||
],
|
||||
"frameworkReferences": {
|
||||
"Microsoft.NETCore.App": {
|
||||
"privateAssets": "all"
|
||||
}
|
||||
},
|
||||
"runtimeIdentifierGraphPath": "D:\\MiceCola\\UE_5.5\\Engine\\Binaries\\ThirdParty\\DotNet\\8.0.300\\win-x64\\sdk\\8.0.300\\RuntimeIdentifierGraph.json"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"version": 2,
|
||||
"dgSpecHash": "+l+ToRTRVP0=",
|
||||
"success": true,
|
||||
"projectFilePath": "D:\\MiceCola\\MingSimulator\\Plugins\\Puerts\\Source\\CSharpParamDefaultValueMetas\\CSharpParamDefaultValueMetas.ubtplugin.csproj",
|
||||
"expectedPackageFiles": [
|
||||
"C:\\Users\\张青\\.nuget\\packages\\microsoft.csharp\\4.7.0\\microsoft.csharp.4.7.0.nupkg.sha512",
|
||||
"C:\\Users\\张青\\.nuget\\packages\\microsoft.netcore.app.ref\\6.0.30\\microsoft.netcore.app.ref.6.0.30.nupkg.sha512",
|
||||
"C:\\Users\\张青\\.nuget\\packages\\microsoft.windowsdesktop.app.ref\\6.0.30\\microsoft.windowsdesktop.app.ref.6.0.30.nupkg.sha512",
|
||||
"C:\\Users\\张青\\.nuget\\packages\\microsoft.aspnetcore.app.ref\\6.0.30\\microsoft.aspnetcore.app.ref.6.0.30.nupkg.sha512"
|
||||
],
|
||||
"logs": []
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using UnrealBuildTool;
|
||||
|
||||
public class DeclarationGenerator : ModuleRules
|
||||
{
|
||||
public DeclarationGenerator(ReadOnlyTargetRules Target) : base(Target)
|
||||
{
|
||||
PublicIncludePaths.AddRange(
|
||||
new string[] {
|
||||
"Programs/UnrealHeaderTool/Public",
|
||||
}
|
||||
);
|
||||
PublicDependencyModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
"Core",
|
||||
"CoreUObject",
|
||||
"UMG",
|
||||
"UnrealEd",
|
||||
"LevelEditor",
|
||||
"Engine",
|
||||
"Slate",
|
||||
"SlateCore",
|
||||
"EditorStyle",
|
||||
"InputCore",
|
||||
"Projects",
|
||||
"JsEnv",
|
||||
"Puerts",
|
||||
#if UE_5_0_OR_LATER
|
||||
"ToolMenus",
|
||||
#endif
|
||||
}
|
||||
);
|
||||
|
||||
if (Target.Platform == UnrealTargetPlatform.Win64 ||Target.Platform == UnrealTargetPlatform.Mac)
|
||||
{
|
||||
PublicDependencyModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
"AssetRegistry"
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
if (JsEnv.WithSourceControl)
|
||||
{
|
||||
PrivateDependencyModuleNames.Add("PuertsEditor");
|
||||
}
|
||||
|
||||
//PublicDefinitions.Add(string.Format("DECL_OUTPUT_PATH={0}", Path.GetFullPath(Path.Combine(ModuleDirectory, "..", "..", "Content", "Scripts"))));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
/*
|
||||
* 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 "CodeGenerator.h"
|
||||
|
||||
// Add default functionality here for any ICodeGenerator functions that are not pure virtual.
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,8 @@
|
||||
// gen by puerts gen tools
|
||||
auto SName = Struct -> GetName();
|
||||
if (SName == "IntVector" || SName == "Color" || SName == "Quat" || SName == "Vector2D" || SName == "Vector4" ||
|
||||
SName == "Transform" || SName == "LinearColor" || SName == "Box2D" || SName == "Vector" || SName == "IntPoint" ||
|
||||
SName == "Rotator" || SName == "Guid")
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* 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 "GenDTSCommands.h"
|
||||
|
||||
#define LOCTEXT_NAMESPACE "FGenDTSModule"
|
||||
|
||||
void FGenDTSCommands::RegisterCommands()
|
||||
{
|
||||
UI_COMMAND(
|
||||
PluginAction, "puerts", "Generate *.d.ts and copy some js builtin libs", EUserInterfaceActionType::Button, FInputChord());
|
||||
}
|
||||
|
||||
#undef LOCTEXT_NAMESPACE
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* 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 "GenDTSStyle.h"
|
||||
#include "Framework/Application/SlateApplication.h"
|
||||
#include "Styling/SlateStyleRegistry.h"
|
||||
#include "Slate/SlateGameResources.h"
|
||||
#include "Interfaces/IPluginManager.h"
|
||||
|
||||
TSharedPtr<FSlateStyleSet> FGenDTSStyle::StyleInstance = NULL;
|
||||
|
||||
void FGenDTSStyle::Initialize()
|
||||
{
|
||||
if (!StyleInstance.IsValid())
|
||||
{
|
||||
StyleInstance = Create();
|
||||
FSlateStyleRegistry::RegisterSlateStyle(*StyleInstance);
|
||||
}
|
||||
}
|
||||
|
||||
void FGenDTSStyle::Shutdown()
|
||||
{
|
||||
FSlateStyleRegistry::UnRegisterSlateStyle(*StyleInstance);
|
||||
ensure(StyleInstance.IsUnique());
|
||||
StyleInstance.Reset();
|
||||
}
|
||||
|
||||
FName FGenDTSStyle::GetStyleSetName()
|
||||
{
|
||||
static FName StyleSetName(TEXT("GenDTSStyle"));
|
||||
return StyleSetName;
|
||||
}
|
||||
|
||||
#define IMAGE_BRUSH(RelativePath, ...) FSlateImageBrush(Style->RootToContentDir(RelativePath, TEXT(".png")), __VA_ARGS__)
|
||||
#define BOX_BRUSH(RelativePath, ...) FSlateBoxBrush(Style->RootToContentDir(RelativePath, TEXT(".png")), __VA_ARGS__)
|
||||
#define BORDER_BRUSH(RelativePath, ...) FSlateBorderBrush(Style->RootToContentDir(RelativePath, TEXT(".png")), __VA_ARGS__)
|
||||
#define TTF_FONT(RelativePath, ...) FSlateFontInfo(Style->RootToContentDir(RelativePath, TEXT(".ttf")), __VA_ARGS__)
|
||||
#define OTF_FONT(RelativePath, ...) FSlateFontInfo(Style->RootToContentDir(RelativePath, TEXT(".otf")), __VA_ARGS__)
|
||||
|
||||
const FVector2D Icon16x16(16.0f, 16.0f);
|
||||
const FVector2D Icon20x20(20.0f, 20.0f);
|
||||
const FVector2D Icon40x40(40.0f, 40.0f);
|
||||
|
||||
TSharedRef<FSlateStyleSet> FGenDTSStyle::Create()
|
||||
{
|
||||
TSharedRef<FSlateStyleSet> Style = MakeShareable(new FSlateStyleSet("GenDTSStyle"));
|
||||
Style->SetContentRoot(IPluginManager::Get().FindPlugin("Puerts")->GetBaseDir() / TEXT("Resources"));
|
||||
|
||||
Style->Set("GenDTS.PluginAction", new IMAGE_BRUSH(TEXT("ButtonIcon_40x"), Icon40x40));
|
||||
|
||||
return Style;
|
||||
}
|
||||
|
||||
#undef IMAGE_BRUSH
|
||||
#undef BOX_BRUSH
|
||||
#undef BORDER_BRUSH
|
||||
#undef TTF_FONT
|
||||
#undef OTF_FONT
|
||||
|
||||
void FGenDTSStyle::ReloadTextures()
|
||||
{
|
||||
if (FSlateApplication::IsInitialized())
|
||||
{
|
||||
FSlateApplication::Get().GetRenderer()->ReloadTextureResources();
|
||||
}
|
||||
}
|
||||
|
||||
const ISlateStyle& FGenDTSStyle::Get()
|
||||
{
|
||||
return *StyleInstance;
|
||||
}
|
||||
@@ -0,0 +1,208 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#include "TemplateBindingGenerator.h"
|
||||
#include "JSClassRegister.h"
|
||||
#include "Interfaces/IPluginManager.h"
|
||||
#include "CoreUObject.h"
|
||||
#ifdef PUERTS_WITH_SOURCE_CONTROL
|
||||
#include "FileSystemOperation.h"
|
||||
#endif
|
||||
|
||||
struct FGenImp
|
||||
{
|
||||
FStringBuffer Output{"", ""};
|
||||
|
||||
FString GetNamePrefix(const PUERTS_NAMESPACE::CTypeInfo* TypeInfo)
|
||||
{
|
||||
return TypeInfo->IsUEType() && !HadNamespace(TypeInfo->Name()) ? "UE." : "";
|
||||
}
|
||||
|
||||
FString GetName(const PUERTS_NAMESPACE::CTypeInfo* TypeInfo)
|
||||
{
|
||||
return UTF8_TO_TCHAR(TypeInfo->Name());
|
||||
}
|
||||
|
||||
void Begin()
|
||||
{
|
||||
Output << "declare module \"cpp\" {\n";
|
||||
Output << " import * as UE from \"ue\"\n";
|
||||
Output << " import * as cpp from \"cpp\"\n";
|
||||
Output << " import {$Ref, $Nullable, cstring} from \"puerts\"\n\n";
|
||||
}
|
||||
|
||||
void GenArguments(const PUERTS_NAMESPACE::CFunctionInfo* Type, FStringBuffer& Buff)
|
||||
{
|
||||
for (unsigned int i = 0; i < Type->ArgumentCount(); i++)
|
||||
{
|
||||
if (i != 0)
|
||||
Buff << ", ";
|
||||
auto argInfo = Type->Argument(i);
|
||||
|
||||
Buff << FString::Printf(TEXT("p%d"), i);
|
||||
|
||||
if (i >= Type->ArgumentCount() - Type->DefaultCount())
|
||||
{
|
||||
Buff << "?";
|
||||
}
|
||||
|
||||
Buff << ": ";
|
||||
|
||||
if (strcmp(argInfo->Name(), "cstring") != 0 && !argInfo->IsUEType() && !argInfo->IsObjectType() && argInfo->IsPointer())
|
||||
{
|
||||
Buff << "ArrayBuffer";
|
||||
}
|
||||
else
|
||||
{
|
||||
bool IsReference = argInfo->IsRef();
|
||||
bool IsNullable = !IsReference && argInfo->IsPointer();
|
||||
if (IsNullable)
|
||||
{
|
||||
Buff << "$Nullable<";
|
||||
}
|
||||
if (IsReference)
|
||||
{
|
||||
Buff << "$Ref<";
|
||||
}
|
||||
|
||||
const PUERTS_NAMESPACE::CTypeInfo* TypeInfo = Type->Argument(i);
|
||||
Buff << GetNamePrefix(TypeInfo) << GetName(TypeInfo);
|
||||
|
||||
if (IsNullable)
|
||||
{
|
||||
Buff << ">";
|
||||
}
|
||||
if (IsReference)
|
||||
{
|
||||
Buff << ">";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GenClass(const PUERTS_NAMESPACE::JSClassDefinition* ClassDefinition)
|
||||
{
|
||||
if (HasUENamespace(ClassDefinition->ScriptName))
|
||||
return;
|
||||
Output << " class " << ClassDefinition->ScriptName;
|
||||
if (ClassDefinition->SuperTypeId)
|
||||
{
|
||||
Output << " extends " << PUERTS_NAMESPACE::FindClassByID(ClassDefinition->SuperTypeId)->ScriptName;
|
||||
}
|
||||
Output << " {\n";
|
||||
|
||||
TSet<FString> AddedFunctions;
|
||||
|
||||
PUERTS_NAMESPACE::NamedFunctionInfo* ConstructorInfo = ClassDefinition->ConstructorInfos;
|
||||
while (ConstructorInfo && ConstructorInfo->Name && ConstructorInfo->Type)
|
||||
{
|
||||
FStringBuffer Tmp;
|
||||
Tmp << " constructor(";
|
||||
GenArguments(ConstructorInfo->Type, Tmp);
|
||||
Tmp << ");\n";
|
||||
if (!AddedFunctions.Contains(Tmp.Buffer))
|
||||
{
|
||||
AddedFunctions.Add(Tmp.Buffer);
|
||||
Output << Tmp;
|
||||
}
|
||||
++ConstructorInfo;
|
||||
}
|
||||
|
||||
PUERTS_NAMESPACE::NamedPropertyInfo* PropertyInfo = ClassDefinition->PropertyInfos;
|
||||
while (PropertyInfo && PropertyInfo->Name && PropertyInfo->Type)
|
||||
{
|
||||
Output << " " << PropertyInfo->Name << ": " << GetNamePrefix(PropertyInfo->Type) << PropertyInfo->Type->Name()
|
||||
<< ";\n";
|
||||
++PropertyInfo;
|
||||
}
|
||||
|
||||
PUERTS_NAMESPACE::NamedPropertyInfo* VariableInfo = ClassDefinition->VariableInfos;
|
||||
while (VariableInfo && VariableInfo->Name && VariableInfo->Type)
|
||||
{
|
||||
int Pos = VariableInfo - ClassDefinition->VariableInfos;
|
||||
Output << " static " << (ClassDefinition->Variables[Pos].Setter ? "" : "readonly ") << VariableInfo->Name << ": "
|
||||
<< GetNamePrefix(VariableInfo->Type) << VariableInfo->Type->Name() << ";\n";
|
||||
++VariableInfo;
|
||||
}
|
||||
|
||||
PUERTS_NAMESPACE::NamedFunctionInfo* FunctionInfo = ClassDefinition->FunctionInfos;
|
||||
while (FunctionInfo && FunctionInfo->Name && FunctionInfo->Type)
|
||||
{
|
||||
FStringBuffer Tmp;
|
||||
Tmp << " static " << FunctionInfo->Name;
|
||||
if (FunctionInfo->Type->Return())
|
||||
{
|
||||
Tmp << "(";
|
||||
GenArguments(FunctionInfo->Type, Tmp);
|
||||
const PUERTS_NAMESPACE::CTypeInfo* ReturnType = FunctionInfo->Type->Return();
|
||||
Tmp << ") :" << GetNamePrefix(ReturnType) << GetName(ReturnType) << ";\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
Tmp << FunctionInfo->Type->CustomSignature() << ";\n";
|
||||
}
|
||||
if (!AddedFunctions.Contains(Tmp.Buffer))
|
||||
{
|
||||
AddedFunctions.Add(Tmp.Buffer);
|
||||
Output << Tmp;
|
||||
}
|
||||
++FunctionInfo;
|
||||
}
|
||||
|
||||
PUERTS_NAMESPACE::NamedFunctionInfo* MethodInfo = ClassDefinition->MethodInfos;
|
||||
while (MethodInfo && MethodInfo->Name && MethodInfo->Type)
|
||||
{
|
||||
FStringBuffer Tmp;
|
||||
Tmp << " " << MethodInfo->Name;
|
||||
if (MethodInfo->Type->Return())
|
||||
{
|
||||
Tmp << "(";
|
||||
GenArguments(MethodInfo->Type, Tmp);
|
||||
const PUERTS_NAMESPACE::CTypeInfo* ReturnType = MethodInfo->Type->Return();
|
||||
Tmp << ") :" << GetNamePrefix(ReturnType) << GetName(ReturnType) << ";\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
Tmp << MethodInfo->Type->CustomSignature() << ";\n";
|
||||
}
|
||||
if (!AddedFunctions.Contains(Tmp.Buffer))
|
||||
{
|
||||
AddedFunctions.Add(Tmp.Buffer);
|
||||
Output << Tmp;
|
||||
}
|
||||
++MethodInfo;
|
||||
}
|
||||
|
||||
Output << " }\n\n";
|
||||
}
|
||||
|
||||
void End()
|
||||
{
|
||||
Output << "}\n";
|
||||
}
|
||||
};
|
||||
|
||||
void UTemplateBindingGenerator::Gen_Implementation() const
|
||||
{
|
||||
FGenImp Gen;
|
||||
|
||||
Gen.Begin();
|
||||
|
||||
PUERTS_NAMESPACE::ForeachRegisterClass(
|
||||
[&](const PUERTS_NAMESPACE::JSClassDefinition* ClassDefinition)
|
||||
{
|
||||
if (ClassDefinition->TypeId && ClassDefinition->ScriptName)
|
||||
{
|
||||
Gen.GenClass(ClassDefinition);
|
||||
}
|
||||
});
|
||||
|
||||
Gen.End();
|
||||
|
||||
const FString FilePath = FPaths::ProjectDir() / TEXT("Typing/cpp/index.d.ts");
|
||||
|
||||
#ifdef PUERTS_WITH_SOURCE_CONTROL
|
||||
PuertsSourceControlUtils::MakeSourceControlFileWritable(FilePath);
|
||||
#endif
|
||||
|
||||
FFileHelper::SaveStringToFile(Gen.Output.Buffer, *FilePath, FFileHelper::EEncodingOptions::ForceUTF8WithoutBOM);
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "UObject/Interface.h"
|
||||
#include "CodeGenerator.generated.h"
|
||||
|
||||
// This class does not need to be modified.
|
||||
UINTERFACE(MinimalAPI)
|
||||
class UCodeGenerator : public UInterface
|
||||
{
|
||||
GENERATED_BODY()
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
class DECLARATIONGENERATOR_API ICodeGenerator
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
// Add interface functions to this class. This is the class that will be inherited to implement this interface.
|
||||
public:
|
||||
UFUNCTION(BlueprintNativeEvent)
|
||||
void Gen() const;
|
||||
};
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Framework/Commands/Commands.h"
|
||||
#include "GenDTSStyle.h"
|
||||
|
||||
class FGenDTSCommands : public TCommands<FGenDTSCommands>
|
||||
{
|
||||
public:
|
||||
FGenDTSCommands()
|
||||
: TCommands<FGenDTSCommands>(
|
||||
TEXT("GenDTS"), NSLOCTEXT("Contexts", "GenDTS", "GenDTS Plugin"), NAME_None, FGenDTSStyle::GetStyleSetName())
|
||||
{
|
||||
}
|
||||
|
||||
// TCommands<> interface
|
||||
void RegisterCommands() override;
|
||||
|
||||
public:
|
||||
TSharedPtr<FUICommandInfo> PluginAction;
|
||||
};
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Styling/SlateStyle.h"
|
||||
|
||||
class FGenDTSStyle
|
||||
{
|
||||
public:
|
||||
static void Initialize();
|
||||
|
||||
static void Shutdown();
|
||||
|
||||
/** reloads textures used by slate renderer */
|
||||
static void ReloadTextures();
|
||||
|
||||
/** @return The Slate style set for the Shooter game */
|
||||
static const ISlateStyle& Get();
|
||||
|
||||
static FName GetStyleSetName();
|
||||
|
||||
private:
|
||||
static TSharedRef<class FSlateStyleSet> Create();
|
||||
|
||||
private:
|
||||
static TSharedPtr<class FSlateStyleSet> StyleInstance;
|
||||
};
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
#include "Modules/ModuleManager.h"
|
||||
#include "CoreMinimal.h"
|
||||
|
||||
class IDeclarationGenerator : public IModuleInterface //: public IScriptGeneratorPluginInterface
|
||||
{
|
||||
public:
|
||||
static inline IDeclarationGenerator& Get()
|
||||
{
|
||||
return FModuleManager::LoadModuleChecked<IDeclarationGenerator>("DeclarationGenerator");
|
||||
}
|
||||
|
||||
static inline bool IsAvailable()
|
||||
{
|
||||
return FModuleManager::Get().IsModuleLoaded("DeclarationGenerator");
|
||||
}
|
||||
|
||||
virtual void GenTypeScriptDeclaration(bool InGenFull, FName InSearchPath) = 0;
|
||||
|
||||
virtual void GenReactDeclaration() = 0;
|
||||
};
|
||||
@@ -0,0 +1,25 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CodeGenerator.h"
|
||||
#include "TypeScriptDeclarationGenerator.h"
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "UObject/NoExportTypes.h"
|
||||
#include "TemplateBindingGenerator.generated.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS()
|
||||
class DECLARATIONGENERATOR_API UTemplateBindingGenerator : public UObject, public ICodeGenerator
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UFUNCTION(BlueprintNativeEvent)
|
||||
void Gen() const;
|
||||
|
||||
virtual void Gen_Implementation() const override;
|
||||
};
|
||||
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include "PropertyMacros.h"
|
||||
|
||||
struct DECLARATIONGENERATOR_API FStringBuffer
|
||||
{
|
||||
FString Buffer;
|
||||
|
||||
FString Prefix;
|
||||
|
||||
FStringBuffer& operator<<(const FString& InText);
|
||||
|
||||
FStringBuffer& operator<<(const TCHAR* InText);
|
||||
|
||||
FStringBuffer& operator<<(const char* InText);
|
||||
|
||||
FStringBuffer& operator<<(const FStringBuffer& Other);
|
||||
|
||||
void Indent(int Num);
|
||||
};
|
||||
|
||||
struct DECLARATIONGENERATOR_API FTypeScriptDeclarationGenerator
|
||||
{
|
||||
FStringBuffer Output{"", ""};
|
||||
TSet<UObject*> Processed;
|
||||
TSet<FString> ProcessedByName;
|
||||
std::map<UStruct*, std::vector<UFunction*>> ExtensionMethodsMap;
|
||||
struct FunctionKey
|
||||
{
|
||||
FunctionKey(const FString& InFunctioName, bool InIsStatic) : FunctionName(InFunctioName), IsStatic(InIsStatic)
|
||||
{
|
||||
}
|
||||
|
||||
bool operator<(const FunctionKey& other) const
|
||||
{
|
||||
return IsStatic != other.IsStatic ? IsStatic < other.IsStatic : FunctionName < other.FunctionName;
|
||||
}
|
||||
|
||||
FString FunctionName;
|
||||
bool IsStatic;
|
||||
};
|
||||
typedef TArray<FString> FunctionOverloads;
|
||||
typedef std::map<FunctionKey, FunctionOverloads> FunctionOutputs;
|
||||
std::map<UStruct*, FunctionOutputs> AllFuncionOutputs;
|
||||
|
||||
std::map<UObject*, FString> NamespaceMap;
|
||||
|
||||
std::map<UObject*, bool> PathIsValidMap;
|
||||
|
||||
struct BlueprintTypeDeclInfo
|
||||
{
|
||||
TMap<FName, FString> NameToDecl;
|
||||
FString FileVersionString;
|
||||
bool IsExist;
|
||||
bool Changed;
|
||||
bool IsAssociation;
|
||||
};
|
||||
|
||||
TMap<FName, BlueprintTypeDeclInfo> BlueprintTypeDeclInfoCache;
|
||||
|
||||
TArray<FAssetData> AssetList;
|
||||
|
||||
bool RefFromOuter = false;
|
||||
|
||||
bool BeginGenAssetData = false;
|
||||
|
||||
const FString& GetNamespace(UObject* Obj);
|
||||
|
||||
FString GetNameWithNamespace(UObject* Obj);
|
||||
|
||||
void NamespaceBegin(UObject* Obj, FStringBuffer& Buff);
|
||||
|
||||
void NamespaceEnd(UObject* Obj, FStringBuffer& Buff);
|
||||
|
||||
void WriteOutput(UObject* Obj, const FStringBuffer& Buff);
|
||||
|
||||
void RestoreBlueprintTypeDeclInfos(bool InGenFull);
|
||||
|
||||
void RestoreBlueprintTypeDeclInfos(const FString& FileContent, bool InGenFull);
|
||||
|
||||
void LoadAllWidgetBlueprint(FName InSearchPath, bool InGenFull);
|
||||
|
||||
void InitExtensionMethodsMap();
|
||||
|
||||
virtual void Begin(FString Namespace = TEXT("ue"));
|
||||
|
||||
void GenTypeScriptDeclaration(bool InGenStruct, bool InGenEnum);
|
||||
|
||||
virtual void Gen(UObject* ToGen);
|
||||
|
||||
virtual bool GenTypeDecl(FStringBuffer& StringBuffer, PropertyMacro* Property, TArray<UObject*>& AddToGen,
|
||||
bool ArrayDimProcessed = false, bool TreatAsRawFunction = false);
|
||||
|
||||
virtual bool GenFunction(FStringBuffer& OwnerBuffer, UFunction* Function, bool WithName = true, bool ForceOneway = false,
|
||||
bool IgnoreOut = false, bool IsExtensionMethod = false);
|
||||
|
||||
void GatherExtensions(UStruct* Struct, FStringBuffer& Buff);
|
||||
|
||||
void GenResolvedFunctions(UStruct* Struct, FStringBuffer& Buff);
|
||||
|
||||
FunctionOutputs& GetFunctionOutputs(UStruct* Struct);
|
||||
|
||||
FunctionOverloads& GetFunctionOverloads(FunctionOutputs& Outputs, const FString& FunctionName, bool IsStatic);
|
||||
|
||||
void TryToAddOverload(FunctionOutputs& Outputs, const FString& FunctionName, bool IsStatic, const FString& Overload);
|
||||
|
||||
virtual void GenClass(UClass* Class);
|
||||
|
||||
virtual void GenEnum(UEnum* Enum);
|
||||
|
||||
virtual void GenStruct(UStruct* Struct);
|
||||
|
||||
virtual void End();
|
||||
|
||||
FString ToString();
|
||||
|
||||
virtual ~FTypeScriptDeclarationGenerator()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
bool HasUENamespace(const char* name);
|
||||
|
||||
bool HadNamespace(const char* name);
|
||||
@@ -0,0 +1,737 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
using System.Collections.Generic;
|
||||
using UnrealBuildTool;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
|
||||
public class JsEnv : ModuleRules
|
||||
{
|
||||
enum SupportedV8Versions
|
||||
{
|
||||
VDeprecated, // for 4.24 or blow only
|
||||
V8_4_371_19,
|
||||
V9_4_146_24,
|
||||
V10_6_194,
|
||||
V11_8_172
|
||||
}
|
||||
|
||||
private SupportedV8Versions UseV8Version =
|
||||
#if UE_4_25_OR_LATER
|
||||
SupportedV8Versions.V9_4_146_24;
|
||||
#else
|
||||
SupportedV8Versions.VDeprecated;
|
||||
#endif
|
||||
|
||||
private bool UseNodejs = false;
|
||||
|
||||
private bool Node16 = true;
|
||||
|
||||
private bool UseQuickjs = false;
|
||||
|
||||
private bool QjsNamespaceSuffix = false;
|
||||
|
||||
private bool WithFFI = false;
|
||||
|
||||
private bool ForceStaticLibInEditor = false;
|
||||
|
||||
private bool ThreadSafe = false;
|
||||
|
||||
private bool FTextAsString = true;
|
||||
|
||||
private bool bEditorSuffix = true;
|
||||
|
||||
// v8 9.4+
|
||||
private bool SingleThreaded = false;
|
||||
|
||||
public static bool WithSourceControl = false;
|
||||
|
||||
public bool WithByteCode = false;
|
||||
|
||||
private bool WithWebsocket = false;
|
||||
|
||||
public JsEnv(ReadOnlyTargetRules Target) : base(Target)
|
||||
{
|
||||
PublicDefinitions.Add("USING_IN_UNREAL_ENGINE");
|
||||
//PublicDefinitions.Add("WITH_V8_FAST_CALL");
|
||||
|
||||
PublicDefinitions.Add("TS_BLUEPRINT_PATH=\"/Blueprints/TypeScript/\"");
|
||||
|
||||
PublicDefinitions.Add(ThreadSafe ? "THREAD_SAFE" : "NOT_THREAD_SAFE");
|
||||
|
||||
if (bEditorSuffix)
|
||||
{
|
||||
PublicDefinitions.Add("PUERTS_WITH_EDITOR_SUFFIX");
|
||||
}
|
||||
|
||||
if (WithWebsocket)
|
||||
{
|
||||
PublicDefinitions.Add("WITH_WEBSOCKET");
|
||||
PublicDefinitions.Add("WITH_WEBSOCKET_SSL");
|
||||
PublicDependencyModuleNames.Add("OpenSSL");
|
||||
}
|
||||
|
||||
ShadowVariableWarningLevel = WarningLevel.Warning;
|
||||
|
||||
if (!FTextAsString)
|
||||
{
|
||||
PublicDefinitions.Add("PUERTS_FTEXT_AS_OBJECT");
|
||||
}
|
||||
|
||||
PublicDependencyModuleNames.AddRange(new string[]
|
||||
{
|
||||
"Core", "CoreUObject", "Engine", "ParamDefaultValueMetas", "UMG"
|
||||
});
|
||||
|
||||
if (Target.bBuildEditor)
|
||||
{
|
||||
PublicDependencyModuleNames.AddRange(new string[] { "DirectoryWatcher", });
|
||||
}
|
||||
|
||||
bEnableExceptions = true;
|
||||
var ContextField = GetType().GetField("Context", BindingFlags.Instance | BindingFlags.NonPublic);
|
||||
if (ContextField != null)
|
||||
{
|
||||
var bCanHotReloadField = ContextField.FieldType.GetField("bCanHotReload", BindingFlags.Instance | BindingFlags.Public);
|
||||
if (bCanHotReloadField != null)
|
||||
{
|
||||
bCanHotReloadField.SetValue(ContextField.GetValue(this), false);
|
||||
}
|
||||
}
|
||||
|
||||
bool bForceAllUFunctionInCPP = false;
|
||||
if (bForceAllUFunctionInCPP)
|
||||
{
|
||||
PublicDefinitions.Add("PUERTS_FORCE_CPP_UFUNCTION=1");
|
||||
}
|
||||
else
|
||||
{
|
||||
PublicDefinitions.Add("PUERTS_FORCE_CPP_UFUNCTION=0");
|
||||
}
|
||||
|
||||
bool bKeepUObjectReference = true;
|
||||
if(bKeepUObjectReference)
|
||||
{
|
||||
PublicDefinitions.Add("PUERTS_KEEP_UOBJECT_REFERENCE=1");
|
||||
}
|
||||
else
|
||||
{
|
||||
PublicDefinitions.Add("PUERTS_KEEP_UOBJECT_REFERENCE=0");
|
||||
}
|
||||
|
||||
bool UseWasm = false;
|
||||
if (UseWasm)
|
||||
{
|
||||
PublicDefinitions.Add("USE_WASM3=1");
|
||||
}
|
||||
else
|
||||
{
|
||||
PublicDefinitions.Add("USE_WASM3=0");
|
||||
}
|
||||
bool OverrideWebAssembly = false;
|
||||
if (OverrideWebAssembly)
|
||||
{
|
||||
PublicDefinitions.Add("WASM3_OVERRIDE_WEBASSEMBLY=1");
|
||||
}
|
||||
else
|
||||
{
|
||||
PublicDefinitions.Add("WASM3_OVERRIDE_WEBASSEMBLY=0");
|
||||
}
|
||||
PublicDependencyModuleNames.AddRange(new string[]
|
||||
{
|
||||
"WasmCore", "Json"
|
||||
});
|
||||
|
||||
if (UseNodejs)
|
||||
{
|
||||
ThirdPartyNodejs(Target);
|
||||
}
|
||||
else if (UseQuickjs)
|
||||
{
|
||||
ForceStaticLibInEditor = true;
|
||||
ThirdPartyQJS(Target);
|
||||
}
|
||||
else if (UseV8Version > SupportedV8Versions.VDeprecated)
|
||||
{
|
||||
ThirdParty(Target);
|
||||
}
|
||||
else
|
||||
{
|
||||
OldThirdParty(Target);
|
||||
}
|
||||
|
||||
if (WithFFI) AddFFI(Target);
|
||||
|
||||
string coreJSPath = Path.GetFullPath(Path.Combine(ModuleDirectory, "..", "..", "Content"));
|
||||
string destDirName = Path.GetFullPath(Path.Combine(ModuleDirectory, "..", "..", "..", "..", "Content"));
|
||||
DirectoryCopy(coreJSPath, destDirName, true);
|
||||
}
|
||||
|
||||
void OldThirdParty(ReadOnlyTargetRules Target)
|
||||
{
|
||||
string LibraryPath = Path.GetFullPath(Path.Combine(ModuleDirectory, "..", "..", "ThirdParty", "v8_for_ue424_or_below", "Lib"));
|
||||
if (Target.Platform == UnrealTargetPlatform.Win64)
|
||||
{
|
||||
//if (Target.bBuildEditor)
|
||||
//{
|
||||
// WinDll(Path.Combine(LibraryPath, "V8"));
|
||||
//}
|
||||
//else
|
||||
{
|
||||
string V8LibraryPath = Path.Combine(LibraryPath, "Win64");
|
||||
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "encoding.lib"));
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "inspector.lib"));
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "inspector_string_conversions.lib"));
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "v8_base_without_compiler_0.lib"));
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "v8_base_without_compiler_1.lib"));
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "v8_compiler.lib"));
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "v8_external_snapshot.lib"));
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "v8_libbase.lib"));
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "v8_libplatform.lib"));
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "v8_libsampler.lib"));
|
||||
}
|
||||
}
|
||||
else if (Target.Platform == UnrealTargetPlatform.Android)
|
||||
{
|
||||
if (Target.Version.MajorVersion == 4 && Target.Version.MinorVersion >= 25)
|
||||
{
|
||||
// for arm7
|
||||
string V8LibraryPath = Path.Combine(LibraryPath, "Android", "armeabi-v7a", "8.4.371.19");
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libwee8.a"));
|
||||
// for arm64
|
||||
V8LibraryPath = Path.Combine(LibraryPath, "V8", "Android", "arm64-v8a", "8.4.371.19");
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libwee8.a"));
|
||||
}
|
||||
else if (Target.Version.MajorVersion == 4 && Target.Version.MinorVersion < 25 && Target.Version.MinorVersion >= 22)
|
||||
{
|
||||
// for arm7
|
||||
string V8LibraryPath = Path.Combine(LibraryPath, "Android", "armeabi-v7a", "7.4.288");
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libinspector.a"));
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libv8_base.a"));
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libv8_external_snapshot.a"));
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libv8_libbase.a"));
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libv8_libplatform.a"));
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libv8_libsampler.a"));
|
||||
// for arm64
|
||||
V8LibraryPath = Path.Combine(LibraryPath, "Android", "arm64-v8a", "7.4.288");
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libinspector.a"));
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libv8_base.a"));
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libv8_external_snapshot.a"));
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libv8_libbase.a"));
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libv8_libplatform.a"));
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libv8_libsampler.a"));
|
||||
}
|
||||
#if !UE_4_22_OR_LATER
|
||||
else if (Target.Version.MajorVersion == 4 && Target.Version.MinorVersion < 22)
|
||||
{
|
||||
string V8LibraryPath = Path.Combine(LibraryPath, "Android", "armeabi-v7a", "7.4.288");
|
||||
PublicLibraryPaths.Add(V8LibraryPath);
|
||||
V8LibraryPath = Path.Combine(LibraryPath, "Android", "arm64-v8a", "7.4.288");
|
||||
PublicLibraryPaths.Add(V8LibraryPath);
|
||||
PublicAdditionalLibraries.Add("inspector");
|
||||
PublicAdditionalLibraries.Add("v8_base");
|
||||
PublicAdditionalLibraries.Add("v8_external_snapshot");
|
||||
PublicAdditionalLibraries.Add("v8_libbase");
|
||||
PublicAdditionalLibraries.Add("v8_libplatform");
|
||||
PublicAdditionalLibraries.Add("v8_libsampler");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else if (Target.Platform == UnrealTargetPlatform.Mac)
|
||||
{
|
||||
// PublicFrameworks.AddRange(new string[] { "WebKit", "JavaScriptCore" });
|
||||
PublicFrameworks.AddRange(new string[] { "WebKit" });
|
||||
string V8LibraryPath = Path.Combine(LibraryPath, "macOS");
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libbindings.a"));
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libencoding.a"));
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libinspector.a"));
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libinspector_string_conversions.a"));
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libtorque_base.a"));
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libtorque_generated_definitions.a"));
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libtorque_generated_initializers.a"));
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libv8_base_without_compiler.a"));
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libv8_compiler.a"));
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libv8_external_snapshot.a"));
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libv8_init.a"));
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libv8_initializers.a"));
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libv8_libbase.a"));
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libv8_libplatform.a"));
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libv8_libsampler.a"));
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libv8_nosnapshot.a"));
|
||||
}
|
||||
else if (Target.Platform == UnrealTargetPlatform.IOS)
|
||||
{
|
||||
PublicFrameworks.AddRange(new string[] { "WebKit" });
|
||||
string V8LibraryPath = Path.Combine(LibraryPath, "iOS", "arm64");
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libbindings.a"));
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libencoding.a"));
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libinspector.a"));
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libinspector_string_conversions.a"));
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libtorque_generated_definitions.a"));
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libv8_base_without_compiler.a"));
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libv8_compiler.a"));
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libv8_external_snapshot.a"));
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libv8_libbase.a"));
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libv8_libplatform.a"));
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libv8_libsampler.a"));
|
||||
|
||||
//PublicAdditionalLibraries.Add(Path.Combine(Path.Combine(LibraryPath, "ffi", "iOS"), "libffi.a"));
|
||||
}
|
||||
else if (Target.Platform == UnrealTargetPlatform.Linux)
|
||||
{
|
||||
string V8LibraryPath = Path.Combine(LibraryPath, "Linux");
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libwee8.a"));
|
||||
}
|
||||
|
||||
string V8HeaderPath = Path.GetFullPath(Path.Combine(ModuleDirectory, "..", "..", "ThirdParty", "v8_for_ue424_or_below", "Inc"));
|
||||
// External headers
|
||||
if (Target.Platform == UnrealTargetPlatform.Android)
|
||||
{
|
||||
if (Target.Version.MajorVersion == 4 && Target.Version.MinorVersion >= 25)
|
||||
{
|
||||
PublicIncludePaths.AddRange(new string[] { Path.Combine(V8HeaderPath, "8.4.371.19") });
|
||||
}
|
||||
else if (Target.Version.MajorVersion == 4 && Target.Version.MinorVersion < 25)
|
||||
{
|
||||
PublicIncludePaths.AddRange(new string[] { Path.Combine(V8HeaderPath, "7.4.288") });
|
||||
}
|
||||
}
|
||||
//else if (Target.bBuildEditor && Target.Platform == UnrealTargetPlatform.Win64)
|
||||
//{
|
||||
// PublicIncludePaths.AddRange(new string[] { Path.Combine(HeaderPath, "8.4.371.19") });
|
||||
//}
|
||||
else if (Target.Platform == UnrealTargetPlatform.Win64 ||
|
||||
Target.Platform == UnrealTargetPlatform.IOS ||
|
||||
Target.Platform == UnrealTargetPlatform.Mac ||
|
||||
Target.Platform == UnrealTargetPlatform.Linux)
|
||||
{
|
||||
PublicIncludePaths.AddRange(new string[] { Path.Combine(V8HeaderPath, "7.7.299") });
|
||||
}
|
||||
string HeaderPath = Path.GetFullPath(Path.Combine(ModuleDirectory, "..", "..", "ThirdParty", "Include"));
|
||||
PublicIncludePaths.AddRange(new string[] { Path.Combine(HeaderPath, "websocketpp") });
|
||||
PublicIncludePaths.AddRange(new string[] { Path.Combine(HeaderPath, "asio") });
|
||||
}
|
||||
|
||||
void AddFFI(ReadOnlyTargetRules Target)
|
||||
{
|
||||
string HeaderPath = Path.GetFullPath(Path.Combine(ModuleDirectory, "..", "..", "ThirdParty", "Include"));
|
||||
string LibraryPath = Path.GetFullPath(Path.Combine(ModuleDirectory, "..", "..", "ThirdParty", "Library"));
|
||||
if (Target.Platform == UnrealTargetPlatform.Win64)
|
||||
{
|
||||
PublicIncludePaths.AddRange(new string[] {Path.Combine(HeaderPath, "ffi", "Win64")});
|
||||
PublicAdditionalLibraries.Add(Path.Combine(LibraryPath, "ffi", "Win64", "ffi.lib"));
|
||||
}
|
||||
else if (Target.Platform == UnrealTargetPlatform.Mac)
|
||||
{
|
||||
PublicIncludePaths.AddRange(new string[] {Path.Combine(HeaderPath, "ffi", "macOS")});
|
||||
PublicAdditionalLibraries.Add(Path.Combine(LibraryPath, "ffi", "macOS", "libffi.a"));
|
||||
}
|
||||
else if (Target.Platform == UnrealTargetPlatform.IOS)
|
||||
{
|
||||
PublicIncludePaths.AddRange(new string[] {Path.Combine(HeaderPath, "ffi", "iOS")});
|
||||
PublicAdditionalLibraries.Add(Path.Combine(LibraryPath, "ffi", "iOS", "libffi.a"));
|
||||
}
|
||||
else if (Target.Platform == UnrealTargetPlatform.Android)
|
||||
{
|
||||
PublicIncludePaths.AddRange(new string[] {Path.Combine(HeaderPath, "ffi", "Android")});
|
||||
PublicAdditionalLibraries.Add(Path.Combine(LibraryPath, "ffi", "Android", "armeabi-v7a", "libffi.a"));
|
||||
PublicAdditionalLibraries.Add(Path.Combine(LibraryPath, "ffi", "Android", "arm64-v8a", "libffi.a"));
|
||||
}
|
||||
|
||||
PrivateDefinitions.Add("WITH_FFI");
|
||||
}
|
||||
|
||||
void AddRuntimeDependencies(string[] DllNames, string LibraryPath, bool Delay)
|
||||
{
|
||||
foreach (var DllName in DllNames)
|
||||
{
|
||||
if(Delay) PublicDelayLoadDLLs.Add(DllName);
|
||||
var DllPath = Path.Combine(LibraryPath, DllName);
|
||||
var DestDllPath = Path.Combine("$(BinaryOutputDir)", DllName);
|
||||
RuntimeDependencies.Add(DestDllPath, DllPath, StagedFileType.NonUFS);
|
||||
}
|
||||
}
|
||||
|
||||
void WinDll(string LibraryPath)
|
||||
{
|
||||
string V8LibraryPath = Path.Combine(LibraryPath, "Win64DLL");
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "v8.dll.lib"));
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "v8_libplatform.dll.lib"));
|
||||
|
||||
List<string> deps = new List<string> {
|
||||
"v8.dll",
|
||||
"v8_libplatform.dll",
|
||||
"v8_libbase.dll"
|
||||
};
|
||||
deps.Add(UseV8Version == SupportedV8Versions.V11_8_172 ? "third_party_zlib.dll" : "zlib.dll");
|
||||
|
||||
AddRuntimeDependencies(deps.ToArray(), V8LibraryPath, false);
|
||||
}
|
||||
|
||||
void MacDylib(string LibraryPath)
|
||||
{
|
||||
PublicAdditionalLibraries.Add(Path.Combine(LibraryPath, "libv8.dylib"));
|
||||
PublicAdditionalLibraries.Add(Path.Combine(LibraryPath, "libv8_libplatform.dylib"));
|
||||
PublicAdditionalLibraries.Add(Path.Combine(LibraryPath, "libv8_libbase.dylib"));
|
||||
PublicAdditionalLibraries.Add(Path.Combine(LibraryPath, "libchrome_zlib.dylib"));
|
||||
if (UseV8Version == SupportedV8Versions.V11_8_172)
|
||||
{
|
||||
PublicAdditionalLibraries.Add(Path.Combine(LibraryPath, "libthird_party_abseil-cpp_absl.dylib"));
|
||||
}
|
||||
}
|
||||
|
||||
void ThirdParty(ReadOnlyTargetRules Target)
|
||||
{
|
||||
if (SingleThreaded)
|
||||
{
|
||||
PrivateDefinitions.Add("USING_SINGLE_THREAD_PLATFORM");
|
||||
}
|
||||
|
||||
if (WithByteCode)
|
||||
{
|
||||
PrivateDefinitions.Add("WITH_V8_BYTECODE");
|
||||
}
|
||||
|
||||
string v8LibSuffix = "";
|
||||
|
||||
if (UseV8Version == SupportedV8Versions.V8_4_371_19)
|
||||
{
|
||||
if(Directory.Exists(Path.Combine(ModuleDirectory, "..", "..", "ThirdParty", "v8_8.4.371.19")))
|
||||
{
|
||||
v8LibSuffix = "_8.4.371.19";
|
||||
}
|
||||
}
|
||||
else if (UseV8Version == SupportedV8Versions.V9_4_146_24)
|
||||
{
|
||||
v8LibSuffix = "_9.4.146.24";
|
||||
}
|
||||
else if (UseV8Version == SupportedV8Versions.V10_6_194)
|
||||
{
|
||||
v8LibSuffix = "_10.6.194";
|
||||
}
|
||||
else if (UseV8Version == SupportedV8Versions.V11_8_172)
|
||||
{
|
||||
#if !UE_5_0_OR_LATER
|
||||
CppStandard = CppStandardVersion.Cpp17;
|
||||
#endif
|
||||
v8LibSuffix = "_11.8.172";
|
||||
}
|
||||
//Add header
|
||||
string HeaderPath = Path.GetFullPath(Path.Combine(ModuleDirectory, "..", "..", "ThirdParty", "Include"));
|
||||
PublicIncludePaths.AddRange(new string[] { Path.Combine(HeaderPath, "websocketpp") });
|
||||
PublicIncludePaths.AddRange(new string[] { Path.Combine(HeaderPath, "asio") });
|
||||
PublicIncludePaths.AddRange(new string[] { Path.Combine(ModuleDirectory, "..", "..", "ThirdParty", "v8" + v8LibSuffix, "Inc") });
|
||||
|
||||
string LibraryPath = Path.GetFullPath(Path.Combine(ModuleDirectory, "..", "..", "ThirdParty", "v8" + v8LibSuffix, "Lib"));
|
||||
if (Target.Platform == UnrealTargetPlatform.Win64)
|
||||
{
|
||||
if (!Target.bBuildEditor || ForceStaticLibInEditor)
|
||||
{
|
||||
string V8LibraryPath = Path.Combine(LibraryPath, "Win64MD");
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "wee8.lib"));
|
||||
}
|
||||
else
|
||||
{
|
||||
WinDll(LibraryPath);
|
||||
}
|
||||
}
|
||||
else if (Target.Platform == UnrealTargetPlatform.Android)
|
||||
{
|
||||
string V8LibraryPath = Path.Combine(LibraryPath, "Android", "armeabi-v7a");
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libwee8.a"));
|
||||
V8LibraryPath = Path.Combine(LibraryPath, "Android", "arm64-v8a");
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libwee8.a"));
|
||||
}
|
||||
else if (Target.Platform == UnrealTargetPlatform.Mac)
|
||||
{
|
||||
//PublicFrameworks.AddRange(new string[] { "WebKit", "JavaScriptCore" });
|
||||
//PublicFrameworks.AddRange(new string[] { "WebKit" });
|
||||
if (!Target.bBuildEditor || ForceStaticLibInEditor)
|
||||
{
|
||||
LibraryPath = Path.Combine(LibraryPath, "macOS");
|
||||
#if UE_5_2_OR_LATER
|
||||
if (Target.Architecture == UnrealArch.Arm64)
|
||||
{
|
||||
LibraryPath += "_arm64";
|
||||
}
|
||||
#endif
|
||||
PublicAdditionalLibraries.Add(Path.Combine(LibraryPath, "libwee8.a"));
|
||||
}
|
||||
else
|
||||
{
|
||||
LibraryPath = Path.Combine(LibraryPath, "macOSdylib");
|
||||
#if UE_5_2_OR_LATER
|
||||
if (Target.Architecture == UnrealArch.Arm64)
|
||||
{
|
||||
LibraryPath += "_arm64";
|
||||
}
|
||||
#endif
|
||||
MacDylib(LibraryPath);
|
||||
}
|
||||
}
|
||||
else if (Target.Platform == UnrealTargetPlatform.IOS)
|
||||
{
|
||||
PublicFrameworks.AddRange(new string[] { "WebKit" });
|
||||
string V8LibraryPath = Path.Combine(LibraryPath, "iOS", "arm64");
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libwee8.a"));
|
||||
}
|
||||
else if (Target.Platform == UnrealTargetPlatform.Linux)
|
||||
{
|
||||
string V8LibraryPath = Path.Combine(LibraryPath, "Linux");
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libwee8.a"));
|
||||
}
|
||||
|
||||
if (ForceStaticLibInEditor)
|
||||
{
|
||||
PrivateDefinitions.Add("FORCE_USE_STATIC_V8_LIB");
|
||||
}
|
||||
}
|
||||
|
||||
void ThirdPartyNodejs(ReadOnlyTargetRules Target)
|
||||
{
|
||||
PrivateDefinitions.Add("WITH_NODEJS");
|
||||
string WsHeaderPath = Path.GetFullPath(Path.Combine(ModuleDirectory, "..", "..", "ThirdParty", "Include"));
|
||||
PublicIncludePaths.AddRange(new string[] { Path.Combine(WsHeaderPath, "websocketpp") });
|
||||
PublicIncludePaths.AddRange(new string[] { Path.Combine(WsHeaderPath, "asio") });
|
||||
|
||||
string NodeRoot = Node16 ? "nodejs_16" : "nodejs";
|
||||
|
||||
string HeaderPath = Path.GetFullPath(Path.Combine(ModuleDirectory, "..", "..", "ThirdParty", NodeRoot));
|
||||
PublicIncludePaths.AddRange(new string[] { Path.Combine(HeaderPath, "include") });
|
||||
PublicIncludePaths.AddRange(new string[] { Path.Combine(HeaderPath, "deps", "v8", "include") });
|
||||
PublicIncludePaths.AddRange(new string[] { Path.Combine(HeaderPath, "deps", "uv", "include") });
|
||||
|
||||
string LibraryPath = Path.GetFullPath(Path.Combine(ModuleDirectory, "..", "..", "ThirdParty", NodeRoot, "lib"));
|
||||
if (Target.Platform == UnrealTargetPlatform.Win64)
|
||||
{
|
||||
string V8LibraryPath = Path.Combine(LibraryPath, "Win64");
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libnode.lib"));
|
||||
|
||||
RuntimeDependencies.Add("$(TargetOutputDir)/libnode.dll", Path.Combine(V8LibraryPath, "libnode.dll"));
|
||||
AddRuntimeDependencies(new string[] { "libnode.dll" }, V8LibraryPath, false);
|
||||
}
|
||||
else if (Target.Platform == UnrealTargetPlatform.Android)
|
||||
{
|
||||
/*
|
||||
#if UE_4_19_OR_LATER
|
||||
AdditionalPropertiesForReceipt.Add("AndroidPlugin", Path.Combine(ModuleDirectory, "..", "..", "ThirdParty", "Libnode_APL.xml"));
|
||||
#else
|
||||
AdditionalPropertiesForReceipt.Add(new ReceiptProperty("AndroidPlugin", Path.Combine(ModuleDirectory, "..", "..", "ThirdParty", "Libnode_APL.xml")));
|
||||
#endif
|
||||
#if UE_4_24_OR_LATER
|
||||
PublicSystemLibraryPaths.Add(Path.Combine(LibraryPath, "Android", "armeabi-v7a"));
|
||||
PublicSystemLibraryPaths.Add(Path.Combine(LibraryPath, "Android", "arm64-v8a"));
|
||||
PublicSystemLibraries.Add("node");
|
||||
#else
|
||||
PublicLibraryPaths.Add(Path.Combine(LibraryPath, "Android", "armeabi-v7a"));
|
||||
PublicLibraryPaths.Add(Path.Combine(LibraryPath, "Android", "arm64-v8a"));
|
||||
PublicAdditionalLibraries.Add("node");
|
||||
#endif //UE_4_24_OR_LATER
|
||||
*/
|
||||
|
||||
string[] Archs = new string[] { "armeabi-v7a", "arm64-v8a" };
|
||||
foreach (var Arch in Archs)
|
||||
{
|
||||
string V8LibraryPath = Path.Combine(LibraryPath, "Android", Arch);
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libhistogram.a"));
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libuvwasi.a"));
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libnode.a"));
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libnode_stub.a"));
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libv8_snapshot.a"));
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libv8_libplatform.a"));
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libzlib.a"));
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libllhttp.a"));
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libcares.a"));
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libuv.a"));
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libnghttp2.a"));
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libbrotli.a"));
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libv8_base_without_compiler.a"));
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libv8_libbase.a"));
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libv8_zlib.a"));
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libv8_compiler.a"));
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libv8_initializers.a"));
|
||||
if (!Node16)
|
||||
{
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libv8_libsampler.a"));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else if (Target.Platform == UnrealTargetPlatform.Mac)
|
||||
{
|
||||
string V8LibraryPath = Path.Combine(LibraryPath, "macOS");
|
||||
if (Node16)
|
||||
{
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libnode.93.dylib"));
|
||||
}
|
||||
else
|
||||
{
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libnode.83.dylib"));
|
||||
}
|
||||
}
|
||||
else if (Target.Platform == UnrealTargetPlatform.IOS)
|
||||
{
|
||||
string V8LibraryPath = Path.Combine(LibraryPath, "iOS");
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libhistogram.a"));
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libuvwasi.a"));
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libnode.a"));
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libnode_stub.a"));
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libv8_snapshot.a"));
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libv8_libplatform.a"));
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libzlib.a"));
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libllhttp.a"));
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libcares.a"));
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libuv.a"));
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libnghttp2.a"));
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libbrotli.a"));
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libopenssl.a"));
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libv8_base_without_compiler.a"));
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libv8_libbase.a"));
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libv8_zlib.a"));
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libv8_compiler.a"));
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libv8_initializers.a"));
|
||||
if (!Node16)
|
||||
{
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libv8_libsampler.a"));
|
||||
}
|
||||
}
|
||||
else if (Target.Platform == UnrealTargetPlatform.Linux)
|
||||
{
|
||||
string V8LibraryPath = Path.Combine(LibraryPath, "Linux");
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libnode.so"));
|
||||
RuntimeDependencies.Add("$(TargetOutputDir)/libnode.so.93", Path.Combine(V8LibraryPath, "libnode.so.93"));
|
||||
}
|
||||
}
|
||||
|
||||
void ThirdPartyQJS(ReadOnlyTargetRules Target)
|
||||
{
|
||||
PrivateDefinitions.Add("WITHOUT_INSPECTOR");
|
||||
PrivateDefinitions.Add("WITH_QUICKJS");
|
||||
if (QjsNamespaceSuffix)
|
||||
{
|
||||
PublicDefinitions.Add("WITH_QJS_NAMESPACE_SUFFIX=1");
|
||||
PublicDefinitions.Add("QJSV8NAMESPACE=v8_qjs");
|
||||
}
|
||||
|
||||
PublicIncludePaths.AddRange(new string[] { Path.Combine(ModuleDirectory, "..", "..", "ThirdParty", "quickjs", "Inc") });
|
||||
|
||||
string LibraryPath = Path.GetFullPath(Path.Combine(ModuleDirectory, "..", "..", "ThirdParty", "quickjs", "Lib"));
|
||||
if (Target.Platform == UnrealTargetPlatform.Win64)
|
||||
{
|
||||
string V8LibraryPath = Path.Combine(LibraryPath, "Win64MD");
|
||||
|
||||
bool UsingSource = false;
|
||||
if (UsingSource)
|
||||
{
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libquickjs.dll.a"));
|
||||
PrivateDefinitions.Add("BUILDING_V8_SHARED");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Target.bBuildEditor && !ForceStaticLibInEditor)
|
||||
{
|
||||
V8LibraryPath = Path.Combine(LibraryPath, "Win64DLL");
|
||||
AddRuntimeDependencies(new string[] { "v8qjs.dll" }, V8LibraryPath, false);
|
||||
}
|
||||
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "quickjs.dll.lib"));
|
||||
}
|
||||
|
||||
AddRuntimeDependencies(new string[] { "msys-quickjs.dll" }, V8LibraryPath, false);
|
||||
AddRuntimeDependencies(new string[]
|
||||
{
|
||||
"libgcc_s_seh-1.dll",
|
||||
"libwinpthread-1.dll"
|
||||
}, V8LibraryPath, true);
|
||||
}
|
||||
else if (Target.Platform == UnrealTargetPlatform.Android)
|
||||
{
|
||||
string V8LibraryPath = Path.Combine(LibraryPath, "Android", "armeabi-v7a");
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libquickjs.a"));
|
||||
V8LibraryPath = Path.Combine(LibraryPath, "Android", "arm64-v8a");
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libquickjs.a"));
|
||||
}
|
||||
else if (Target.Platform == UnrealTargetPlatform.Mac)
|
||||
{
|
||||
// PublicFrameworks.AddRange(new string[] { "WebKit", "JavaScriptCore" });
|
||||
//PublicFrameworks.AddRange(new string[] { "WebKit" });
|
||||
if (!Target.bBuildEditor || ForceStaticLibInEditor)
|
||||
{
|
||||
string V8LibraryPath = Path.Combine(LibraryPath, "macOS");
|
||||
#if UE_5_2_OR_LATER
|
||||
if (Target.Architecture == UnrealArch.Arm64)
|
||||
{
|
||||
V8LibraryPath = Path.Combine(LibraryPath, "macOS_arm64");
|
||||
}
|
||||
#endif
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libquickjs.a"));
|
||||
}
|
||||
else
|
||||
{
|
||||
string V8LibraryPath = Path.Combine(LibraryPath, "macOSdylib");
|
||||
string QJSDylibName = "libquickjs.dylib";
|
||||
#if UE_5_2_OR_LATER
|
||||
if (Target.Architecture == UnrealArch.Arm64)
|
||||
{
|
||||
V8LibraryPath = Path.Combine(LibraryPath, "macOS_arm64");
|
||||
QJSDylibName = "libquickjs.a";
|
||||
}
|
||||
#endif
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, QJSDylibName));
|
||||
}
|
||||
}
|
||||
else if (Target.Platform == UnrealTargetPlatform.IOS)
|
||||
{
|
||||
PublicFrameworks.AddRange(new string[] { "WebKit" });
|
||||
string V8LibraryPath = Path.Combine(LibraryPath, "iOS", "arm64");
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libquickjs.a"));
|
||||
}
|
||||
else if (Target.Platform == UnrealTargetPlatform.Linux)
|
||||
{
|
||||
string V8LibraryPath = Path.Combine(LibraryPath, "Linux");
|
||||
PublicAdditionalLibraries.Add(Path.Combine(V8LibraryPath, "libquickjs.a"));
|
||||
}
|
||||
}
|
||||
|
||||
private static void DirectoryCopy(string sourceDirName, string destDirName, bool copySubDirs)
|
||||
{
|
||||
DirectoryInfo dir = new DirectoryInfo(sourceDirName);
|
||||
|
||||
if (!dir.Exists)
|
||||
{
|
||||
throw new DirectoryNotFoundException(
|
||||
"Source directory does not exist or could not be found: "
|
||||
+ sourceDirName);
|
||||
}
|
||||
|
||||
if (!Directory.Exists(destDirName))
|
||||
{
|
||||
Directory.CreateDirectory(destDirName);
|
||||
}
|
||||
|
||||
// Get the files in the directory and copy them to the new location.
|
||||
FileInfo[] files = dir.GetFiles();
|
||||
foreach (FileInfo file in files)
|
||||
{
|
||||
string temppath = Path.Combine(destDirName, file.Name);
|
||||
file.CopyTo(temppath, true);
|
||||
}
|
||||
|
||||
if (copySubDirs)
|
||||
{
|
||||
DirectoryInfo[] dirs = dir.GetDirectories();
|
||||
foreach (DirectoryInfo subdir in dirs)
|
||||
{
|
||||
string temppath = Path.Combine(destDirName, subdir.Name);
|
||||
DirectoryCopy(subdir.FullName, temppath, copySubDirs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,277 @@
|
||||
/*
|
||||
* 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 "ContainerMeta.h"
|
||||
#include "UObject/Package.h"
|
||||
|
||||
namespace PUERTS_NAMESPACE
|
||||
{
|
||||
FContainerMeta::FContainerMeta()
|
||||
{
|
||||
::memset(&BuiltinProperty, 0, sizeof(BuiltinProperty));
|
||||
|
||||
#if (ENGINE_MAJOR_VERSION == 5 && ENGINE_MINOR_VERSION >= 1) || ENGINE_MAJOR_VERSION > 5
|
||||
PropertyMetaRoot = FindObject<UScriptStruct>(nullptr, TEXT("/Script/JsEnv.PropertyMetaRoot"));
|
||||
#else
|
||||
PropertyMetaRoot = FindObject<UScriptStruct>(ANY_PACKAGE, TEXT("PropertyMetaRoot"));
|
||||
#endif
|
||||
}
|
||||
|
||||
FContainerMeta::~FContainerMeta()
|
||||
{
|
||||
#if ENGINE_MINOR_VERSION >= 25 || ENGINE_MAJOR_VERSION > 4
|
||||
// for (auto KV : ObjectPropertyMap)
|
||||
//{
|
||||
// delete KV.Value;
|
||||
//}
|
||||
#else
|
||||
for (int i = 0; i < MaxBuiltinType; i++)
|
||||
{
|
||||
if (BuiltinProperty[i])
|
||||
{
|
||||
// UE_LOG(LogTemp, Warning, TEXT("BuiltinProperty RemoveFromRoot %s"), *BuiltinProperty[i]->GetName());
|
||||
BuiltinProperty[i]->RemoveFromRoot();
|
||||
}
|
||||
}
|
||||
for (auto KV : ObjectPropertyMap)
|
||||
{
|
||||
// UE_LOG(LogTemp, Warning, TEXT("BuiltinProperty RemoveFromRoot %s"), *KV.Value->GetName());
|
||||
KV.Value->RemoveFromRoot();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
PropertyMacro* FContainerMeta::GetBuiltinProperty(BuiltinType type)
|
||||
{
|
||||
PropertyMacro* Ret = nullptr;
|
||||
|
||||
if (type < MaxBuiltinType)
|
||||
{
|
||||
if (BuiltinProperty[type])
|
||||
{
|
||||
return BuiltinProperty[type];
|
||||
}
|
||||
|
||||
switch (type)
|
||||
{
|
||||
#if ENGINE_MINOR_VERSION < 25 && ENGINE_MAJOR_VERSION < 5
|
||||
case TBool:
|
||||
Ret = new (EC_InternalUseOnlyConstructor, PropertyMetaRoot, NAME_None, RF_Transient)
|
||||
UBoolProperty(FObjectInitializer(), EC_CppProperty, 0, (EPropertyFlags) 0, 0xFF, 1, true);
|
||||
break;
|
||||
case TByte:
|
||||
Ret = new (EC_InternalUseOnlyConstructor, PropertyMetaRoot, NAME_None, RF_Transient)
|
||||
UByteProperty(FObjectInitializer(), EC_CppProperty, 0, CPF_HasGetValueTypeHash);
|
||||
break;
|
||||
case TInt:
|
||||
Ret = new (EC_InternalUseOnlyConstructor, PropertyMetaRoot, NAME_None, RF_Transient)
|
||||
UIntProperty(FObjectInitializer(), EC_CppProperty, 0, CPF_HasGetValueTypeHash);
|
||||
break;
|
||||
case TFloat:
|
||||
Ret = new (EC_InternalUseOnlyConstructor, PropertyMetaRoot, NAME_None, RF_Transient)
|
||||
UFloatProperty(FObjectInitializer(), EC_CppProperty, 0, CPF_HasGetValueTypeHash);
|
||||
break;
|
||||
case TDouble:
|
||||
Ret = new (EC_InternalUseOnlyConstructor, PropertyMetaRoot, NAME_None, RF_Transient)
|
||||
UDoubleProperty(FObjectInitializer(), EC_CppProperty, 0, CPF_HasGetValueTypeHash);
|
||||
break;
|
||||
case TInt64:
|
||||
Ret = new (EC_InternalUseOnlyConstructor, PropertyMetaRoot, NAME_None, RF_Transient)
|
||||
UInt64Property(FObjectInitializer(), EC_CppProperty, 0, CPF_HasGetValueTypeHash);
|
||||
break;
|
||||
case TString:
|
||||
Ret = new (EC_InternalUseOnlyConstructor, PropertyMetaRoot, NAME_None, RF_Transient)
|
||||
UStrProperty(FObjectInitializer(), EC_CppProperty, 0, CPF_HasGetValueTypeHash);
|
||||
break;
|
||||
case TText:
|
||||
Ret = new (EC_InternalUseOnlyConstructor, PropertyMetaRoot, NAME_None, RF_Transient)
|
||||
UNameProperty(FObjectInitializer(), EC_CppProperty, 0, CPF_HasGetValueTypeHash);
|
||||
break;
|
||||
case TName:
|
||||
Ret = new (EC_InternalUseOnlyConstructor, PropertyMetaRoot, NAME_None, RF_Transient)
|
||||
UTextProperty(FObjectInitializer(), EC_CppProperty, 0, CPF_HasGetValueTypeHash);
|
||||
break;
|
||||
#elif ENGINE_MINOR_VERSION > 0 && ENGINE_MAJOR_VERSION > 4
|
||||
case TBool:
|
||||
Ret = new FBoolProperty(PropertyMetaRoot, NAME_None, RF_Transient);
|
||||
static_cast<FBoolProperty*>(Ret)->SetBoolSize(1, true, 0xFF);
|
||||
break;
|
||||
case TByte:
|
||||
Ret = new FByteProperty(PropertyMetaRoot, NAME_None, RF_Transient);
|
||||
Ret->PropertyFlags |= CPF_HasGetValueTypeHash;
|
||||
break;
|
||||
case TInt:
|
||||
Ret = new FIntProperty(PropertyMetaRoot, NAME_None, RF_Transient);
|
||||
Ret->PropertyFlags |= CPF_HasGetValueTypeHash;
|
||||
break;
|
||||
case TFloat:
|
||||
Ret = new FFloatProperty(PropertyMetaRoot, NAME_None, RF_Transient);
|
||||
Ret->PropertyFlags |= CPF_HasGetValueTypeHash;
|
||||
break;
|
||||
case TDouble:
|
||||
Ret = new FDoubleProperty(PropertyMetaRoot, NAME_None, RF_Transient);
|
||||
Ret->PropertyFlags |= CPF_HasGetValueTypeHash;
|
||||
break;
|
||||
case TInt64:
|
||||
Ret = new FInt64Property(PropertyMetaRoot, NAME_None, RF_Transient);
|
||||
Ret->PropertyFlags |= CPF_HasGetValueTypeHash;
|
||||
break;
|
||||
case TString:
|
||||
Ret = new FStrProperty(PropertyMetaRoot, NAME_None, RF_Transient);
|
||||
Ret->PropertyFlags |= CPF_HasGetValueTypeHash;
|
||||
break;
|
||||
case TText:
|
||||
Ret = new FTextProperty(PropertyMetaRoot, NAME_None, RF_Transient);
|
||||
Ret->PropertyFlags |= CPF_HasGetValueTypeHash;
|
||||
break;
|
||||
case TName:
|
||||
Ret = new FNameProperty(PropertyMetaRoot, NAME_None, RF_Transient);
|
||||
Ret->PropertyFlags |= CPF_HasGetValueTypeHash;
|
||||
break;
|
||||
#else
|
||||
case TBool:
|
||||
Ret = new FBoolProperty(PropertyMetaRoot, NAME_None, RF_Transient, 0, (EPropertyFlags) 0, 0xFF, 1, true);
|
||||
break;
|
||||
case TByte:
|
||||
Ret = new FByteProperty(PropertyMetaRoot, NAME_None, RF_Transient, 0, CPF_HasGetValueTypeHash);
|
||||
break;
|
||||
case TInt:
|
||||
Ret = new FIntProperty(PropertyMetaRoot, NAME_None, RF_Transient, 0, CPF_HasGetValueTypeHash);
|
||||
break;
|
||||
case TFloat:
|
||||
Ret = new FFloatProperty(PropertyMetaRoot, NAME_None, RF_Transient, 0, CPF_HasGetValueTypeHash);
|
||||
break;
|
||||
case TDouble:
|
||||
Ret = new FDoubleProperty(PropertyMetaRoot, NAME_None, RF_Transient, 0, CPF_HasGetValueTypeHash);
|
||||
break;
|
||||
case TInt64:
|
||||
Ret = new FInt64Property(PropertyMetaRoot, NAME_None, RF_Transient, 0, CPF_HasGetValueTypeHash);
|
||||
break;
|
||||
case TString:
|
||||
Ret = new FStrProperty(PropertyMetaRoot, NAME_None, RF_Transient, 0, CPF_HasGetValueTypeHash);
|
||||
break;
|
||||
case TText:
|
||||
Ret = new FTextProperty(PropertyMetaRoot, NAME_None, RF_Transient, 0, CPF_HasGetValueTypeHash);
|
||||
break;
|
||||
case TName:
|
||||
Ret = new FNameProperty(PropertyMetaRoot, NAME_None, RF_Transient, 0, CPF_HasGetValueTypeHash);
|
||||
break;
|
||||
#endif
|
||||
case MaxBuiltinType:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (Ret)
|
||||
{
|
||||
#if ENGINE_MINOR_VERSION < 25 && ENGINE_MAJOR_VERSION < 5
|
||||
Ret->AddToRoot();
|
||||
#endif
|
||||
BuiltinProperty[type] = Ret;
|
||||
}
|
||||
}
|
||||
|
||||
return Ret;
|
||||
}
|
||||
|
||||
PropertyMacro* FContainerMeta::GetObjectProperty(UField* Field)
|
||||
{
|
||||
auto Iter = ObjectPropertyMap.Find(Field);
|
||||
if (Iter)
|
||||
{
|
||||
return *Iter;
|
||||
}
|
||||
|
||||
PropertyMacro* Ret = nullptr;
|
||||
|
||||
if (auto Class = Cast<UClass>(Field))
|
||||
{
|
||||
#if ENGINE_MINOR_VERSION < 25 && ENGINE_MAJOR_VERSION < 5
|
||||
Ret = new (EC_InternalUseOnlyConstructor, PropertyMetaRoot, NAME_None, RF_Transient)
|
||||
UObjectProperty(FObjectInitializer(), EC_CppProperty, 0, CPF_HasGetValueTypeHash, Class);
|
||||
#elif ENGINE_MINOR_VERSION > 0 && ENGINE_MAJOR_VERSION > 4
|
||||
Ret = new FObjectProperty(PropertyMetaRoot, NAME_None, RF_Transient);
|
||||
static_cast<FObjectProperty*>(Ret)->PropertyClass = Class;
|
||||
Ret->PropertyFlags |= CPF_HasGetValueTypeHash;
|
||||
#else
|
||||
Ret = new FObjectProperty(PropertyMetaRoot, NAME_None, RF_Transient, 0, CPF_HasGetValueTypeHash, Class);
|
||||
#endif
|
||||
}
|
||||
else if (auto ScriptStruct = Cast<UScriptStruct>(Field))
|
||||
{
|
||||
#if ENGINE_MINOR_VERSION < 25 && ENGINE_MAJOR_VERSION < 5
|
||||
Ret = new (EC_InternalUseOnlyConstructor, PropertyMetaRoot, NAME_None, RF_Transient)
|
||||
UStructProperty(FObjectInitializer(), EC_CppProperty, 0, CPF_HasGetValueTypeHash, ScriptStruct);
|
||||
#elif ENGINE_MINOR_VERSION > 0 && ENGINE_MAJOR_VERSION > 4
|
||||
Ret = new FStructProperty(PropertyMetaRoot, NAME_None, RF_Transient);
|
||||
static_cast<FStructProperty*>(Ret)->Struct = ScriptStruct;
|
||||
Ret->ElementSize = ScriptStruct->PropertiesSize;
|
||||
Ret->PropertyFlags |= CPF_HasGetValueTypeHash;
|
||||
#else
|
||||
Ret = new FStructProperty(PropertyMetaRoot, NAME_None, RF_Transient, 0, CPF_HasGetValueTypeHash, ScriptStruct);
|
||||
#endif
|
||||
}
|
||||
else if (auto Enum = Cast<UEnum>(Field))
|
||||
{
|
||||
#if ENGINE_MINOR_VERSION < 25 && ENGINE_MAJOR_VERSION < 5
|
||||
UEnumProperty* EnumProp = new (EC_InternalUseOnlyConstructor, ScriptStruct, NAME_None, RF_Transient)
|
||||
UEnumProperty(FObjectInitializer(), EC_CppProperty, 0, CPF_HasGetValueTypeHash, Enum);
|
||||
UNumericProperty* UnderlyingProp = NewObject<UByteProperty>(EnumProp, TEXT("UnderlyingType"));
|
||||
EnumProp->AddCppProperty(UnderlyingProp);
|
||||
Ret = EnumProp;
|
||||
#else
|
||||
if (Enum->GetCppForm() == UEnum::ECppForm::EnumClass)
|
||||
{
|
||||
FEnumProperty* EnumProp =
|
||||
new FEnumProperty(PropertyMetaRoot, NAME_None, RF_Transient, 0, CPF_HasGetValueTypeHash, Enum);
|
||||
FNumericProperty* UnderlyingProp = new FByteProperty(EnumProp, TEXT("UnderlyingType"), RF_Transient);
|
||||
EnumProp->AddCppProperty(UnderlyingProp);
|
||||
EnumProp->ElementSize = UnderlyingProp->ElementSize;
|
||||
EnumProp->PropertyFlags |= CPF_IsPlainOldData | CPF_NoDestructor | CPF_ZeroConstructor;
|
||||
|
||||
Ret = EnumProp;
|
||||
}
|
||||
else
|
||||
{
|
||||
FByteProperty* ByteProp = new FByteProperty(PropertyMetaRoot, NAME_None, RF_Transient);
|
||||
ByteProp->Enum = Enum;
|
||||
|
||||
Ret = ByteProp;
|
||||
}
|
||||
|
||||
Ret->SetPropertyFlags(CPF_HasGetValueTypeHash);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#if ENGINE_MINOR_VERSION < 25 && ENGINE_MAJOR_VERSION < 5
|
||||
Ret->AddToRoot();
|
||||
#endif
|
||||
|
||||
ObjectPropertyMap.Add(Field, Ret);
|
||||
return Ret;
|
||||
}
|
||||
|
||||
void FContainerMeta::NotifyElementTypeDeleted(const UField* Field)
|
||||
{
|
||||
auto Iter = ObjectPropertyMap.Find(Field);
|
||||
if (Iter)
|
||||
{
|
||||
#if ENGINE_MINOR_VERSION < 25 && ENGINE_MAJOR_VERSION < 5
|
||||
(const_cast<UField*>(Field))->RemoveFromRoot();
|
||||
#else
|
||||
// delete *Iter;
|
||||
#endif
|
||||
ObjectPropertyMap.Remove(Field);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace PUERTS_NAMESPACE
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "PuertsNamespaceDef.h"
|
||||
#include "CoreMinimal.h"
|
||||
#include "Runtime/Launch/Resources/Version.h"
|
||||
#include "PropertyMacros.h"
|
||||
#include "UObject/UnrealType.h"
|
||||
#include "UObject/TextProperty.h"
|
||||
#if !defined(ENGINE_INDEPENDENT_JSENV)
|
||||
#include "EngineMinimal.h"
|
||||
#endif
|
||||
|
||||
USTRUCT(noexport)
|
||||
struct FPropertyMetaRoot
|
||||
{
|
||||
};
|
||||
|
||||
namespace PUERTS_NAMESPACE
|
||||
{
|
||||
enum BuiltinType
|
||||
{
|
||||
TBool = 0,
|
||||
TByte = 1,
|
||||
TInt = 2,
|
||||
TFloat = 3,
|
||||
TDouble = 4,
|
||||
TInt64 = 5,
|
||||
TString = 6,
|
||||
TText = 7,
|
||||
TName = 8,
|
||||
MaxBuiltinType
|
||||
};
|
||||
|
||||
class FContainerMeta
|
||||
{
|
||||
public:
|
||||
FContainerMeta();
|
||||
~FContainerMeta();
|
||||
|
||||
PropertyMacro* GetBuiltinProperty(BuiltinType type);
|
||||
|
||||
PropertyMacro* GetObjectProperty(UField* Field);
|
||||
|
||||
void NotifyElementTypeDeleted(const UField* Struct);
|
||||
|
||||
private:
|
||||
UScriptStruct* PropertyMetaRoot;
|
||||
|
||||
PropertyMacro* BuiltinProperty[MaxBuiltinType];
|
||||
|
||||
TMap<UField*, PropertyMacro*> ObjectPropertyMap;
|
||||
};
|
||||
|
||||
} // namespace PUERTS_NAMESPACE
|
||||
@@ -0,0 +1,850 @@
|
||||
/*
|
||||
* 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 "ContainerWrapper.h"
|
||||
#include "PropertyTranslator.h"
|
||||
|
||||
namespace PUERTS_NAMESPACE
|
||||
{
|
||||
v8::Local<v8::FunctionTemplate> FScriptArrayWrapper::ToFunctionTemplate(v8::Isolate* Isolate)
|
||||
{
|
||||
v8::Isolate::Scope Isolatescope(Isolate);
|
||||
auto Result = v8::FunctionTemplate::New(Isolate, New);
|
||||
Result->InstanceTemplate()->SetInternalFieldCount(4); // 0 Ptr, 1 Property
|
||||
|
||||
Result->PrototypeTemplate()->Set(FV8Utils::InternalString(Isolate, "Num"), v8::FunctionTemplate::New(Isolate, Num));
|
||||
Result->PrototypeTemplate()->Set(FV8Utils::InternalString(Isolate, "Add"), v8::FunctionTemplate::New(Isolate, Add));
|
||||
Result->PrototypeTemplate()->Set(FV8Utils::InternalString(Isolate, "Get"), v8::FunctionTemplate::New(Isolate, Get));
|
||||
Result->PrototypeTemplate()->Set(FV8Utils::InternalString(Isolate, "GetRef"), v8::FunctionTemplate::New(Isolate, GetRef));
|
||||
Result->PrototypeTemplate()->Set(FV8Utils::InternalString(Isolate, "Set"), v8::FunctionTemplate::New(Isolate, Set));
|
||||
Result->PrototypeTemplate()->Set(FV8Utils::InternalString(Isolate, "Contains"), v8::FunctionTemplate::New(Isolate, Contains));
|
||||
Result->PrototypeTemplate()->Set(FV8Utils::InternalString(Isolate, "FindIndex"), v8::FunctionTemplate::New(Isolate, FindIndex));
|
||||
Result->PrototypeTemplate()->Set(FV8Utils::InternalString(Isolate, "RemoveAt"), v8::FunctionTemplate::New(Isolate, RemoveAt));
|
||||
Result->PrototypeTemplate()->Set(
|
||||
FV8Utils::InternalString(Isolate, "IsValidIndex"), v8::FunctionTemplate::New(Isolate, IsValidIndex));
|
||||
Result->PrototypeTemplate()->Set(FV8Utils::InternalString(Isolate, "Empty"), v8::FunctionTemplate::New(Isolate, Empty));
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
void FScriptArrayWrapper::Add(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::HandleScope HandleScope(Isolate);
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
|
||||
if (Info.Length() > 0)
|
||||
{
|
||||
auto Self = FV8Utils::GetPointerFast<FScriptArray>(Info.Holder(), 0);
|
||||
auto Inner = FV8Utils::GetPointerFast<FPropertyTranslator>(Info.Holder(), 1);
|
||||
if (!Inner->IsPropertyValid())
|
||||
{
|
||||
FV8Utils::ThrowException(Isolate, "item info is invalid!");
|
||||
return;
|
||||
}
|
||||
|
||||
int32 Index = AddUninitialized(Self, GetSizeWithAlignment(Inner->Property), Info.Length());
|
||||
for (int i = 0; i < Info.Length(); ++i)
|
||||
{
|
||||
uint8* DataPtr = GetData(Self, GetSizeWithAlignment(Inner->Property), Index + i);
|
||||
Inner->Property->InitializeValue(DataPtr); //使用之前必须得初始化,即使是设置也要
|
||||
Inner->JsToUE(Isolate, Context, Info[i], DataPtr, false);
|
||||
}
|
||||
Info.GetReturnValue().Set(Index);
|
||||
}
|
||||
}
|
||||
|
||||
void FScriptArrayWrapper::InternalGet(const v8::FunctionCallbackInfo<v8::Value>& Info, bool PassByPointer)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::HandleScope HandleScope(Isolate);
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
|
||||
CHECK_V8_ARGS_LEN(1);
|
||||
|
||||
auto Self = FV8Utils::GetPointerFast<FScriptArray>(Info.Holder(), 0);
|
||||
auto Inner = FV8Utils::GetPointerFast<FPropertyTranslator>(Info.Holder(), 1);
|
||||
if (!Inner->IsPropertyValid())
|
||||
{
|
||||
FV8Utils::ThrowException(Isolate, "item info is invalid!");
|
||||
return;
|
||||
}
|
||||
|
||||
int Index = Info[0]->Int32Value(Context).ToChecked();
|
||||
if (Index < 0 || Index >= Self->Num())
|
||||
{
|
||||
FV8Utils::ThrowException(Isolate, TEXT("invalid index"));
|
||||
return;
|
||||
}
|
||||
uint8* DataPtr = GetData(Self, GetSizeWithAlignment(Inner->Property), Index);
|
||||
auto Ret = Inner->UEToJs(Isolate, Context, DataPtr, PassByPointer);
|
||||
if (Inner->NeedLinkOuter && PassByPointer)
|
||||
{
|
||||
LinkOuterImpl(Context, Info.Holder(), Ret);
|
||||
}
|
||||
Info.GetReturnValue().Set(Ret);
|
||||
}
|
||||
|
||||
void FScriptArrayWrapper::Get(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
InternalGet(Info, false);
|
||||
}
|
||||
|
||||
void FScriptArrayWrapper::GetRef(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
InternalGet(Info, true);
|
||||
}
|
||||
|
||||
void FScriptArrayWrapper::Set(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::HandleScope HandleScope(Isolate);
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
|
||||
CHECK_V8_ARGS_LEN(2);
|
||||
|
||||
auto Self = FV8Utils::GetPointerFast<FScriptArray>(Info.Holder(), 0);
|
||||
auto Inner = FV8Utils::GetPointerFast<FPropertyTranslator>(Info.Holder(), 1);
|
||||
if (!Inner->IsPropertyValid())
|
||||
{
|
||||
FV8Utils::ThrowException(Isolate, "item info is invalid!");
|
||||
return;
|
||||
}
|
||||
|
||||
int Index = Info[0]->Int32Value(Context).ToChecked();
|
||||
if (Index < 0 || Index >= Self->Num())
|
||||
{
|
||||
FV8Utils::ThrowException(Isolate, TEXT("invalid index"));
|
||||
return;
|
||||
}
|
||||
uint8* DataPtr = GetData(Self, GetSizeWithAlignment(Inner->Property), Index);
|
||||
Inner->Property->InitializeValue(DataPtr);
|
||||
Inner->JsToUE(Isolate, Context, Info[1], DataPtr, false);
|
||||
}
|
||||
|
||||
void FScriptArrayWrapper::Contains(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
CHECK_V8_ARGS_LEN(1);
|
||||
bool Result = FindIndexInner(Info) != INDEX_NONE;
|
||||
Info.GetReturnValue().Set(Result);
|
||||
}
|
||||
|
||||
void FScriptArrayWrapper::FindIndex(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
CHECK_V8_ARGS_LEN(1);
|
||||
int32 Result = FindIndexInner(Info);
|
||||
Info.GetReturnValue().Set(Result);
|
||||
}
|
||||
|
||||
void FScriptArrayWrapper::RemoveAt(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::HandleScope HandleScope(Isolate);
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
|
||||
CHECK_V8_ARGS_LEN(1);
|
||||
|
||||
auto Self = FV8Utils::GetPointerFast<FScriptArray>(Info.Holder(), 0);
|
||||
auto Inner = FV8Utils::GetPointerFast<FPropertyTranslator>(Info.Holder(), 1);
|
||||
if (!Inner->IsPropertyValid())
|
||||
{
|
||||
FV8Utils::ThrowException(Isolate, "item info is invalid!");
|
||||
return;
|
||||
}
|
||||
|
||||
int32 Index = Info[0]->Int32Value(Context).ToChecked();
|
||||
if (Index < 0 || Index >= Self->Num())
|
||||
{
|
||||
FV8Utils::ThrowException(Isolate, TEXT("invalid index"));
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
FScriptArrayEx::Destruct(Self, Inner->Property, Index, 1);
|
||||
#if ENGINE_MAJOR_VERSION > 4
|
||||
Self->Remove(Index, 1, GetSizeWithAlignment(Inner->Property), __STDCPP_DEFAULT_NEW_ALIGNMENT__);
|
||||
#else
|
||||
Self->Remove(Index, 1, GetSizeWithAlignment(Inner->Property));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void FScriptArrayWrapper::IsValidIndex(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::HandleScope HandleScope(Isolate);
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
|
||||
CHECK_V8_ARGS_LEN(1);
|
||||
|
||||
auto Self = FV8Utils::GetPointerFast<FScriptArray>(Info.Holder(), 0);
|
||||
int32 Index = Info[0]->Int32Value(Context).ToChecked();
|
||||
Info.GetReturnValue().Set(Self->IsValidIndex(Index));
|
||||
}
|
||||
|
||||
void FScriptArrayWrapper::Empty(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::HandleScope HandleScope(Isolate);
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
|
||||
auto Self = FV8Utils::GetPointerFast<FScriptArray>(Info.Holder(), 0);
|
||||
auto Inner = FV8Utils::GetPointerFast<FPropertyTranslator>(Info.Holder(), 1);
|
||||
if (!Inner->IsPropertyValid())
|
||||
{
|
||||
FV8Utils::ThrowException(Isolate, "item info is invalid!");
|
||||
return;
|
||||
}
|
||||
|
||||
FScriptArrayEx::Empty(Self, Inner->Property);
|
||||
}
|
||||
|
||||
FORCEINLINE int32 FScriptArrayWrapper::AddUninitialized(FScriptArray* ScriptArray, int32 ElementSize, int32 Count)
|
||||
{
|
||||
#if ENGINE_MAJOR_VERSION > 4
|
||||
return ScriptArray->Add(Count, ElementSize, __STDCPP_DEFAULT_NEW_ALIGNMENT__);
|
||||
#else
|
||||
return ScriptArray->Add(Count, ElementSize);
|
||||
#endif
|
||||
}
|
||||
|
||||
FORCEINLINE uint8* FScriptArrayWrapper::GetData(FScriptArray* ScriptArray, int32 ElementSize, int32 Index)
|
||||
{
|
||||
return reinterpret_cast<uint8*>(ScriptArray->GetData()) + Index * ElementSize;
|
||||
}
|
||||
|
||||
FORCEINLINE void FScriptArrayWrapper::Construct(FScriptArray* ScriptArray, FPropertyTranslator* Inner, int32 Index, int32 Count)
|
||||
{
|
||||
int32 ElementSize = GetSizeWithAlignment(Inner->Property);
|
||||
uint8* Dest = GetData(ScriptArray, ElementSize, Index);
|
||||
for (int32 i = 0; i < Count; ++i)
|
||||
{
|
||||
Inner->Property->InitializeValue(Dest);
|
||||
Dest += ElementSize;
|
||||
}
|
||||
}
|
||||
|
||||
int32 FScriptArrayWrapper::FindIndexInner(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::HandleScope HandleScope(Isolate);
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
|
||||
auto Self = FV8Utils::GetPointerFast<FScriptArray>(Info.Holder(), 0);
|
||||
auto Inner = FV8Utils::GetPointerFast<FPropertyTranslator>(Info.Holder(), 1);
|
||||
if (!Inner->IsPropertyValid())
|
||||
{
|
||||
FV8Utils::ThrowException(Isolate, "item info is invalid!");
|
||||
return INDEX_NONE;
|
||||
}
|
||||
auto Property = Inner->Property;
|
||||
|
||||
void* Dest = FMemory_Alloca(GetSizeWithAlignment(Property));
|
||||
Property->InitializeValue(Dest);
|
||||
Inner->JsToUE(Isolate, Context, Info[0], Dest, false);
|
||||
|
||||
const int32 Num = Self->Num();
|
||||
int32 Result = INDEX_NONE;
|
||||
for (int32 i = 0; i < Num; ++i)
|
||||
{
|
||||
uint8* Src = GetData(Self, GetSizeWithAlignment(Property), i);
|
||||
if (Property->Identical(Src, Dest))
|
||||
{
|
||||
Result = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
Property->DestroyValue(Dest);
|
||||
return Result;
|
||||
}
|
||||
|
||||
//---------------------------------------Set-----------------------------------------------
|
||||
|
||||
v8::Local<v8::FunctionTemplate> FScriptSetWrapper::ToFunctionTemplate(v8::Isolate* Isolate)
|
||||
{
|
||||
v8::Isolate::Scope Isolatescope(Isolate);
|
||||
auto Result = v8::FunctionTemplate::New(Isolate, New);
|
||||
Result->InstanceTemplate()->SetInternalFieldCount(4); // 0 Ptr, 1 Property
|
||||
|
||||
Result->PrototypeTemplate()->Set(FV8Utils::InternalString(Isolate, "Num"), v8::FunctionTemplate::New(Isolate, Num));
|
||||
Result->PrototypeTemplate()->Set(FV8Utils::InternalString(Isolate, "Add"), v8::FunctionTemplate::New(Isolate, Add));
|
||||
Result->PrototypeTemplate()->Set(FV8Utils::InternalString(Isolate, "Get"), v8::FunctionTemplate::New(Isolate, Get));
|
||||
Result->PrototypeTemplate()->Set(FV8Utils::InternalString(Isolate, "GetRef"), v8::FunctionTemplate::New(Isolate, GetRef));
|
||||
Result->PrototypeTemplate()->Set(FV8Utils::InternalString(Isolate, "Contains"), v8::FunctionTemplate::New(Isolate, Contains));
|
||||
Result->PrototypeTemplate()->Set(FV8Utils::InternalString(Isolate, "FindIndex"), v8::FunctionTemplate::New(Isolate, FindIndex));
|
||||
Result->PrototypeTemplate()->Set(FV8Utils::InternalString(Isolate, "RemoveAt"), v8::FunctionTemplate::New(Isolate, RemoveAt));
|
||||
Result->PrototypeTemplate()->Set(
|
||||
FV8Utils::InternalString(Isolate, "GetMaxIndex"), v8::FunctionTemplate::New(Isolate, GetMaxIndex));
|
||||
Result->PrototypeTemplate()->Set(
|
||||
FV8Utils::InternalString(Isolate, "IsValidIndex"), v8::FunctionTemplate::New(Isolate, IsValidIndex));
|
||||
Result->PrototypeTemplate()->Set(FV8Utils::InternalString(Isolate, "Empty"), v8::FunctionTemplate::New(Isolate, Empty));
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
void FScriptSetWrapper::Add(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::HandleScope HandleScope(Isolate);
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
|
||||
CHECK_V8_ARGS_LEN(1);
|
||||
|
||||
auto Self = FV8Utils::GetPointerFast<FScriptSet>(Info.Holder(), 0);
|
||||
auto Inner = FV8Utils::GetPointerFast<FPropertyTranslator>(Info.Holder(), 1);
|
||||
if (!Inner->IsPropertyValid())
|
||||
{
|
||||
FV8Utils::ThrowException(Isolate, "item info is invalid!");
|
||||
return;
|
||||
}
|
||||
auto Property = Inner->Property;
|
||||
|
||||
void* DataPtr = FMemory_Alloca(GetSizeWithAlignment(Property));
|
||||
Property->InitializeValue(DataPtr);
|
||||
Inner->JsToUE(Isolate, Context, Info[0], DataPtr, false);
|
||||
|
||||
auto ScriptLayout = FScriptSet::GetScriptLayout(Property->GetSize(), Property->GetMinAlignment());
|
||||
Self->Add(
|
||||
DataPtr, ScriptLayout, [Property](const void* Element) { return Property->GetValueTypeHash(Element); },
|
||||
[Property](const void* A, const void* B) { return Property->Identical(A, B); },
|
||||
[Property, DataPtr](void* Element)
|
||||
{
|
||||
Property->InitializeValue(Element);
|
||||
Property->CopySingleValue(Element, DataPtr);
|
||||
},
|
||||
[Property](void* Element) { Property->DestroyValue(Element); });
|
||||
Property->DestroyValue(DataPtr);
|
||||
}
|
||||
|
||||
void FScriptSetWrapper::InternalGet(const v8::FunctionCallbackInfo<v8::Value>& Info, bool PassByPointer)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::HandleScope HandleScope(Isolate);
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
|
||||
CHECK_V8_ARGS_LEN(1);
|
||||
|
||||
auto Self = FV8Utils::GetPointerFast<FScriptSet>(Info.Holder(), 0);
|
||||
auto Inner = FV8Utils::GetPointerFast<FPropertyTranslator>(Info.Holder(), 1);
|
||||
if (!Inner->IsPropertyValid())
|
||||
{
|
||||
FV8Utils::ThrowException(Isolate, "item info is invalid!");
|
||||
return;
|
||||
}
|
||||
auto Property = Inner->Property;
|
||||
|
||||
int32 Index = Info[0]->Int32Value(Context).ToChecked();
|
||||
if (Self->IsValidIndex(Index) == false)
|
||||
{
|
||||
FV8Utils::ThrowException(Isolate, "invalid index argument");
|
||||
}
|
||||
else
|
||||
{
|
||||
auto ScriptLayout = FScriptSet::GetScriptLayout(Property->GetSize(), Property->GetMinAlignment());
|
||||
void* Data = Self->GetData(Index, ScriptLayout);
|
||||
auto Ret = Inner->UEToJs(Isolate, Context, Data, PassByPointer);
|
||||
if (Inner->NeedLinkOuter && PassByPointer)
|
||||
{
|
||||
LinkOuterImpl(Context, Info.Holder(), Ret);
|
||||
}
|
||||
Info.GetReturnValue().Set(Ret);
|
||||
}
|
||||
}
|
||||
|
||||
void FScriptSetWrapper::Get(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
InternalGet(Info, false);
|
||||
}
|
||||
|
||||
void FScriptSetWrapper::GetRef(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
InternalGet(Info, true);
|
||||
}
|
||||
|
||||
void FScriptSetWrapper::Contains(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
CHECK_V8_ARGS_LEN(1);
|
||||
bool Result = FindIndexInner(Info) != INDEX_NONE;
|
||||
Info.GetReturnValue().Set(Result);
|
||||
}
|
||||
|
||||
void FScriptSetWrapper::FindIndex(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
CHECK_V8_ARGS_LEN(1);
|
||||
int32 Result = FindIndexInner(Info);
|
||||
Info.GetReturnValue().Set(Result);
|
||||
}
|
||||
|
||||
void FScriptSetWrapper::RemoveAt(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::HandleScope HandleScope(Isolate);
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
|
||||
CHECK_V8_ARGS_LEN(1);
|
||||
|
||||
auto Self = FV8Utils::GetPointerFast<FScriptSet>(Info.Holder(), 0);
|
||||
auto Inner = FV8Utils::GetPointerFast<FPropertyTranslator>(Info.Holder(), 1);
|
||||
if (!Inner->IsPropertyValid())
|
||||
{
|
||||
FV8Utils::ThrowException(Isolate, "item info is invalid!");
|
||||
return;
|
||||
}
|
||||
auto Property = Inner->Property;
|
||||
|
||||
int32 Index = Info[0]->Int32Value(Context).ToChecked();
|
||||
if (Self->IsValidIndex(Index) == false)
|
||||
{
|
||||
FV8Utils::ThrowException(Isolate, "invalid index argument");
|
||||
}
|
||||
else
|
||||
{
|
||||
auto ScriptLayout = FScriptSet::GetScriptLayout(Property->GetSize(), Property->GetMinAlignment());
|
||||
void* Data = Self->GetData(Index, ScriptLayout);
|
||||
FScriptSetEx::Destruct(Self, Property, Index, 1);
|
||||
Self->RemoveAt(Index, ScriptLayout);
|
||||
}
|
||||
}
|
||||
|
||||
void FScriptSetWrapper::GetMaxIndex(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::HandleScope HandleScope(Isolate);
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
|
||||
auto Self = FV8Utils::GetPointerFast<FScriptSet>(Info.Holder(), 0);
|
||||
uint32 Result = Self->GetMaxIndex();
|
||||
Info.GetReturnValue().Set(Result);
|
||||
}
|
||||
|
||||
void FScriptSetWrapper::IsValidIndex(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::HandleScope HandleScope(Isolate);
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
|
||||
CHECK_V8_ARGS_LEN(1);
|
||||
|
||||
auto Self = FV8Utils::GetPointerFast<FScriptSet>(Info.Holder(), 0);
|
||||
int32 Index = Info[0]->Int32Value(Context).ToChecked();
|
||||
uint32 Result = Self->IsValidIndex(Index);
|
||||
Info.GetReturnValue().Set(Result);
|
||||
}
|
||||
|
||||
void FScriptSetWrapper::Empty(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::HandleScope HandleScope(Isolate);
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
|
||||
auto Self = FV8Utils::GetPointerFast<FScriptSet>(Info.Holder(), 0);
|
||||
auto Inner = FV8Utils::GetPointerFast<FPropertyTranslator>(Info.Holder(), 1);
|
||||
if (!Inner->IsPropertyValid())
|
||||
{
|
||||
FV8Utils::ThrowException(Isolate, "item info is invalid!");
|
||||
return;
|
||||
}
|
||||
|
||||
FScriptSetEx::Empty(Self, Inner->Property);
|
||||
}
|
||||
|
||||
int32 FScriptSetWrapper::FindIndexInner(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::HandleScope HandleScope(Isolate);
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
|
||||
auto Self = FV8Utils::GetPointerFast<FScriptSet>(Info.Holder(), 0);
|
||||
auto Inner = FV8Utils::GetPointerFast<FPropertyTranslator>(Info.Holder(), 1);
|
||||
if (!Inner->IsPropertyValid())
|
||||
{
|
||||
FV8Utils::ThrowException(Isolate, "item info is invalid!");
|
||||
return INDEX_NONE;
|
||||
}
|
||||
auto Property = Inner->Property;
|
||||
|
||||
void* DataPtr = FMemory_Alloca(GetSizeWithAlignment(Property));
|
||||
Property->InitializeValue(DataPtr);
|
||||
|
||||
Inner->JsToUE(Isolate, Context, Info[0], DataPtr, false);
|
||||
|
||||
auto ScriptLayout = FScriptSet::GetScriptLayout(Property->GetSize(), Property->GetMinAlignment());
|
||||
|
||||
int32 Result = Self->FindIndex(
|
||||
DataPtr, ScriptLayout, [Property](const void* Element) { return Property->GetValueTypeHash(Element); },
|
||||
[Property](const void* A, const void* B) { return Property->Identical(A, B); });
|
||||
Property->DestroyValue(DataPtr);
|
||||
return Result;
|
||||
}
|
||||
|
||||
//---------------------------------------Map-----------------------------------------------
|
||||
v8::Local<v8::FunctionTemplate> FScriptMapWrapper::ToFunctionTemplate(v8::Isolate* Isolate)
|
||||
{
|
||||
v8::Isolate::Scope Isolatescope(Isolate);
|
||||
auto Result = v8::FunctionTemplate::New(Isolate, New);
|
||||
Result->InstanceTemplate()->SetInternalFieldCount(6); // 0 Ptr, 1-2 Property
|
||||
|
||||
Result->PrototypeTemplate()->Set(FV8Utils::InternalString(Isolate, "Num"), v8::FunctionTemplate::New(Isolate, Num));
|
||||
Result->PrototypeTemplate()->Set(FV8Utils::InternalString(Isolate, "Add"), v8::FunctionTemplate::New(Isolate, Add));
|
||||
Result->PrototypeTemplate()->Set(FV8Utils::InternalString(Isolate, "Get"), v8::FunctionTemplate::New(Isolate, Get));
|
||||
Result->PrototypeTemplate()->Set(FV8Utils::InternalString(Isolate, "GetRef"), v8::FunctionTemplate::New(Isolate, GetRef));
|
||||
Result->PrototypeTemplate()->Set(FV8Utils::InternalString(Isolate, "Set"), v8::FunctionTemplate::New(Isolate, Set));
|
||||
Result->PrototypeTemplate()->Set(FV8Utils::InternalString(Isolate, "Remove"), v8::FunctionTemplate::New(Isolate, Remove));
|
||||
Result->PrototypeTemplate()->Set(
|
||||
FV8Utils::InternalString(Isolate, "GetMaxIndex"), v8::FunctionTemplate::New(Isolate, GetMaxIndex));
|
||||
Result->PrototypeTemplate()->Set(
|
||||
FV8Utils::InternalString(Isolate, "IsValidIndex"), v8::FunctionTemplate::New(Isolate, IsValidIndex));
|
||||
Result->PrototypeTemplate()->Set(FV8Utils::InternalString(Isolate, "GetKey"), v8::FunctionTemplate::New(Isolate, GetKey));
|
||||
Result->PrototypeTemplate()->Set(FV8Utils::InternalString(Isolate, "Empty"), v8::FunctionTemplate::New(Isolate, Empty));
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
void FScriptMapWrapper::Add(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::HandleScope HandleScope(Isolate);
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
|
||||
CHECK_V8_ARGS_LEN(2);
|
||||
|
||||
auto Self = FV8Utils::GetPointerFast<FScriptMap>(Info.Holder(), 0);
|
||||
auto KeyPropertyTranslator = FV8Utils::GetPointerFast<FPropertyTranslator>(Info.Holder(), 1);
|
||||
auto KeyProperty = KeyPropertyTranslator->Property;
|
||||
auto ValuePropertyTranslator = FV8Utils::GetPointerFast<FPropertyTranslator>(Info.Holder(), 2);
|
||||
auto ValueProperty = ValuePropertyTranslator->Property;
|
||||
if (!KeyPropertyTranslator->IsPropertyValid() || !ValuePropertyTranslator->IsPropertyValid())
|
||||
{
|
||||
FV8Utils::ThrowException(Isolate, "key/value info is invalid!");
|
||||
return;
|
||||
}
|
||||
|
||||
void* KeyPtr = FMemory_Alloca(GetSizeWithAlignment(KeyProperty));
|
||||
KeyProperty->InitializeValue(KeyPtr);
|
||||
|
||||
void* ValuePtr = FMemory_Alloca(GetSizeWithAlignment(ValueProperty));
|
||||
ValueProperty->InitializeValue(ValuePtr);
|
||||
|
||||
KeyPropertyTranslator->JsToUE(Isolate, Context, Info[0], KeyPtr, false);
|
||||
ValuePropertyTranslator->JsToUE(Isolate, Context, Info[1], ValuePtr, false);
|
||||
|
||||
auto ScriptLayout = FScriptMap::GetScriptLayout(
|
||||
KeyProperty->GetSize(), KeyProperty->GetMinAlignment(), ValueProperty->GetSize(), ValueProperty->GetMinAlignment());
|
||||
|
||||
Self->Add(
|
||||
KeyPtr, ValuePtr, ScriptLayout, [KeyProperty](const void* ElementKey) { return KeyProperty->GetValueTypeHash(ElementKey); },
|
||||
[KeyProperty](const void* A, const void* B) { return KeyProperty->Identical(A, B); },
|
||||
[KeyProperty, KeyPtr](void* NewElementKey)
|
||||
{
|
||||
KeyProperty->InitializeValue(NewElementKey);
|
||||
KeyProperty->CopySingleValue(NewElementKey, KeyPtr);
|
||||
},
|
||||
[ValueProperty, ValuePtr](void* NewElementValue)
|
||||
{
|
||||
ValueProperty->InitializeValue(NewElementValue);
|
||||
ValueProperty->CopySingleValue(NewElementValue, ValuePtr);
|
||||
},
|
||||
[ValueProperty, ValuePtr](void* ExistingElementValue) { ValueProperty->CopySingleValue(ExistingElementValue, ValuePtr); },
|
||||
[KeyProperty](void* ElementKey) { KeyProperty->DestroyValue(ElementKey); },
|
||||
[ValueProperty](void* ElementValue) { ValueProperty->DestroyValue(ElementValue); });
|
||||
KeyProperty->DestroyValue(KeyPtr);
|
||||
ValueProperty->DestroyValue(ValuePtr);
|
||||
}
|
||||
|
||||
void FScriptMapWrapper::InternalGet(const v8::FunctionCallbackInfo<v8::Value>& Info, bool PassByPointer)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::HandleScope HandleScope(Isolate);
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
|
||||
CHECK_V8_ARGS_LEN(1);
|
||||
|
||||
auto Self = FV8Utils::GetPointerFast<FScriptMap>(Info.Holder(), 0);
|
||||
auto KeyPropertyTranslator = FV8Utils::GetPointerFast<FPropertyTranslator>(Info.Holder(), 1);
|
||||
auto KeyProperty = KeyPropertyTranslator->Property;
|
||||
auto ValuePropertyTranslator = FV8Utils::GetPointerFast<FPropertyTranslator>(Info.Holder(), 2);
|
||||
auto ValueProperty = ValuePropertyTranslator->Property;
|
||||
if (!KeyPropertyTranslator->IsPropertyValid() || !ValuePropertyTranslator->IsPropertyValid())
|
||||
{
|
||||
FV8Utils::ThrowException(Isolate, "key/value info is invalid!");
|
||||
return;
|
||||
}
|
||||
|
||||
void* KeyPtr = FMemory_Alloca(GetSizeWithAlignment(KeyProperty));
|
||||
KeyProperty->InitializeValue(KeyPtr);
|
||||
KeyPropertyTranslator->JsToUE(Isolate, Context, Info[0], KeyPtr, false);
|
||||
|
||||
auto ScriptLayout = FScriptMap::GetScriptLayout(
|
||||
KeyProperty->GetSize(), KeyProperty->GetMinAlignment(), ValueProperty->GetSize(), ValueProperty->GetMinAlignment());
|
||||
|
||||
void* ValuePtr = Self->FindValue(
|
||||
KeyPtr, ScriptLayout, [KeyProperty](const void* ElementKey) { return KeyProperty->GetValueTypeHash(ElementKey); },
|
||||
[KeyProperty](const void* A, const void* B) { return KeyProperty->Identical(A, B); });
|
||||
|
||||
if (ValuePtr)
|
||||
{
|
||||
auto Ret = ValuePropertyTranslator->UEToJs(Isolate, Context, ValuePtr, PassByPointer);
|
||||
if (ValuePropertyTranslator->NeedLinkOuter && PassByPointer)
|
||||
{
|
||||
LinkOuterImpl(Context, Info.Holder(), Ret);
|
||||
}
|
||||
Info.GetReturnValue().Set(Ret);
|
||||
}
|
||||
KeyProperty->DestroyValue(KeyPtr);
|
||||
}
|
||||
|
||||
void FScriptMapWrapper::Get(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
InternalGet(Info, false);
|
||||
}
|
||||
|
||||
void FScriptMapWrapper::GetRef(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
InternalGet(Info, true);
|
||||
}
|
||||
|
||||
void FScriptMapWrapper::Set(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
Add(Info);
|
||||
}
|
||||
|
||||
void FScriptMapWrapper::Remove(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::HandleScope HandleScope(Isolate);
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
|
||||
CHECK_V8_ARGS_LEN(1);
|
||||
|
||||
auto Self = FV8Utils::GetPointerFast<FScriptMap>(Info.Holder(), 0);
|
||||
auto KeyPropertyTranslator = FV8Utils::GetPointerFast<FPropertyTranslator>(Info.Holder(), 1);
|
||||
auto KeyProperty = KeyPropertyTranslator->Property;
|
||||
auto ValuePropertyTranslator = FV8Utils::GetPointerFast<FPropertyTranslator>(Info.Holder(), 2);
|
||||
auto ValueProperty = ValuePropertyTranslator->Property;
|
||||
if (!KeyPropertyTranslator->IsPropertyValid() || !ValuePropertyTranslator->IsPropertyValid())
|
||||
{
|
||||
FV8Utils::ThrowException(Isolate, "key/value info is invalid!");
|
||||
return;
|
||||
}
|
||||
|
||||
void* KeyPtr = FMemory_Alloca(GetSizeWithAlignment(KeyProperty));
|
||||
KeyProperty->InitializeValue(KeyPtr);
|
||||
KeyPropertyTranslator->JsToUE(Isolate, Context, Info[0], KeyPtr, false);
|
||||
|
||||
auto ScriptLayout = GetScriptLayout(KeyProperty, ValueProperty);
|
||||
int32 Index = Self->FindPairIndex(
|
||||
KeyPtr, ScriptLayout, [KeyProperty](const void* Key) { return KeyProperty->GetValueTypeHash(Key); },
|
||||
[KeyProperty](const void* A, const void* B) { return KeyProperty->Identical(A, B); });
|
||||
if (Index == INDEX_NONE)
|
||||
{
|
||||
FV8Utils::ThrowException(Isolate, TEXT("invalid key argument"));
|
||||
}
|
||||
else
|
||||
{
|
||||
FScriptMapEx::Destruct(Self, KeyProperty, ValueProperty, Index, 1);
|
||||
Self->RemoveAt(Index, ScriptLayout);
|
||||
}
|
||||
KeyProperty->DestroyValue(KeyPtr);
|
||||
}
|
||||
|
||||
void FScriptMapWrapper::GetMaxIndex(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::HandleScope HandleScope(Isolate);
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
|
||||
auto Self = FV8Utils::GetPointerFast<FScriptMap>(Info.Holder(), 0);
|
||||
int32 Result = Self->GetMaxIndex();
|
||||
Info.GetReturnValue().Set(Result);
|
||||
}
|
||||
|
||||
void FScriptMapWrapper::IsValidIndex(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::HandleScope HandleScope(Isolate);
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
|
||||
CHECK_V8_ARGS_LEN(1);
|
||||
|
||||
auto Self = FV8Utils::GetPointerFast<FScriptMap>(Info.Holder(), 0);
|
||||
int32 Index = Info[0]->Int32Value(Context).ToChecked();
|
||||
Info.GetReturnValue().Set(Self->IsValidIndex(Index));
|
||||
}
|
||||
|
||||
void FScriptMapWrapper::GetKey(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::HandleScope HandleScope(Isolate);
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
|
||||
CHECK_V8_ARGS_LEN(1);
|
||||
|
||||
auto Self = FV8Utils::GetPointerFast<FScriptMap>(Info.Holder(), 0);
|
||||
int32 Index = Info[0]->Int32Value(Context).ToChecked();
|
||||
if (Self->IsValidIndex(Index) == false)
|
||||
{
|
||||
FV8Utils::ThrowException(Isolate, TEXT("the argument is an invalid index"));
|
||||
Info.GetReturnValue().Set(v8::Undefined(Isolate));
|
||||
}
|
||||
else
|
||||
{
|
||||
auto KeyPropertyTranslator = FV8Utils::GetPointerFast<FPropertyTranslator>(Info.Holder(), 1);
|
||||
auto KeyProperty = KeyPropertyTranslator->Property;
|
||||
auto ValuePropertyTranslator = FV8Utils::GetPointerFast<FPropertyTranslator>(Info.Holder(), 2);
|
||||
auto ValueProperty = ValuePropertyTranslator->Property;
|
||||
if (!KeyPropertyTranslator->IsPropertyValid() || !ValuePropertyTranslator->IsPropertyValid())
|
||||
{
|
||||
FV8Utils::ThrowException(Isolate, "key/value info is invalid!");
|
||||
return;
|
||||
}
|
||||
|
||||
auto ScriptLayout = GetScriptLayout(KeyProperty, ValueProperty);
|
||||
uint8* Data = reinterpret_cast<uint8*>(Self->GetData(Index, ScriptLayout));
|
||||
void* KeyPtr = Data + GetKeyOffset(ScriptLayout);
|
||||
Info.GetReturnValue().Set(KeyPropertyTranslator->UEToJs(Isolate, Context, KeyPtr, false));
|
||||
}
|
||||
}
|
||||
|
||||
void FScriptMapWrapper::Empty(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::HandleScope HandleScope(Isolate);
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
|
||||
auto Self = FV8Utils::GetPointerFast<FScriptMap>(Info.Holder(), 0);
|
||||
auto KeyPropertyTranslator = FV8Utils::GetPointerFast<FPropertyTranslator>(Info.Holder(), 1);
|
||||
auto KeyProperty = KeyPropertyTranslator->Property;
|
||||
auto ValuePropertyTranslator = FV8Utils::GetPointerFast<FPropertyTranslator>(Info.Holder(), 2);
|
||||
auto ValueProperty = ValuePropertyTranslator->Property;
|
||||
if (!KeyPropertyTranslator->IsPropertyValid() || !ValuePropertyTranslator->IsPropertyValid())
|
||||
{
|
||||
FV8Utils::ThrowException(Isolate, "key/value info is invalid!");
|
||||
return;
|
||||
}
|
||||
|
||||
FScriptMapEx::Empty(Self, KeyProperty, ValueProperty);
|
||||
}
|
||||
|
||||
FScriptMapLayout FScriptMapWrapper::GetScriptLayout(const PropertyMacro* KeyProperty, const PropertyMacro* ValueProperty)
|
||||
{
|
||||
return FScriptMap::GetScriptLayout(
|
||||
KeyProperty->GetSize(), KeyProperty->GetMinAlignment(), ValueProperty->GetSize(), ValueProperty->GetMinAlignment());
|
||||
}
|
||||
|
||||
//---------------------------------------Fix Size Array-----------------------------------------------
|
||||
v8::Local<v8::FunctionTemplate> FFixSizeArrayWrapper::ToFunctionTemplate(v8::Isolate* Isolate)
|
||||
{
|
||||
v8::Isolate::Scope Isolatescope(Isolate);
|
||||
auto Result = v8::FunctionTemplate::New(Isolate, New);
|
||||
Result->InstanceTemplate()->SetInternalFieldCount(4); // 0 Ptr, 1 Property
|
||||
|
||||
Result->PrototypeTemplate()->Set(FV8Utils::InternalString(Isolate, "Num"), v8::FunctionTemplate::New(Isolate, Num));
|
||||
Result->PrototypeTemplate()->Set(FV8Utils::InternalString(Isolate, "Get"), v8::FunctionTemplate::New(Isolate, Get));
|
||||
Result->PrototypeTemplate()->Set(FV8Utils::InternalString(Isolate, "GetRef"), v8::FunctionTemplate::New(Isolate, GetRef));
|
||||
Result->PrototypeTemplate()->Set(FV8Utils::InternalString(Isolate, "Set"), v8::FunctionTemplate::New(Isolate, Set));
|
||||
// Result->PrototypeTemplate()->SetIndexedPropertyHandler(Getter, Setter);
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
void FFixSizeArrayWrapper::Num(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::HandleScope HandleScope(Isolate);
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
|
||||
auto Inner = FV8Utils::GetPointerFast<FPropertyTranslator>(Info.Holder(), 1);
|
||||
if (!Inner->IsPropertyValid())
|
||||
{
|
||||
FV8Utils::ThrowException(Isolate, "item info is invalid!");
|
||||
return;
|
||||
}
|
||||
Info.GetReturnValue().Set(Inner->Property->ArrayDim);
|
||||
}
|
||||
|
||||
void FFixSizeArrayWrapper::InternalGet(const v8::FunctionCallbackInfo<v8::Value>& Info, bool PassByPointer)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::HandleScope HandleScope(Isolate);
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
|
||||
auto Self = FV8Utils::GetPointerFast<uint8>(Info.Holder(), 0);
|
||||
auto Inner = FV8Utils::GetPointerFast<FPropertyTranslator>(Info.Holder(), 1);
|
||||
if (!Inner->IsPropertyValid())
|
||||
{
|
||||
FV8Utils::ThrowException(Isolate, "item info is invalid!");
|
||||
return;
|
||||
}
|
||||
auto Property = Inner->Property;
|
||||
|
||||
int32 Index = -1;
|
||||
|
||||
if (Info[0]->IsInt32())
|
||||
{
|
||||
Index = Info[0]->Int32Value(Context).ToChecked();
|
||||
}
|
||||
|
||||
if (Index < 0 || Index >= Property->ArrayDim)
|
||||
{
|
||||
FV8Utils::ThrowException(Isolate, "invalid index");
|
||||
return;
|
||||
}
|
||||
|
||||
auto Ptr = Self + Property->ElementSize * Index;
|
||||
|
||||
auto Ret = Inner->UEToJs(Isolate, Context, Ptr, PassByPointer);
|
||||
if (Inner->NeedLinkOuter && PassByPointer)
|
||||
{
|
||||
LinkOuterImpl(Context, Info.Holder(), Ret);
|
||||
}
|
||||
Info.GetReturnValue().Set(Ret);
|
||||
}
|
||||
|
||||
void FFixSizeArrayWrapper::Get(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
InternalGet(Info, false);
|
||||
}
|
||||
|
||||
void FFixSizeArrayWrapper::GetRef(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
InternalGet(Info, true);
|
||||
}
|
||||
|
||||
void FFixSizeArrayWrapper::Set(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::HandleScope HandleScope(Isolate);
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
|
||||
auto Self = FV8Utils::GetPointerFast<uint8>(Info.Holder(), 0);
|
||||
auto Inner = FV8Utils::GetPointerFast<FPropertyTranslator>(Info.Holder(), 1);
|
||||
if (!Inner->IsPropertyValid())
|
||||
{
|
||||
FV8Utils::ThrowException(Isolate, "item info is invalid!");
|
||||
return;
|
||||
}
|
||||
auto Property = Inner->Property;
|
||||
|
||||
int32 Index = -1;
|
||||
|
||||
if (Info[0]->IsInt32())
|
||||
{
|
||||
Index = Info[0]->Int32Value(Context).ToChecked();
|
||||
}
|
||||
|
||||
if (Index < 0 || Index >= Property->ArrayDim)
|
||||
{
|
||||
FV8Utils::ThrowException(Isolate, "invalid index");
|
||||
return;
|
||||
}
|
||||
|
||||
auto Ptr = Self + Property->ElementSize * Index;
|
||||
|
||||
Inner->JsToUE(Isolate, Context, Info[1], Ptr, true);
|
||||
}
|
||||
} // namespace PUERTS_NAMESPACE
|
||||
@@ -0,0 +1,417 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "CoreUObject.h"
|
||||
#include "V8Utils.h"
|
||||
#include "ObjectMapper.h"
|
||||
#include "JSLogger.h"
|
||||
|
||||
#include "NamespaceDef.h"
|
||||
|
||||
PRAGMA_DISABLE_UNDEFINED_IDENTIFIER_WARNINGS
|
||||
#pragma warning(push, 0)
|
||||
#include "libplatform/libplatform.h"
|
||||
#include "v8.h"
|
||||
#pragma warning(pop)
|
||||
PRAGMA_ENABLE_UNDEFINED_IDENTIFIER_WARNINGS
|
||||
|
||||
namespace PUERTS_NAMESPACE
|
||||
{
|
||||
class FPropertyTranslator;
|
||||
FORCEINLINE int32 GetSizeWithAlignment(PropertyMacro* InProperty)
|
||||
{
|
||||
return Align(InProperty->GetSize(), InProperty->GetMinAlignment());
|
||||
}
|
||||
|
||||
struct FScriptArrayEx
|
||||
{
|
||||
FScriptArray Data;
|
||||
|
||||
#if ENGINE_MINOR_VERSION < 25 && ENGINE_MAJOR_VERSION < 5
|
||||
TWeakObjectPtr<PropertyMacro> PropertyPtr;
|
||||
#else
|
||||
TWeakFieldPtr<PropertyMacro> PropertyPtr;
|
||||
#endif
|
||||
|
||||
FORCEINLINE FScriptArrayEx(PropertyMacro* InProperty)
|
||||
{
|
||||
// UE_LOG(LogTemp, Warning, TEXT("FScriptArrayEx:%p"), this);
|
||||
PropertyPtr = InProperty;
|
||||
}
|
||||
|
||||
FORCEINLINE ~FScriptArrayEx()
|
||||
{
|
||||
// UE_LOG(LogTemp, Warning, TEXT("~FScriptArrayEx:%p"), this);
|
||||
if (PropertyPtr.IsValid())
|
||||
{
|
||||
Empty(&Data, PropertyPtr.Get());
|
||||
}
|
||||
else
|
||||
{
|
||||
UE_LOG(Puerts, Error, TEXT("~FScriptArrayEx: Property is invalid"));
|
||||
}
|
||||
}
|
||||
|
||||
FORCEINLINE static uint8* GetData(FScriptArray* ScriptArray, int32 ElementSize, int32 Index)
|
||||
{
|
||||
return static_cast<uint8*>(ScriptArray->GetData()) + Index * ElementSize;
|
||||
}
|
||||
|
||||
FORCEINLINE static void Destruct(FScriptArray* ScriptArray, PropertyMacro* Property, int32 Index, int32 Count = 1)
|
||||
{
|
||||
const int32 ElementSize = GetSizeWithAlignment(Property);
|
||||
uint8* Dest = GetData(ScriptArray, ElementSize, Index);
|
||||
for (int32 i = 0; i < Count; ++i)
|
||||
{
|
||||
Property->DestroyValue(Dest);
|
||||
Dest += ElementSize;
|
||||
}
|
||||
}
|
||||
|
||||
FORCEINLINE static void Empty(FScriptArray* ScriptArray, PropertyMacro* Property)
|
||||
{
|
||||
Destruct(ScriptArray, Property, 0, ScriptArray->Num());
|
||||
#if ENGINE_MAJOR_VERSION > 4
|
||||
ScriptArray->Empty(0, GetSizeWithAlignment(Property), __STDCPP_DEFAULT_NEW_ALIGNMENT__);
|
||||
#else
|
||||
ScriptArray->Empty(0, GetSizeWithAlignment(Property));
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
struct FScriptSetEx
|
||||
{
|
||||
FScriptSet Data;
|
||||
|
||||
#if ENGINE_MINOR_VERSION < 25 && ENGINE_MAJOR_VERSION < 5
|
||||
TWeakObjectPtr<PropertyMacro> PropertyPtr;
|
||||
#else
|
||||
TWeakFieldPtr<PropertyMacro> PropertyPtr;
|
||||
#endif
|
||||
|
||||
FORCEINLINE FScriptSetEx(PropertyMacro* InProperty)
|
||||
{
|
||||
// UE_LOG(LogTemp, Warning, TEXT("FScriptSetEx:%p"), this);
|
||||
PropertyPtr = InProperty;
|
||||
}
|
||||
|
||||
FORCEINLINE ~FScriptSetEx()
|
||||
{
|
||||
// UE_LOG(LogTemp, Warning, TEXT("~FScriptSetEx:%p"), this);
|
||||
if (PropertyPtr.IsValid())
|
||||
{
|
||||
Empty(&Data, PropertyPtr.Get());
|
||||
}
|
||||
else
|
||||
{
|
||||
UE_LOG(Puerts, Error, TEXT("~FScriptSetEx: Property is invalid"));
|
||||
}
|
||||
}
|
||||
|
||||
FORCEINLINE static void Destruct(FScriptSet* ScriptSet, PropertyMacro* Property, int32 Index, int32 Count = 1)
|
||||
{
|
||||
auto SetLayout = ScriptSet->GetScriptLayout(Property->GetSize(), Property->GetMinAlignment());
|
||||
for (int32 i = Index; i < Index + Count; ++i)
|
||||
{
|
||||
if (ScriptSet->IsValidIndex(i))
|
||||
{
|
||||
void* Data = ScriptSet->GetData(i, SetLayout);
|
||||
Property->DestroyValue(Data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FORCEINLINE static void Empty(FScriptSet* ScriptSet, PropertyMacro* Property)
|
||||
{
|
||||
auto SetLayout = FScriptSet::GetScriptLayout(Property->GetSize(), Property->GetMinAlignment());
|
||||
Destruct(ScriptSet, Property, 0, ScriptSet->Num());
|
||||
ScriptSet->Empty(0, SetLayout);
|
||||
}
|
||||
};
|
||||
|
||||
FORCEINLINE static int32 GetKeyOffset(const FScriptMapLayout& ScriptMapLayout)
|
||||
{
|
||||
#if ENGINE_MINOR_VERSION < 22 && ENGINE_MAJOR_VERSION < 5
|
||||
return ScriptMapLayout.KeyOffset;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
struct FScriptMapEx
|
||||
{
|
||||
FScriptMap Data;
|
||||
|
||||
#if ENGINE_MINOR_VERSION < 25 && ENGINE_MAJOR_VERSION < 5
|
||||
TWeakObjectPtr<PropertyMacro> KeyPropertyPtr;
|
||||
TWeakObjectPtr<PropertyMacro> ValuePropertyPtr;
|
||||
#else
|
||||
TWeakFieldPtr<PropertyMacro> KeyPropertyPtr;
|
||||
TWeakFieldPtr<PropertyMacro> ValuePropertyPtr;
|
||||
#endif
|
||||
|
||||
FORCEINLINE FScriptMapEx(PropertyMacro* InKeyProperty, PropertyMacro* InValueProperty)
|
||||
{
|
||||
// UE_LOG(LogTemp, Warning, TEXT("FScriptMapEx:%p"), this);
|
||||
KeyPropertyPtr = InKeyProperty;
|
||||
ValuePropertyPtr = InValueProperty;
|
||||
}
|
||||
|
||||
FORCEINLINE ~FScriptMapEx()
|
||||
{
|
||||
// UE_LOG(LogTemp, Warning, TEXT("~FScriptMapEx:%p"), this);
|
||||
if (KeyPropertyPtr.IsValid() && ValuePropertyPtr.IsValid())
|
||||
{
|
||||
Empty(&Data, KeyPropertyPtr.Get(), ValuePropertyPtr.Get());
|
||||
}
|
||||
else
|
||||
{
|
||||
UE_LOG(Puerts, Error, TEXT("~FScriptMapEx: Property is invalid"));
|
||||
}
|
||||
}
|
||||
|
||||
FORCEINLINE static FScriptMapLayout GetScriptLayout(const PropertyMacro* KeyProperty, const PropertyMacro* ValueProperty)
|
||||
{
|
||||
return FScriptMap::GetScriptLayout(
|
||||
KeyProperty->GetSize(), KeyProperty->GetMinAlignment(), ValueProperty->GetSize(), ValueProperty->GetMinAlignment());
|
||||
}
|
||||
|
||||
FORCEINLINE static void Destruct(
|
||||
FScriptMap* ScriptMap, PropertyMacro* KeyProperty, PropertyMacro* ValueProperty, int32 Index, int32 Count = 1)
|
||||
{
|
||||
int32 MaxIndex = ScriptMap->GetMaxIndex();
|
||||
auto MapLayout = GetScriptLayout(KeyProperty, ValueProperty);
|
||||
for (int32 i = Index; i < Index + Count; ++i)
|
||||
{
|
||||
if (ScriptMap->IsValidIndex(i))
|
||||
{
|
||||
uint8* Data = reinterpret_cast<uint8*>(ScriptMap->GetData(i, MapLayout));
|
||||
void* Key = Data + GetKeyOffset(MapLayout);
|
||||
void* Value = Data + MapLayout.ValueOffset;
|
||||
KeyProperty->DestroyValue(Key);
|
||||
ValueProperty->DestroyValue(Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FORCEINLINE static void Empty(FScriptMap* ScriptMap, PropertyMacro* KeyProperty, PropertyMacro* ValueProperty)
|
||||
{
|
||||
auto MapLayout = GetScriptLayout(KeyProperty, ValueProperty);
|
||||
Destruct(ScriptMap, KeyProperty, ValueProperty, 0, ScriptMap->Num());
|
||||
ScriptMap->Empty(0, MapLayout);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct ContainerExTypeMapper;
|
||||
|
||||
template <>
|
||||
struct ContainerExTypeMapper<FScriptArray>
|
||||
{
|
||||
using Type = FScriptArrayEx;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct ContainerExTypeMapper<FScriptSet>
|
||||
{
|
||||
using Type = FScriptSetEx;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct ContainerExTypeMapper<FScriptMap>
|
||||
{
|
||||
using Type = FScriptMapEx;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class FContainerWrapper
|
||||
{
|
||||
public:
|
||||
static void OnGarbageCollectedWithFree(const v8::WeakCallbackInfo<void>& Data)
|
||||
{
|
||||
typedef typename ContainerExTypeMapper<T>::Type ET;
|
||||
ET* Container =
|
||||
static_cast<ET*>(DataTransfer::MakeAddressWithHighPartOfTwo(Data.GetInternalField(0), Data.GetInternalField(1)));
|
||||
FV8Utils::IsolateData<IObjectMapper>(Data.GetIsolate())->UnBindContainer(Container);
|
||||
delete Container;
|
||||
}
|
||||
|
||||
static void OnGarbageCollected(const v8::WeakCallbackInfo<void>& Data)
|
||||
{
|
||||
T* Container =
|
||||
static_cast<T*>(DataTransfer::MakeAddressWithHighPartOfTwo(Data.GetInternalField(0), Data.GetInternalField(1)));
|
||||
FV8Utils::IsolateData<IObjectMapper>(Data.GetIsolate())->UnBindContainer(Container);
|
||||
}
|
||||
|
||||
static void New(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
FV8Utils::ThrowException(Isolate, "Container Constructor no support yet");
|
||||
}
|
||||
|
||||
// TODO - 用doxygen注释
|
||||
// 参数:无
|
||||
// 返回:容器内元素总数
|
||||
static void Num(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::HandleScope HandleScope(Isolate);
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
|
||||
auto Self = FV8Utils::GetPointerFast<T>(Info.Holder());
|
||||
Info.GetReturnValue().Set(Self->Num());
|
||||
}
|
||||
};
|
||||
|
||||
class FScriptArrayWrapper : public FContainerWrapper<FScriptArray>
|
||||
{
|
||||
public:
|
||||
static v8::Local<v8::FunctionTemplate> ToFunctionTemplate(v8::Isolate* Isolate);
|
||||
|
||||
private:
|
||||
// 参数:一到多个容器元素
|
||||
// 返回:无
|
||||
// 作用:追加新元素到容器
|
||||
static void Add(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
|
||||
// 参数:索引
|
||||
// 返回:元素(值类型,有内存拷贝)
|
||||
// 作用:获取索引对应的元素,如果索引越界则抛出异常
|
||||
static void Get(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
|
||||
// 参数:索引
|
||||
// 返回:元素(引用类型)
|
||||
// 作用:获取索引对应的元素,如果索引越界则抛出异常
|
||||
static void GetRef(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
|
||||
// 参数1:索引;参数2:元素
|
||||
// 返回:无
|
||||
// 作用:设置容器中索引对应的元素值,如果索引越界则抛出异常
|
||||
static void Set(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
|
||||
// 参数:元素
|
||||
// 返回:bool
|
||||
// 作用:查询容器是否包含该元素,若是则返回true,否则返回false
|
||||
static void Contains(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
|
||||
// 参数:元素
|
||||
// 返回:索引
|
||||
// 作用:返回容器中第一次出现该元素的索引,若元素不存在则返回INDEX_NONE(-1)
|
||||
static void FindIndex(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
|
||||
// 参数:索引
|
||||
// 返回:无
|
||||
// 作用:移除索引对应的元素,被移除的位置之后的元素会自动前移,如果索引越界则抛出异常
|
||||
static void RemoveAt(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
|
||||
// 参数:索引
|
||||
// 返回:bool
|
||||
// 作用:如果参数是有效索引,返回true,否则返回false
|
||||
static void IsValidIndex(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
|
||||
// 参数:无
|
||||
// 返回:无
|
||||
// 作用:清空容器
|
||||
static void Empty(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
|
||||
FORCEINLINE static int32 AddUninitialized(FScriptArray* ScriptArray, int32 ElementSize, int32 Count = 1);
|
||||
|
||||
FORCEINLINE static uint8* GetData(FScriptArray* ScriptArray, int32 ElementSize, int32 Index);
|
||||
|
||||
FORCEINLINE static void Construct(FScriptArray* ScriptArray, FPropertyTranslator* Inner, int32 Index, int32 Count = 1);
|
||||
|
||||
static int32 FindIndexInner(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
|
||||
FORCEINLINE static void InternalGet(const v8::FunctionCallbackInfo<v8::Value>& Info, bool PassByPointer);
|
||||
};
|
||||
|
||||
class FScriptSetWrapper : public FContainerWrapper<FScriptSet>
|
||||
{
|
||||
public:
|
||||
static v8::Local<v8::FunctionTemplate> ToFunctionTemplate(v8::Isolate* Isolate);
|
||||
|
||||
private:
|
||||
static void Add(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
|
||||
static void Get(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
|
||||
static void GetRef(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
|
||||
static void Contains(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
|
||||
static void FindIndex(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
|
||||
static void RemoveAt(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
|
||||
static void GetMaxIndex(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
|
||||
static void IsValidIndex(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
|
||||
static void Empty(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
|
||||
FORCEINLINE static int32 FindIndexInner(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
|
||||
FORCEINLINE static void InternalGet(const v8::FunctionCallbackInfo<v8::Value>& Info, bool PassByPointer);
|
||||
};
|
||||
|
||||
class FScriptMapWrapper : public FContainerWrapper<FScriptMap>
|
||||
{
|
||||
public:
|
||||
static v8::Local<v8::FunctionTemplate> ToFunctionTemplate(v8::Isolate* Isolate);
|
||||
|
||||
private:
|
||||
static void Add(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
|
||||
static void Get(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
|
||||
static void GetRef(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
|
||||
static void Set(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
|
||||
static void Remove(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
|
||||
static void GetMaxIndex(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
|
||||
static void IsValidIndex(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
|
||||
static void GetKey(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
|
||||
static void Empty(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
|
||||
FORCEINLINE static FScriptMapLayout GetScriptLayout(const PropertyMacro* KeyProperty, const PropertyMacro* ValueProperty);
|
||||
|
||||
FORCEINLINE static void InternalGet(const v8::FunctionCallbackInfo<v8::Value>& Info, bool PassByPointer);
|
||||
};
|
||||
|
||||
class FFixSizeArrayWrapper
|
||||
{
|
||||
public:
|
||||
static v8::Local<v8::FunctionTemplate> ToFunctionTemplate(v8::Isolate* Isolate);
|
||||
|
||||
private:
|
||||
static void New(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
}
|
||||
|
||||
static void Num(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
|
||||
static void Get(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
|
||||
static void GetRef(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
|
||||
static void Set(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
|
||||
FORCEINLINE static void InternalGet(const v8::FunctionCallbackInfo<v8::Value>& Info, bool PassByPointer);
|
||||
};
|
||||
} // namespace PUERTS_NAMESPACE
|
||||
@@ -0,0 +1,424 @@
|
||||
/*
|
||||
* 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 "CppObjectMapper.h"
|
||||
#include "DataTransfer.h"
|
||||
|
||||
namespace PUERTS_NAMESPACE
|
||||
{
|
||||
template <typename T>
|
||||
inline void __USE(T&&)
|
||||
{
|
||||
}
|
||||
|
||||
static void ThrowException(v8::Isolate* Isolate, const char* Message)
|
||||
{
|
||||
auto ExceptionStr = v8::String::NewFromUtf8(Isolate, Message, v8::NewStringType::kNormal).ToLocalChecked();
|
||||
Isolate->ThrowException(v8::Exception::Error(ExceptionStr));
|
||||
}
|
||||
|
||||
void FCppObjectMapper::LoadCppType(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Isolate::Scope IsolateScope(Isolate);
|
||||
v8::HandleScope HandleScope(Isolate);
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
v8::Context::Scope ContextScope(Context);
|
||||
|
||||
if (!Info[0]->IsString())
|
||||
{
|
||||
ThrowException(Isolate, "#0 argument expect a string");
|
||||
return;
|
||||
}
|
||||
|
||||
std::string TypeName = *(v8::String::Utf8Value(Isolate, Info[0]));
|
||||
|
||||
auto ClassDef = FindCppTypeClassByName(TypeName);
|
||||
if (ClassDef)
|
||||
{
|
||||
Info.GetReturnValue().Set(GetTemplateOfClass(Isolate, ClassDef)->GetFunction(Context).ToLocalChecked());
|
||||
}
|
||||
else
|
||||
{
|
||||
const std::string ErrMsg = "can not find type: " + TypeName;
|
||||
ThrowException(Isolate, ErrMsg.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
v8::MaybeLocal<v8::Function> FCppObjectMapper::LoadTypeById(v8::Local<v8::Context> Context, const void* TypeId)
|
||||
{
|
||||
auto ClassDef = puerts::LoadClassByID(TypeId);
|
||||
if (!ClassDef)
|
||||
{
|
||||
return v8::MaybeLocal<v8::Function>();
|
||||
}
|
||||
auto Template = GetTemplateOfClass(Context->GetIsolate(), ClassDef);
|
||||
return Template->GetFunction(Context);
|
||||
}
|
||||
|
||||
static void PointerNew(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
void FCppObjectMapper::Initialize(v8::Isolate* InIsolate, v8::Local<v8::Context> InContext)
|
||||
{
|
||||
auto LocalTemplate = v8::FunctionTemplate::New(InIsolate, PointerNew);
|
||||
LocalTemplate->InstanceTemplate()->SetInternalFieldCount(4); // 0 Ptr, 1, CDataName
|
||||
PointerTemplate = v8::UniquePersistent<v8::FunctionTemplate>(InIsolate, LocalTemplate);
|
||||
#ifndef WITH_QUICKJS
|
||||
PrivateKey.Reset(InIsolate, v8::Symbol::New(InIsolate));
|
||||
#endif
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> FCppObjectMapper::FindOrAddCppObject(
|
||||
v8::Isolate* Isolate, v8::Local<v8::Context>& Context, const void* TypeId, void* Ptr, bool PassByPointer)
|
||||
{
|
||||
if (Ptr == nullptr)
|
||||
{
|
||||
return v8::Null(Isolate);
|
||||
}
|
||||
|
||||
if (PassByPointer)
|
||||
{
|
||||
auto Iter = CDataCache.find(Ptr);
|
||||
if (Iter != CDataCache.end())
|
||||
{
|
||||
auto CacheNodePtr = Iter->second.Find(TypeId);
|
||||
if (CacheNodePtr)
|
||||
{
|
||||
return CacheNodePtr->Value.Get(Isolate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// create and link
|
||||
auto ClassDefinition = LoadClassByID(TypeId);
|
||||
if (ClassDefinition)
|
||||
{
|
||||
auto Result = GetTemplateOfClass(Isolate, ClassDefinition)->InstanceTemplate()->NewInstance(Context).ToLocalChecked();
|
||||
BindCppObject(Isolate, const_cast<JSClassDefinition*>(ClassDefinition), Ptr, Result, PassByPointer);
|
||||
return Result;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto Result = PointerTemplate.Get(Isolate)->InstanceTemplate()->NewInstance(Context).ToLocalChecked();
|
||||
DataTransfer::SetPointer(Isolate, Result, Ptr, 0);
|
||||
DataTransfer::SetPointer(Isolate, Result, TypeId, 1);
|
||||
return Result;
|
||||
}
|
||||
}
|
||||
|
||||
bool FCppObjectMapper::IsInstanceOfCppObject(v8::Isolate* Isolate, const void* TypeId, v8::Local<v8::Object> JsObject)
|
||||
{
|
||||
if (DataTransfer::GetPointerFast<const void>(JsObject, 1) == TypeId)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
auto ClassDefinition = FindClassByID(TypeId);
|
||||
if (ClassDefinition)
|
||||
{
|
||||
auto Template = GetTemplateOfClass(Isolate, ClassDefinition);
|
||||
return Template->HasInstance(JsObject);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::weak_ptr<int> FCppObjectMapper::GetJsEnvLifeCycleTracker()
|
||||
{
|
||||
return std::weak_ptr<int>(Ref);
|
||||
}
|
||||
|
||||
static void CDataNew(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Isolate::Scope IsolateScope(Isolate);
|
||||
v8::HandleScope HandleScope(Isolate);
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
v8::Context::Scope ContextScope(Context);
|
||||
|
||||
if (Info.IsConstructCall())
|
||||
{
|
||||
auto Self = Info.This();
|
||||
JSClassDefinition* ClassDefinition = reinterpret_cast<JSClassDefinition*>(
|
||||
reinterpret_cast<char*>(v8::Local<v8::External>::Cast(Info.Data())->Value()) - offsetof(JSClassDefinition, Data));
|
||||
void* Ptr = nullptr;
|
||||
|
||||
if (ClassDefinition->Initialize)
|
||||
Ptr = ClassDefinition->Initialize((pesapi_callback_info) &Info);
|
||||
if (Ptr == nullptr)
|
||||
return;
|
||||
|
||||
DataTransfer::IsolateData<ICppObjectMapper>(Isolate)->BindCppObject(Isolate, ClassDefinition, Ptr, Self, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
ThrowException(Isolate, "only call as Construct is supported!");
|
||||
}
|
||||
}
|
||||
|
||||
MSVC_PRAGMA(warning(push))
|
||||
MSVC_PRAGMA(warning(disable : 4191))
|
||||
v8::Local<v8::FunctionTemplate> FCppObjectMapper::GetTemplateOfClass(v8::Isolate* Isolate, const JSClassDefinition* ClassDefinition)
|
||||
{
|
||||
auto Iter = TypeIdToTemplateMap.find(ClassDefinition->TypeId);
|
||||
if (Iter == TypeIdToTemplateMap.end())
|
||||
{
|
||||
auto Template = v8::FunctionTemplate::New(
|
||||
Isolate, CDataNew, v8::External::New(Isolate, &(const_cast<JSClassDefinition*>(ClassDefinition)->Data)));
|
||||
Template->InstanceTemplate()->SetInternalFieldCount(4);
|
||||
|
||||
JSPropertyInfo* PropertyInfo = ClassDefinition->Properties;
|
||||
while (PropertyInfo && PropertyInfo->Name && PropertyInfo->Getter)
|
||||
{
|
||||
v8::PropertyAttribute PropertyAttribute = v8::DontDelete;
|
||||
if (!PropertyInfo->Setter)
|
||||
PropertyAttribute = (v8::PropertyAttribute)(PropertyAttribute | v8::ReadOnly);
|
||||
auto GetterData = v8::External::New(Isolate, &PropertyInfo->GetterData);
|
||||
auto SetterData = v8::External::New(Isolate, &PropertyInfo->SetterData);
|
||||
Template->PrototypeTemplate()->SetAccessorProperty(
|
||||
v8::String::NewFromUtf8(Isolate, PropertyInfo->Name, v8::NewStringType::kNormal).ToLocalChecked(),
|
||||
PropertyInfo->Getter ? v8::FunctionTemplate::New(Isolate, (v8::FunctionCallback) PropertyInfo->Getter, GetterData)
|
||||
: v8::Local<v8::FunctionTemplate>(),
|
||||
PropertyInfo->Setter ? v8::FunctionTemplate::New(Isolate, (v8::FunctionCallback) PropertyInfo->Setter, SetterData)
|
||||
: v8::Local<v8::FunctionTemplate>(),
|
||||
PropertyAttribute);
|
||||
++PropertyInfo;
|
||||
}
|
||||
|
||||
PropertyInfo = ClassDefinition->Variables;
|
||||
while (PropertyInfo && PropertyInfo->Name && PropertyInfo->Getter)
|
||||
{
|
||||
v8::PropertyAttribute PropertyAttribute = v8::DontDelete;
|
||||
if (!PropertyInfo->Setter)
|
||||
PropertyAttribute = (v8::PropertyAttribute)(PropertyAttribute | v8::ReadOnly);
|
||||
auto GetterData = v8::External::New(Isolate, &PropertyInfo->GetterData);
|
||||
auto SetterData = v8::External::New(Isolate, &PropertyInfo->SetterData);
|
||||
Template->SetAccessorProperty(
|
||||
v8::String::NewFromUtf8(Isolate, PropertyInfo->Name, v8::NewStringType::kNormal).ToLocalChecked(),
|
||||
PropertyInfo->Getter ? v8::FunctionTemplate::New(Isolate, (v8::FunctionCallback) PropertyInfo->Getter, GetterData)
|
||||
: v8::Local<v8::FunctionTemplate>(),
|
||||
PropertyInfo->Setter ? v8::FunctionTemplate::New(Isolate, (v8::FunctionCallback) PropertyInfo->Setter, SetterData)
|
||||
: v8::Local<v8::FunctionTemplate>(),
|
||||
PropertyAttribute);
|
||||
++PropertyInfo;
|
||||
}
|
||||
|
||||
JSFunctionInfo* FunctionInfo = ClassDefinition->Methods;
|
||||
while (FunctionInfo && FunctionInfo->Name && FunctionInfo->Callback)
|
||||
{
|
||||
#ifndef WITH_QUICKJS
|
||||
auto FastCallInfo = FunctionInfo->ReflectionInfo ? FunctionInfo->ReflectionInfo->FastCallInfo() : nullptr;
|
||||
if (FastCallInfo)
|
||||
{
|
||||
Template->PrototypeTemplate()->Set(
|
||||
v8::String::NewFromUtf8(Isolate, FunctionInfo->Name, v8::NewStringType::kNormal).ToLocalChecked(),
|
||||
v8::FunctionTemplate::New(Isolate, (v8::FunctionCallback) FunctionInfo->Callback,
|
||||
v8::External::New(Isolate, &FunctionInfo->Data), v8::Local<v8::Signature>(), 0,
|
||||
v8::ConstructorBehavior::kThrow, v8::SideEffectType::kHasSideEffect, FastCallInfo));
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
Template->PrototypeTemplate()->Set(
|
||||
v8::String::NewFromUtf8(Isolate, FunctionInfo->Name, v8::NewStringType::kNormal).ToLocalChecked(),
|
||||
v8::FunctionTemplate::New(
|
||||
Isolate, (v8::FunctionCallback) FunctionInfo->Callback, v8::External::New(Isolate, &FunctionInfo->Data)
|
||||
#ifndef WITH_QUICKJS
|
||||
,
|
||||
v8::Local<v8::Signature>(), 0, v8::ConstructorBehavior::kThrow
|
||||
#endif
|
||||
));
|
||||
}
|
||||
++FunctionInfo;
|
||||
}
|
||||
FunctionInfo = ClassDefinition->Functions;
|
||||
while (FunctionInfo && FunctionInfo->Name && FunctionInfo->Callback)
|
||||
{
|
||||
#ifndef WITH_QUICKJS
|
||||
auto FastCallInfo = FunctionInfo->ReflectionInfo ? FunctionInfo->ReflectionInfo->FastCallInfo() : nullptr;
|
||||
if (FastCallInfo)
|
||||
{
|
||||
Template->Set(v8::String::NewFromUtf8(Isolate, FunctionInfo->Name, v8::NewStringType::kNormal).ToLocalChecked(),
|
||||
v8::FunctionTemplate::New(Isolate, (v8::FunctionCallback) FunctionInfo->Callback,
|
||||
v8::External::New(Isolate, &FunctionInfo->Data), v8::Local<v8::Signature>(), 0,
|
||||
v8::ConstructorBehavior::kThrow, v8::SideEffectType::kHasSideEffect, FastCallInfo));
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
Template->Set(v8::String::NewFromUtf8(Isolate, FunctionInfo->Name, v8::NewStringType::kNormal).ToLocalChecked(),
|
||||
v8::FunctionTemplate::New(
|
||||
Isolate, (v8::FunctionCallback) FunctionInfo->Callback, v8::External::New(Isolate, &FunctionInfo->Data)
|
||||
#ifndef WITH_QUICKJS
|
||||
,
|
||||
v8::Local<v8::Signature>(), 0, v8::ConstructorBehavior::kThrow
|
||||
#endif
|
||||
));
|
||||
}
|
||||
++FunctionInfo;
|
||||
}
|
||||
|
||||
if (ClassDefinition->SuperTypeId)
|
||||
{
|
||||
if (auto SuperDefinition = LoadClassByID(ClassDefinition->SuperTypeId))
|
||||
{
|
||||
Template->Inherit(GetTemplateOfClass(Isolate, SuperDefinition));
|
||||
}
|
||||
}
|
||||
|
||||
TypeIdToTemplateMap[ClassDefinition->TypeId] = v8::UniquePersistent<v8::FunctionTemplate>(Isolate, Template);
|
||||
|
||||
return Template;
|
||||
}
|
||||
else
|
||||
{
|
||||
return v8::Local<v8::FunctionTemplate>::New(Isolate, Iter->second);
|
||||
}
|
||||
}
|
||||
MSVC_PRAGMA(warning(pop))
|
||||
|
||||
static void CDataGarbageCollectedWithFree(const v8::WeakCallbackInfo<JSClassDefinition>& Data)
|
||||
{
|
||||
JSClassDefinition* ClassDefinition = Data.GetParameter();
|
||||
void* Ptr = DataTransfer::MakeAddressWithHighPartOfTwo(Data.GetInternalField(0), Data.GetInternalField(1));
|
||||
if (ClassDefinition->Finalize)
|
||||
ClassDefinition->Finalize(Ptr, ClassDefinition->Data, DataTransfer::GetIsolatePrivateData(Data.GetIsolate()));
|
||||
DataTransfer::IsolateData<ICppObjectMapper>(Data.GetIsolate())->UnBindCppObject(Data.GetIsolate(), ClassDefinition, Ptr);
|
||||
}
|
||||
|
||||
static void CDataGarbageCollectedWithoutFree(const v8::WeakCallbackInfo<JSClassDefinition>& Data)
|
||||
{
|
||||
JSClassDefinition* ClassDefinition = Data.GetParameter();
|
||||
void* Ptr = DataTransfer::MakeAddressWithHighPartOfTwo(Data.GetInternalField(0), Data.GetInternalField(1));
|
||||
DataTransfer::IsolateData<ICppObjectMapper>(Data.GetIsolate())->UnBindCppObject(Data.GetIsolate(), ClassDefinition, Ptr);
|
||||
}
|
||||
|
||||
void FCppObjectMapper::BindCppObject(
|
||||
v8::Isolate* Isolate, JSClassDefinition* ClassDefinition, void* Ptr, v8::Local<v8::Object> JSObject, bool PassByPointer)
|
||||
{
|
||||
DataTransfer::SetPointer(Isolate, JSObject, Ptr, 0);
|
||||
DataTransfer::SetPointer(Isolate, JSObject, ClassDefinition->TypeId, 1);
|
||||
|
||||
auto Iter = CDataCache.find(Ptr);
|
||||
FObjectCacheNode* CacheNodePtr;
|
||||
if (Iter != CDataCache.end())
|
||||
{
|
||||
CacheNodePtr = Iter->second.Add(ClassDefinition->TypeId);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto Ret = CDataCache.insert({Ptr, FObjectCacheNode(ClassDefinition->TypeId)});
|
||||
CacheNodePtr = &Ret.first->second;
|
||||
}
|
||||
CacheNodePtr->Value.Reset(Isolate, JSObject);
|
||||
|
||||
if (!PassByPointer)
|
||||
{
|
||||
CacheNodePtr->MustCallFinalize = true;
|
||||
CacheNodePtr->Value.SetWeak<JSClassDefinition>(
|
||||
ClassDefinition, CDataGarbageCollectedWithFree, v8::WeakCallbackType::kInternalFields);
|
||||
}
|
||||
else
|
||||
{
|
||||
CacheNodePtr->Value.SetWeak<JSClassDefinition>(
|
||||
ClassDefinition, CDataGarbageCollectedWithoutFree, v8::WeakCallbackType::kInternalFields);
|
||||
}
|
||||
|
||||
if (ClassDefinition->OnEnter)
|
||||
{
|
||||
CacheNodePtr->UserData = ClassDefinition->OnEnter(Ptr, ClassDefinition->Data, DataTransfer::GetIsolatePrivateData(Isolate));
|
||||
}
|
||||
}
|
||||
|
||||
#define QJS_PRIVATE_KEY_STR "__,kp@"
|
||||
|
||||
void* FCppObjectMapper::GetPrivateData(v8::Local<v8::Context> Context, v8::Local<v8::Object> JSObject)
|
||||
{
|
||||
#ifndef WITH_QUICKJS
|
||||
auto Key = PrivateKey.Get(Context->GetIsolate());
|
||||
#else
|
||||
auto Key = FV8Utils::InternalString(Context->GetIsolate(), QJS_PRIVATE_KEY_STR);
|
||||
#endif
|
||||
v8::MaybeLocal<v8::Value> maybeValue = JSObject->Get(Context, Key);
|
||||
if (maybeValue.IsEmpty())
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> maybeExternal = maybeValue.ToLocalChecked();
|
||||
if (!maybeExternal->IsExternal())
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return v8::Local<v8::External>::Cast(maybeExternal)->Value();
|
||||
}
|
||||
|
||||
void FCppObjectMapper::SetPrivateData(v8::Local<v8::Context> Context, v8::Local<v8::Object> JSObject, void* Ptr)
|
||||
{
|
||||
#ifndef WITH_QUICKJS
|
||||
auto Key = PrivateKey.Get(Context->GetIsolate());
|
||||
#else
|
||||
auto Key = FV8Utils::InternalString(Context->GetIsolate(), QJS_PRIVATE_KEY_STR);
|
||||
#endif
|
||||
(void) (JSObject->Set(Context, Key, v8::External::New(Context->GetIsolate(), Ptr)));
|
||||
}
|
||||
|
||||
void FCppObjectMapper::UnBindCppObject(v8::Isolate* Isolate, JSClassDefinition* ClassDefinition, void* Ptr)
|
||||
{
|
||||
auto Iter = CDataCache.find(Ptr);
|
||||
if (Iter != CDataCache.end())
|
||||
{
|
||||
if (ClassDefinition->OnExit)
|
||||
{
|
||||
ClassDefinition->OnExit(
|
||||
Ptr, ClassDefinition->Data, DataTransfer::GetIsolatePrivateData(Isolate), Iter->second.UserData);
|
||||
}
|
||||
auto Removed = Iter->second.Remove(ClassDefinition->TypeId, true);
|
||||
if (!Iter->second.TypeId) // last one
|
||||
{
|
||||
CDataCache.erase(Ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FCppObjectMapper::UnInitialize(v8::Isolate* InIsolate)
|
||||
{
|
||||
auto PData = DataTransfer::GetIsolatePrivateData(InIsolate);
|
||||
for (auto& KV : CDataCache)
|
||||
{
|
||||
FObjectCacheNode* PNode = &KV.second;
|
||||
while (PNode)
|
||||
{
|
||||
const JSClassDefinition* ClassDefinition = FindClassByID(PNode->TypeId);
|
||||
if (PNode->MustCallFinalize)
|
||||
{
|
||||
if (ClassDefinition && ClassDefinition->Finalize)
|
||||
{
|
||||
ClassDefinition->Finalize(KV.first, ClassDefinition->Data, PData);
|
||||
}
|
||||
PNode->MustCallFinalize = false;
|
||||
}
|
||||
if (ClassDefinition->OnExit)
|
||||
{
|
||||
ClassDefinition->OnExit(
|
||||
KV.first, ClassDefinition->Data, DataTransfer::GetIsolatePrivateData(InIsolate), PNode->UserData);
|
||||
}
|
||||
PNode = PNode->Next;
|
||||
}
|
||||
}
|
||||
CDataCache.clear();
|
||||
TypeIdToTemplateMap.clear();
|
||||
#ifndef WITH_QUICKJS
|
||||
PrivateKey.Reset();
|
||||
#endif
|
||||
PointerTemplate.Reset();
|
||||
}
|
||||
|
||||
} // namespace PUERTS_NAMESPACE
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "NamespaceDef.h"
|
||||
|
||||
PRAGMA_DISABLE_UNDEFINED_IDENTIFIER_WARNINGS
|
||||
#pragma warning(push, 0)
|
||||
#include "v8.h"
|
||||
#pragma warning(pop)
|
||||
PRAGMA_ENABLE_UNDEFINED_IDENTIFIER_WARNINGS
|
||||
|
||||
#include <unordered_map>
|
||||
#include "JSClassRegister.h"
|
||||
#include "ObjectCacheNode.h"
|
||||
#include "ObjectMapper.h"
|
||||
|
||||
namespace PUERTS_NAMESPACE
|
||||
{
|
||||
struct PointerHash
|
||||
{
|
||||
std::size_t operator()(const void* ptr) const
|
||||
{
|
||||
return reinterpret_cast<std::size_t>(ptr);
|
||||
}
|
||||
};
|
||||
|
||||
struct PointerEqual
|
||||
{
|
||||
bool operator()(const void* lhs, const void* rhs) const
|
||||
{
|
||||
return lhs == rhs;
|
||||
}
|
||||
};
|
||||
class FCppObjectMapper final : public ICppObjectMapper
|
||||
{
|
||||
public:
|
||||
void Initialize(v8::Isolate* InIsolate, v8::Local<v8::Context> InContext);
|
||||
|
||||
void LoadCppType(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
|
||||
virtual bool IsInstanceOfCppObject(v8::Isolate* Isolate, const void* TypeId, v8::Local<v8::Object> JsObject) override;
|
||||
|
||||
virtual std::weak_ptr<int> GetJsEnvLifeCycleTracker() override;
|
||||
|
||||
virtual v8::Local<v8::Value> FindOrAddCppObject(
|
||||
v8::Isolate* Isolate, v8::Local<v8::Context>& Context, const void* TypeId, void* Ptr, bool PassByPointer) override;
|
||||
|
||||
virtual void UnBindCppObject(v8::Isolate* Isolate, JSClassDefinition* ClassDefinition, void* Ptr) override;
|
||||
|
||||
virtual void BindCppObject(v8::Isolate* Isolate, JSClassDefinition* ClassDefinition, void* Ptr, v8::Local<v8::Object> JSObject,
|
||||
bool PassByPointer) override;
|
||||
|
||||
virtual void* GetPrivateData(v8::Local<v8::Context> Context, v8::Local<v8::Object> JSObject) override;
|
||||
|
||||
virtual void SetPrivateData(v8::Local<v8::Context> Context, v8::Local<v8::Object> JSObject, void* Ptr) override;
|
||||
|
||||
virtual v8::MaybeLocal<v8::Function> LoadTypeById(v8::Local<v8::Context> Context, const void* TypeId) override;
|
||||
|
||||
void UnInitialize(v8::Isolate* InIsolate);
|
||||
|
||||
v8::Local<v8::FunctionTemplate> GetTemplateOfClass(v8::Isolate* Isolate, const JSClassDefinition* ClassDefinition);
|
||||
|
||||
private:
|
||||
std::unordered_map<void*, FObjectCacheNode, PointerHash, PointerEqual> CDataCache;
|
||||
|
||||
std::unordered_map<const void*, v8::UniquePersistent<v8::FunctionTemplate>, PointerHash, PointerEqual> TypeIdToTemplateMap;
|
||||
|
||||
v8::UniquePersistent<v8::FunctionTemplate> PointerTemplate;
|
||||
|
||||
#ifndef WITH_QUICKJS
|
||||
v8::Global<v8::Symbol> PrivateKey;
|
||||
#endif
|
||||
|
||||
std::shared_ptr<int> Ref = std::make_shared<int>(0);
|
||||
};
|
||||
|
||||
} // namespace PUERTS_NAMESPACE
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* 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 "DataTransfer.h"
|
||||
#include "ObjectMapper.h"
|
||||
#if USING_IN_UNREAL_ENGINE
|
||||
#include "V8Utils.h"
|
||||
#endif
|
||||
|
||||
namespace PUERTS_NAMESPACE
|
||||
{
|
||||
v8::Local<v8::Value> DataTransfer::FindOrAddCData(
|
||||
v8::Isolate* Isolate, v8::Local<v8::Context> Context, const void* TypeId, const void* Ptr, bool PassByPointer)
|
||||
{
|
||||
return IsolateData<ICppObjectMapper>(Isolate)->FindOrAddCppObject(
|
||||
Isolate, Context, TypeId, const_cast<void*>(Ptr), PassByPointer);
|
||||
}
|
||||
|
||||
bool DataTransfer::IsInstanceOf(v8::Isolate* Isolate, const void* TypeId, v8::Local<v8::Object> JsObject)
|
||||
{
|
||||
return IsolateData<ICppObjectMapper>(Isolate)->IsInstanceOfCppObject(Isolate, TypeId, JsObject);
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> DataTransfer::UnRef(v8::Isolate* Isolate, const v8::Local<v8::Value>& Value)
|
||||
{
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
v8::Local<v8::Value> ReturnValue = Value->ToObject(Context).ToLocalChecked()->Get(Context, 0).ToLocalChecked();
|
||||
|
||||
return ReturnValue;
|
||||
}
|
||||
|
||||
void DataTransfer::UpdateRef(v8::Isolate* Isolate, v8::Local<v8::Value> Outer, const v8::Local<v8::Value>& Value)
|
||||
{
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
|
||||
auto Ret = Outer->ToObject(Context).ToLocalChecked()->Set(Context, 0, Value);
|
||||
}
|
||||
|
||||
std::weak_ptr<int> DataTransfer::GetJsEnvLifeCycleTracker(v8::Isolate* Isolate)
|
||||
{
|
||||
return IsolateData<ICppObjectMapper>(Isolate)->GetJsEnvLifeCycleTracker();
|
||||
}
|
||||
|
||||
#if USING_IN_UNREAL_ENGINE
|
||||
FString DataTransfer::ToFString(v8::Isolate* Isolate, v8::Local<v8::Value> Value)
|
||||
{
|
||||
return FV8Utils::ToFString(Isolate, Value);
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> DataTransfer::FindOrAddObject(
|
||||
v8::Isolate* Isolate, v8::Local<v8::Context>& Context, UClass* Class, UObject* UEObject)
|
||||
{
|
||||
return FV8Utils::IsolateData<IObjectMapper>(Isolate)->FindOrAdd(Isolate, Context, Class, UEObject);
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> DataTransfer::FindOrAddStruct(
|
||||
v8::Isolate* Isolate, v8::Local<v8::Context> Context, UScriptStruct* ScriptStruct, void* Ptr, bool PassByPointer)
|
||||
{
|
||||
return FV8Utils::IsolateData<IObjectMapper>(Isolate)->FindOrAddStruct(Isolate, Context, ScriptStruct, Ptr, PassByPointer);
|
||||
}
|
||||
|
||||
bool DataTransfer::IsInstanceOf(v8::Isolate* Isolate, UStruct* Struct, v8::Local<v8::Object> JsObject)
|
||||
{
|
||||
return FV8Utils::IsolateData<IObjectMapper>(Isolate)->IsInstanceOf(Struct, JsObject);
|
||||
}
|
||||
|
||||
void DataTransfer::ThrowException(v8::Isolate* Isolate, const char* Message)
|
||||
{
|
||||
FV8Utils::ThrowException(Isolate, Message);
|
||||
}
|
||||
#endif
|
||||
} // namespace PUERTS_NAMESPACE
|
||||
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
* 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 "JSModuleLoader.h"
|
||||
#include "Misc/Paths.h"
|
||||
#include "Misc/FileHelper.h"
|
||||
#include "Algo/Reverse.h"
|
||||
#if (ENGINE_MAJOR_VERSION >= 5)
|
||||
#include "HAL/PlatformFileManager.h"
|
||||
#else
|
||||
#include "HAL/PlatformFilemanager.h"
|
||||
#endif
|
||||
|
||||
namespace PUERTS_NAMESPACE
|
||||
{
|
||||
static FString PathNormalize(const FString& PathIn)
|
||||
{
|
||||
TArray<FString> PathFrags;
|
||||
PathIn.ParseIntoArray(PathFrags, TEXT("/"));
|
||||
Algo::Reverse(PathFrags);
|
||||
TArray<FString> NewPathFrags;
|
||||
bool FromRoot = PathIn.StartsWith(TEXT("/"));
|
||||
while (PathFrags.Num() > 0)
|
||||
{
|
||||
FString E = PathFrags.Pop();
|
||||
if (E != TEXT("") && E != TEXT("."))
|
||||
{
|
||||
if (E == TEXT("..") && NewPathFrags.Num() > 0 && NewPathFrags.Last() != TEXT(".."))
|
||||
{
|
||||
NewPathFrags.Pop();
|
||||
}
|
||||
else
|
||||
{
|
||||
NewPathFrags.Push(E);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (FromRoot)
|
||||
{
|
||||
return TEXT("/") + FString::Join(NewPathFrags, TEXT("/"));
|
||||
}
|
||||
else
|
||||
{
|
||||
return FString::Join(NewPathFrags, TEXT("/"));
|
||||
}
|
||||
}
|
||||
|
||||
bool DefaultJSModuleLoader::CheckExists(const FString& PathIn, FString& Path, FString& AbsolutePath)
|
||||
{
|
||||
IPlatformFile& PlatformFile = FPlatformFileManager::Get().GetPlatformFile();
|
||||
FString NormalizedPath = PathNormalize(PathIn);
|
||||
if (PlatformFile.FileExists(*NormalizedPath))
|
||||
{
|
||||
AbsolutePath = IFileManager::Get().ConvertToAbsolutePathForExternalAppForRead(*NormalizedPath);
|
||||
Path = NormalizedPath;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DefaultJSModuleLoader::SearchModuleInDir(
|
||||
const FString& Dir, const FString& RequiredModule, FString& Path, FString& AbsolutePath)
|
||||
{
|
||||
FString Extension = FPaths::GetExtension(RequiredModule);
|
||||
bool IsJs = Extension == TEXT("js") || Extension == TEXT("mjs") || Extension == TEXT("cjs") || Extension == TEXT("json");
|
||||
if (IsJs && SearchModuleWithExtInDir(Dir, RequiredModule, Path, AbsolutePath))
|
||||
return true;
|
||||
return SearchModuleWithExtInDir(Dir, RequiredModule + ".js", Path, AbsolutePath) ||
|
||||
SearchModuleWithExtInDir(Dir, RequiredModule + ".mjs", Path, AbsolutePath) ||
|
||||
SearchModuleWithExtInDir(Dir, RequiredModule + ".cjs", Path, AbsolutePath) ||
|
||||
#if defined(WITH_V8_BYTECODE)
|
||||
SearchModuleWithExtInDir(Dir, RequiredModule + ".mbc", Path, AbsolutePath) ||
|
||||
SearchModuleWithExtInDir(Dir, RequiredModule + ".cbc", Path, AbsolutePath) ||
|
||||
#endif
|
||||
SearchModuleWithExtInDir(Dir, RequiredModule / "package.json", Path, AbsolutePath) ||
|
||||
SearchModuleWithExtInDir(Dir, RequiredModule / "index.js", Path, AbsolutePath);
|
||||
}
|
||||
|
||||
bool DefaultJSModuleLoader::SearchModuleWithExtInDir(
|
||||
const FString& Dir, const FString& RequiredModule, FString& Path, FString& AbsolutePath)
|
||||
{
|
||||
return CheckExists(Dir / RequiredModule, Path, AbsolutePath) ||
|
||||
(!Dir.EndsWith(TEXT("node_modules")) && CheckExists(Dir / TEXT("node_modules") / RequiredModule, Path, AbsolutePath));
|
||||
}
|
||||
|
||||
bool DefaultJSModuleLoader::Search(const FString& RequiredDir, const FString& RequiredModule, FString& Path, FString& AbsolutePath)
|
||||
{
|
||||
if (SearchModuleInDir(RequiredDir, RequiredModule, Path, AbsolutePath))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (RequiredDir != TEXT("") && !RequiredModule.GetCharArray().Contains('/') && !RequiredModule.EndsWith(TEXT(".js")) &&
|
||||
!RequiredModule.EndsWith(TEXT(".mjs")))
|
||||
{
|
||||
// 调用require的文件所在的目录往上找
|
||||
TArray<FString> pathFrags;
|
||||
RequiredDir.ParseIntoArray(pathFrags, TEXT("/"));
|
||||
pathFrags.Pop(); // has try in "if (SearchModuleInDir(RequiredDir, RequiredModule, Path, AbsolutePath))"
|
||||
while (pathFrags.Num() > 0)
|
||||
{
|
||||
if (!pathFrags.Last().Equals(TEXT("node_modules")))
|
||||
{
|
||||
if (SearchModuleInDir(FString::Join(pathFrags, TEXT("/")), RequiredModule, Path, AbsolutePath))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
pathFrags.Pop();
|
||||
}
|
||||
}
|
||||
|
||||
return SearchModuleInDir(FPaths::ProjectContentDir() / ScriptRoot, RequiredModule, Path, AbsolutePath) ||
|
||||
(ScriptRoot != TEXT("JavaScript") &&
|
||||
SearchModuleInDir(FPaths::ProjectContentDir() / TEXT("JavaScript"), RequiredModule, Path, AbsolutePath));
|
||||
}
|
||||
|
||||
bool DefaultJSModuleLoader::Load(const FString& Path, TArray<uint8>& Content)
|
||||
{
|
||||
// return (FPaths::FileExists(FullPath) && FFileHelper::LoadFileToString(Content, *FullPath));
|
||||
IPlatformFile& PlatformFile = FPlatformFileManager::Get().GetPlatformFile();
|
||||
IFileHandle* FileHandle = PlatformFile.OpenRead(*Path);
|
||||
if (FileHandle)
|
||||
{
|
||||
int len = FileHandle->Size();
|
||||
Content.Reset(len + 2);
|
||||
Content.AddUninitialized(len);
|
||||
const bool Success = FileHandle->Read(Content.GetData(), len);
|
||||
delete FileHandle;
|
||||
|
||||
return Success;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
FString& DefaultJSModuleLoader::GetScriptRoot()
|
||||
{
|
||||
return ScriptRoot;
|
||||
}
|
||||
|
||||
} // namespace PUERTS_NAMESPACE
|
||||
@@ -0,0 +1,211 @@
|
||||
/*
|
||||
* 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 "DelegateWrapper.h"
|
||||
#include "ObjectMapper.h"
|
||||
#include "V8Utils.h"
|
||||
|
||||
namespace PUERTS_NAMESPACE
|
||||
{
|
||||
v8::Local<v8::FunctionTemplate> FDelegateWrapper::ToFunctionTemplate(v8::Isolate* Isolate)
|
||||
{
|
||||
auto Result = v8::FunctionTemplate::New(Isolate, New);
|
||||
Result->InstanceTemplate()->SetInternalFieldCount(2);
|
||||
|
||||
Result->PrototypeTemplate()->Set(FV8Utils::InternalString(Isolate, "Bind"), v8::FunctionTemplate::New(Isolate, Bind));
|
||||
Result->PrototypeTemplate()->Set(FV8Utils::InternalString(Isolate, "IsBound"), v8::FunctionTemplate::New(Isolate, IsBound));
|
||||
Result->PrototypeTemplate()->Set(FV8Utils::InternalString(Isolate, "Unbind"), v8::FunctionTemplate::New(Isolate, Unbind));
|
||||
Result->PrototypeTemplate()->Set(FV8Utils::InternalString(Isolate, "Execute"), v8::FunctionTemplate::New(Isolate, Execute));
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
void FDelegateWrapper::New(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
}
|
||||
|
||||
void FDelegateWrapper::IsBound(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Isolate::Scope IsolateScope(Isolate);
|
||||
v8::HandleScope HandleScope(Isolate);
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
v8::Context::Scope ContextScope(Context);
|
||||
|
||||
auto DelegatePtr = FV8Utils::GetPointerFast<FScriptDelegate>(Info.Holder(), 0);
|
||||
|
||||
Info.GetReturnValue().Set(DelegatePtr->IsBound());
|
||||
}
|
||||
|
||||
void FDelegateWrapper::Bind(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Isolate::Scope IsolateScope(Isolate);
|
||||
v8::HandleScope HandleScope(Isolate);
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
v8::Context::Scope ContextScope(Context);
|
||||
|
||||
if (Info.Length() == 1 && Info[0]->IsFunction())
|
||||
{
|
||||
auto DelegatePtr = FV8Utils::GetPointerFast<void>(Info.Holder(), 0);
|
||||
FV8Utils::IsolateData<IObjectMapper>(Isolate)->AddToDelegate(
|
||||
Isolate, Context, DelegatePtr, v8::Local<v8::Function>::Cast(Info[0]));
|
||||
return;
|
||||
}
|
||||
if (Info.Length() == 2 && Info[0]->IsObject() && Info[1]->IsString())
|
||||
{
|
||||
if (auto Object = FV8Utils::GetUObject(Info[0].As<v8::Object>()))
|
||||
{
|
||||
if (FV8Utils::IsReleasedPtr(Object))
|
||||
{
|
||||
FV8Utils::ThrowException(Isolate, "passing a invalid object");
|
||||
return;
|
||||
}
|
||||
auto DelegatePtr = FV8Utils::GetPointerFast<FScriptDelegate>(Info.Holder(), 0);
|
||||
FScriptDelegate Delegate;
|
||||
Delegate.BindUFunction(Object, FName(*FV8Utils::ToFString(Isolate, Info[1])));
|
||||
*DelegatePtr = Delegate;
|
||||
return;
|
||||
}
|
||||
}
|
||||
FV8Utils::ThrowException(Isolate, "invalid arguments");
|
||||
}
|
||||
|
||||
void FDelegateWrapper::Unbind(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Isolate::Scope IsolateScope(Isolate);
|
||||
v8::HandleScope HandleScope(Isolate);
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
v8::Context::Scope ContextScope(Context);
|
||||
|
||||
auto DelegatePtr = FV8Utils::GetPointerFast<void>(Info.Holder(), 0);
|
||||
FV8Utils::IsolateData<IObjectMapper>(Isolate)->ClearDelegate(Isolate, Context, DelegatePtr);
|
||||
}
|
||||
|
||||
void FDelegateWrapper::Execute(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Isolate::Scope IsolateScope(Isolate);
|
||||
v8::HandleScope HandleScope(Isolate);
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
v8::Context::Scope ContextScope(Context);
|
||||
|
||||
auto DelegatePtr = FV8Utils::GetPointerFast<void>(Info.Holder(), 0);
|
||||
FV8Utils::IsolateData<IObjectMapper>(Isolate)->ExecuteDelegate(Isolate, Context, Info, DelegatePtr);
|
||||
}
|
||||
|
||||
v8::Local<v8::FunctionTemplate> FMulticastDelegateWrapper::ToFunctionTemplate(v8::Isolate* Isolate)
|
||||
{
|
||||
auto Result = v8::FunctionTemplate::New(Isolate, New);
|
||||
Result->InstanceTemplate()->SetInternalFieldCount(2);
|
||||
|
||||
Result->PrototypeTemplate()->Set(FV8Utils::InternalString(Isolate, "Add"), v8::FunctionTemplate::New(Isolate, Add));
|
||||
Result->PrototypeTemplate()->Set(FV8Utils::InternalString(Isolate, "Remove"), v8::FunctionTemplate::New(Isolate, Remove));
|
||||
Result->PrototypeTemplate()->Set(FV8Utils::InternalString(Isolate, "Clear"), v8::FunctionTemplate::New(Isolate, Clear));
|
||||
Result->PrototypeTemplate()->Set(FV8Utils::InternalString(Isolate, "Broadcast"), v8::FunctionTemplate::New(Isolate, Broadcast));
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
void FMulticastDelegateWrapper::New(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
}
|
||||
|
||||
void FMulticastDelegateWrapper::Add(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Isolate::Scope IsolateScope(Isolate);
|
||||
v8::HandleScope HandleScope(Isolate);
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
v8::Context::Scope ContextScope(Context);
|
||||
|
||||
if (Info.Length() == 1 && Info[0]->IsFunction())
|
||||
{
|
||||
auto DelegatePtr = FV8Utils::GetPointerFast<void>(Info.Holder(), 0);
|
||||
FV8Utils::IsolateData<IObjectMapper>(Isolate)->AddToDelegate(
|
||||
Isolate, Context, DelegatePtr, v8::Local<v8::Function>::Cast(Info[0]));
|
||||
return;
|
||||
}
|
||||
if (Info.Length() == 2 && Info[0]->IsObject() && Info[1]->IsString())
|
||||
{
|
||||
if (auto Object = FV8Utils::GetUObject(Info[0].As<v8::Object>()))
|
||||
{
|
||||
if (FV8Utils::IsReleasedPtr(Object))
|
||||
{
|
||||
FV8Utils::ThrowException(Isolate, "passing a invalid object");
|
||||
return;
|
||||
}
|
||||
auto DelegatePtr = FV8Utils::GetPointerFast<void>(Info.Holder(), 0);
|
||||
if (auto Property = CastFieldMacro<MulticastDelegatePropertyMacro>(
|
||||
FV8Utils::IsolateData<IObjectMapper>(Isolate)->FindDelegateProperty(DelegatePtr)))
|
||||
{
|
||||
FScriptDelegate Delegate;
|
||||
Delegate.BindUFunction(Object, FName(*FV8Utils::ToFString(Isolate, Info[1])));
|
||||
|
||||
#if ENGINE_MINOR_VERSION >= 23 || ENGINE_MAJOR_VERSION > 4
|
||||
if (Property->IsA<MulticastSparseDelegatePropertyMacro>())
|
||||
{
|
||||
Property->AddDelegate(MoveTemp(Delegate), nullptr, DelegatePtr);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
static_cast<FMulticastScriptDelegate*>(DelegatePtr)->AddUnique(Delegate);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
FV8Utils::ThrowException(Isolate, "invalid arguments");
|
||||
}
|
||||
|
||||
void FMulticastDelegateWrapper::Remove(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Isolate::Scope IsolateScope(Isolate);
|
||||
v8::HandleScope HandleScope(Isolate);
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
v8::Context::Scope ContextScope(Context);
|
||||
|
||||
if (Info.Length() == 1 && Info[0]->IsFunction())
|
||||
{
|
||||
auto DelegatePtr = FV8Utils::GetPointerFast<void>(Info.Holder(), 0);
|
||||
FV8Utils::IsolateData<IObjectMapper>(Isolate)->RemoveFromDelegate(
|
||||
Isolate, Context, DelegatePtr, v8::Local<v8::Function>::Cast(Info[0]));
|
||||
}
|
||||
else
|
||||
{
|
||||
FV8Utils::ThrowException(Isolate, "invalid arguments");
|
||||
}
|
||||
}
|
||||
|
||||
void FMulticastDelegateWrapper::Clear(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Isolate::Scope IsolateScope(Isolate);
|
||||
v8::HandleScope HandleScope(Isolate);
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
v8::Context::Scope ContextScope(Context);
|
||||
|
||||
auto DelegatePtr = FV8Utils::GetPointerFast<void>(Info.Holder(), 0);
|
||||
FV8Utils::IsolateData<IObjectMapper>(Isolate)->ClearDelegate(Isolate, Context, DelegatePtr);
|
||||
}
|
||||
|
||||
void FMulticastDelegateWrapper::Broadcast(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Isolate::Scope IsolateScope(Isolate);
|
||||
v8::HandleScope HandleScope(Isolate);
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
v8::Context::Scope ContextScope(Context);
|
||||
|
||||
auto DelegatePtr = FV8Utils::GetPointerFast<void>(Info.Holder(), 0);
|
||||
FV8Utils::IsolateData<IObjectMapper>(Isolate)->ExecuteDelegate(Isolate, Context, Info, DelegatePtr);
|
||||
}
|
||||
} // namespace PUERTS_NAMESPACE
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "CoreUObject.h"
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include "PropertyTranslator.h"
|
||||
#include "FunctionTranslator.h"
|
||||
|
||||
#include "NamespaceDef.h"
|
||||
|
||||
PRAGMA_DISABLE_UNDEFINED_IDENTIFIER_WARNINGS
|
||||
#pragma warning(push, 0)
|
||||
#include "libplatform/libplatform.h"
|
||||
#include "v8.h"
|
||||
#pragma warning(pop)
|
||||
PRAGMA_ENABLE_UNDEFINED_IDENTIFIER_WARNINGS
|
||||
|
||||
namespace PUERTS_NAMESPACE
|
||||
{
|
||||
class FDelegateWrapper
|
||||
{
|
||||
public:
|
||||
static v8::Local<v8::FunctionTemplate> ToFunctionTemplate(v8::Isolate* Isolate);
|
||||
|
||||
private:
|
||||
static void New(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
|
||||
static void Bind(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
|
||||
static void IsBound(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
|
||||
static void Unbind(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
|
||||
static void Execute(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
};
|
||||
|
||||
class FMulticastDelegateWrapper
|
||||
{
|
||||
public:
|
||||
static v8::Local<v8::FunctionTemplate> ToFunctionTemplate(v8::Isolate* Isolate);
|
||||
|
||||
private:
|
||||
static void New(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
|
||||
static void Add(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
|
||||
static void Remove(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
|
||||
static void Clear(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
|
||||
static void Broadcast(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
};
|
||||
} // namespace PUERTS_NAMESPACE
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* 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 "DynamicDelegateProxy.h"
|
||||
|
||||
void UDynamicDelegateProxy::Fire()
|
||||
{
|
||||
// Do Nothing
|
||||
}
|
||||
|
||||
void UDynamicDelegateProxy::ProcessEvent(UFunction*, void* Params)
|
||||
{
|
||||
#ifdef THREAD_SAFE
|
||||
v8::Locker Locker(Isolate);
|
||||
#endif
|
||||
auto PinedDynamicInvoker = DynamicInvoker.Pin();
|
||||
if (PinedDynamicInvoker && Owner.IsValid())
|
||||
{
|
||||
if (ensureAlwaysMsgf(!JsFunction.IsEmpty(), TEXT("Invalid JS Function")))
|
||||
{
|
||||
PinedDynamicInvoker->InvokeDelegateCallback(this, Params);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "NamespaceDef.h"
|
||||
|
||||
PRAGMA_DISABLE_UNDEFINED_IDENTIFIER_WARNINGS
|
||||
#pragma warning(push, 0)
|
||||
#include "libplatform/libplatform.h"
|
||||
#include "v8.h"
|
||||
#pragma warning(pop)
|
||||
PRAGMA_ENABLE_UNDEFINED_IDENTIFIER_WARNINGS
|
||||
|
||||
#include "DynamicInvoker.h"
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "UObject/NoExportTypes.h"
|
||||
#include "DynamicDelegateProxy.generated.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS()
|
||||
class UDynamicDelegateProxy : public UObject
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
UFUNCTION(BlueprintCallable, Category = "TGameJS")
|
||||
void Fire();
|
||||
|
||||
void ProcessEvent(UFunction*, void* Parms) override;
|
||||
|
||||
TWeakPtr<PUERTS_NAMESPACE::IDynamicInvoker, ESPMode::ThreadSafe> DynamicInvoker;
|
||||
|
||||
TWeakObjectPtr<UFunction> SignatureFunction;
|
||||
|
||||
// So, only uobject's delelgate is supported!
|
||||
TWeakObjectPtr<UObject> Owner;
|
||||
|
||||
v8::UniquePersistent<v8::Function> JsFunction;
|
||||
|
||||
#ifdef THREAD_SAFE
|
||||
v8::Isolate* Isolate;
|
||||
#endif
|
||||
};
|
||||
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* 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 "CoreMinimal.h"
|
||||
#include "Binding.hpp"
|
||||
#include "UEDataBinding.hpp"
|
||||
#include "V8Utils.h"
|
||||
#if !defined(ENGINE_INDEPENDENT_JSENV)
|
||||
#include "Kismet/DataTableFunctionLibrary.h"
|
||||
#include "Components/SceneComponent.h"
|
||||
#include "Engine/World.h"
|
||||
#endif
|
||||
|
||||
UsingUClass(UObject);
|
||||
UsingUClass(UClass);
|
||||
UsingUClass(UStruct);
|
||||
#if !defined(ENGINE_INDEPENDENT_JSENV)
|
||||
UsingUClass(UWorld); // for return type
|
||||
UsingUClass(USceneComponent);
|
||||
UsingUClass(UActorComponent);
|
||||
UsingUClass(UDataTable);
|
||||
UsingUClass(UDataTableFunctionLibrary);
|
||||
#endif
|
||||
#ifdef PUERTS_FTEXT_AS_OBJECT
|
||||
UsingCppType(FText);
|
||||
static PUERTS_NAMESPACE::CFunctionInfoWithCustomSignature FormatSignature(
|
||||
"(Fmt: string | FText, ...InArguments: (string | number | FText) []) :FText");
|
||||
|
||||
static void FText_Format(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
|
||||
FTextFormat Fmt;
|
||||
auto P0 = Info[0];
|
||||
if (P0->IsString())
|
||||
{
|
||||
Fmt = FTextFormat::FromString(PUERTS_NAMESPACE::FV8Utils::ToFString(Isolate, P0));
|
||||
}
|
||||
else if (::PUERTS_NAMESPACE::v8_impl::Converter<FText*>::accept(Context, P0))
|
||||
{
|
||||
Fmt = *::PUERTS_NAMESPACE::v8_impl::Converter<FText*>::toCpp(Context, P0);
|
||||
}
|
||||
else
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "Fmt expect a string or FText");
|
||||
return;
|
||||
}
|
||||
FFormatOrderedArguments Args;
|
||||
for (int i = 1; i < Info.Length(); i++)
|
||||
{
|
||||
if (Info[i]->IsInt32())
|
||||
{
|
||||
Args.Add(FFormatArgumentValue(Info[i]->Int32Value(Context).FromJust()));
|
||||
}
|
||||
else if (Info[i]->IsNumber())
|
||||
{
|
||||
Args.Add(FFormatArgumentValue(Info[i]->ToNumber(Context).ToLocalChecked()->Value()));
|
||||
}
|
||||
else if (Info[i]->IsString())
|
||||
{
|
||||
Args.Add(FFormatArgumentValue(FText::FromString(PUERTS_NAMESPACE::FV8Utils::ToFString(Isolate, Info[i]))));
|
||||
}
|
||||
else if (Info[i]->IsObject() && ::PUERTS_NAMESPACE::v8_impl::Converter<FText*>::accept(Context, Info[i]))
|
||||
{
|
||||
Args.Add(FFormatArgumentValue(*::PUERTS_NAMESPACE::v8_impl::Converter<FText*>::toCpp(Context, Info[i])));
|
||||
}
|
||||
else
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "InArguments expect a number/string/FText");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Info.GetReturnValue().Set(::PUERTS_NAMESPACE::v8_impl::Converter<FText>::toScript(Context, FText::Format(Fmt, Args)));
|
||||
}
|
||||
#endif
|
||||
|
||||
struct AutoRegisterForUE
|
||||
{
|
||||
AutoRegisterForUE()
|
||||
{
|
||||
PUERTS_NAMESPACE::DefineClass<UObject>()
|
||||
#if ENGINE_MAJOR_VERSION > 4 || ENGINE_MAJOR_VERSION == 4 && ENGINE_MINOR_VERSION >= 23
|
||||
.Method("CreateDefaultSubobject",
|
||||
SelectFunction(UObject * (UObject::*) (FName, UClass*, UClass*, bool, bool), &UObject::CreateDefaultSubobject))
|
||||
#else
|
||||
.Method("CreateDefaultSubobject", SelectFunction(UObject * (UObject::*) (FName, UClass*, UClass*, bool, bool, bool),
|
||||
&UObject::CreateDefaultSubobject))
|
||||
#endif
|
||||
.Method("GetName", SelectFunction(FString(UObjectBaseUtility::*)() const, &UObjectBaseUtility::GetName))
|
||||
.Method("GetOuter", MakeFunction(&UObject::GetOuter))
|
||||
.Method("GetClass", MakeFunction(&UObject::GetClass))
|
||||
.Method("IsA", SelectFunction(bool (UObjectBaseUtility::*)(UClass*) const, &UObjectBaseUtility::IsA))
|
||||
.Method("IsNative", MakeFunction(&UObjectBaseUtility::IsNative))
|
||||
#if !defined(ENGINE_INDEPENDENT_JSENV)
|
||||
.Method("GetWorld", MakeFunction(&UObject::GetWorld))
|
||||
#endif
|
||||
.Register();
|
||||
|
||||
PUERTS_NAMESPACE::DefineClass<UStruct>()
|
||||
.Method("IsChildOf", SelectFunction(bool (UStruct::*)(const UStruct*) const, &UStruct::IsChildOf))
|
||||
.Register();
|
||||
|
||||
#if !defined(ENGINE_INDEPENDENT_JSENV)
|
||||
PUERTS_NAMESPACE::DefineClass<USceneComponent>()
|
||||
.Method("SetupAttachment", MakeFunction(&USceneComponent::SetupAttachment))
|
||||
.Register();
|
||||
|
||||
PUERTS_NAMESPACE::DefineClass<UActorComponent>()
|
||||
.Method("RegisterComponent", MakeFunction(&UActorComponent::RegisterComponent))
|
||||
.Register();
|
||||
|
||||
PUERTS_NAMESPACE::DefineClass<UDataTableFunctionLibrary>()
|
||||
.Function("Generic_GetDataTableRowFromName", MakeFunction(&UDataTableFunctionLibrary::Generic_GetDataTableRowFromName))
|
||||
.Register();
|
||||
#endif
|
||||
|
||||
#ifdef PUERTS_FTEXT_AS_OBJECT
|
||||
PUERTS_NAMESPACE::DefineClass<FText>()
|
||||
.Constructor<>() // make destructor available
|
||||
.Method("ToString", MakeFunction(&FText::ToString))
|
||||
.Function("FromStringTable", MakeFunction(&FText::FromStringTable))
|
||||
.Function("FromString", SelectFunction(FText(*)(const FString&), &FText::FromString))
|
||||
.Function("Format", FText_Format, &FormatSignature)
|
||||
.Register();
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
AutoRegisterForUE _AutoRegisterForUE__;
|
||||
@@ -0,0 +1,9 @@
|
||||
/*
|
||||
* 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 "ExtensionMethods.h"
|
||||
@@ -0,0 +1,609 @@
|
||||
/*
|
||||
* 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 "FFIBinding.h"
|
||||
#ifdef WITH_FFI
|
||||
#include "JSClassRegister.h"
|
||||
#include "V8Utils.h"
|
||||
#if _MSC_VER
|
||||
#define FFI_BUILDING
|
||||
#endif
|
||||
|
||||
#if PLATFORM_ANDROID_ARM
|
||||
#include "armeabi-v7a/ffi.h"
|
||||
#elif PLATFORM_ANDROID_ARM64
|
||||
#include "arm64-v8a/ffi.h"
|
||||
#else
|
||||
#include "ffi.h"
|
||||
#endif
|
||||
|
||||
static FuncPtr* GFuncArray = nullptr;
|
||||
static uint32_t GFuncArrayLength = 0;
|
||||
|
||||
void SetFunctionArray(FuncPtr* FuncArray, uint32_t FuncArrayLength)
|
||||
{
|
||||
GFuncArray = FuncArray;
|
||||
GFuncArrayLength = FuncArrayLength;
|
||||
}
|
||||
|
||||
static v8::Local<v8::Uint8Array> WrapPointer(v8::Isolate* Isolate, void* Ptr, size_t Length)
|
||||
{
|
||||
v8::Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(Isolate, Ptr, Length);
|
||||
return v8::Uint8Array::New(ab, 0, Length);
|
||||
}
|
||||
|
||||
static v8::Local<v8::Uint8Array> WrapPointer(v8::Isolate* Isolate, void* Ptr)
|
||||
{
|
||||
return WrapPointer(Isolate, Ptr, 0);
|
||||
}
|
||||
|
||||
static char* ArrayBufferData(v8::Local<v8::Value> Val)
|
||||
{
|
||||
if (!Val->IsArrayBufferView())
|
||||
return nullptr;
|
||||
auto ui = Val.As<v8::ArrayBufferView>();
|
||||
auto ab_c = ui->Buffer()->GetContents();
|
||||
return static_cast<char*>(ab_c.Data()) + ui->ByteOffset();
|
||||
}
|
||||
|
||||
static size_t ArrayBufferLength(v8::Local<v8::Value> Val)
|
||||
{
|
||||
if (!Val->IsArrayBufferView())
|
||||
return 0;
|
||||
auto ui = Val.As<v8::ArrayBufferView>();
|
||||
return ui->ByteLength();
|
||||
}
|
||||
|
||||
static bool IsArrayBuffer(v8::Local<v8::Value> Val)
|
||||
{
|
||||
return Val->IsArrayBufferView();
|
||||
}
|
||||
|
||||
inline int64_t GetInt64(v8::Local<v8::Value> Val)
|
||||
{
|
||||
return Val->IsNumber() ? (Val->IsBigInt() ? Val.As<v8::BigInt>()->Int64Value() : (int64_t) Val.As<v8::Number>()->Value()) : 0;
|
||||
}
|
||||
|
||||
static void FFIPrepCif(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
unsigned int Nargs;
|
||||
char *Cif, *ArgTypes, *RetType;
|
||||
ffi_status Status;
|
||||
ffi_abi Abi;
|
||||
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Isolate::Scope IsolateScope(Isolate);
|
||||
v8::HandleScope HandleScope(Isolate);
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
v8::Context::Scope ContextScope(Context);
|
||||
|
||||
if (Info.Length() != 5 || !IsArrayBuffer(Info[0]) || !IsArrayBuffer(Info[3]) || !IsArrayBuffer(Info[4]))
|
||||
{
|
||||
PUERTS_NAMESPACE::FV8Utils::ThrowException(Isolate, "Bad parameters.");
|
||||
return;
|
||||
}
|
||||
|
||||
Cif = ArrayBufferData(Info[0]);
|
||||
Abi = (ffi_abi) Info[1]->Uint32Value(Context).ToChecked();
|
||||
Nargs = Info[2]->Uint32Value(Context).ToChecked();
|
||||
RetType = ArrayBufferData(Info[3]);
|
||||
ArgTypes = ArrayBufferData(Info[4]);
|
||||
|
||||
Status = ffi_prep_cif(
|
||||
reinterpret_cast<ffi_cif*>(Cif), Abi, Nargs, reinterpret_cast<ffi_type*>(RetType), reinterpret_cast<ffi_type**>(ArgTypes));
|
||||
|
||||
Info.GetReturnValue().Set(v8::Integer::New(Isolate, Status));
|
||||
}
|
||||
|
||||
static void FFIPrepCifVar(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
unsigned int FixArgs, TotoalArgs;
|
||||
char *Cif, *ArgTypes, *RetType;
|
||||
ffi_status Status;
|
||||
ffi_abi Abi;
|
||||
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Isolate::Scope IsolateScope(Isolate);
|
||||
v8::HandleScope HandleScope(Isolate);
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
v8::Context::Scope ContextScope(Context);
|
||||
|
||||
if (Info.Length() != 6 || !IsArrayBuffer(Info[0]) || !IsArrayBuffer(Info[4]) || !IsArrayBuffer(Info[5]))
|
||||
{
|
||||
PUERTS_NAMESPACE::FV8Utils::ThrowException(Isolate, "Bad parameters.");
|
||||
return;
|
||||
}
|
||||
|
||||
Cif = ArrayBufferData(Info[0]);
|
||||
Abi = (ffi_abi) Info[1]->Uint32Value(Context).ToChecked();
|
||||
FixArgs = Info[2]->Uint32Value(Context).ToChecked();
|
||||
TotoalArgs = Info[3]->Uint32Value(Context).ToChecked();
|
||||
RetType = ArrayBufferData(Info[4]);
|
||||
ArgTypes = ArrayBufferData(Info[5]);
|
||||
|
||||
Status = ffi_prep_cif_var(reinterpret_cast<ffi_cif*>(Cif), Abi, FixArgs, TotoalArgs, reinterpret_cast<ffi_type*>(RetType),
|
||||
reinterpret_cast<ffi_type**>(ArgTypes));
|
||||
|
||||
Info.GetReturnValue().Set(v8::Integer::New(Isolate, Status));
|
||||
}
|
||||
|
||||
class ClosureInfo
|
||||
{
|
||||
public:
|
||||
ClosureInfo(v8::Isolate* InIsolate, v8::Local<v8::Context> InContext, v8::Local<v8::Function> InFunction, void* InCodeLoc,
|
||||
ffi_closure* InClosure, size_t InRetSize)
|
||||
: CodeLoc(InCodeLoc)
|
||||
, Isolate(InIsolate)
|
||||
, Context(InIsolate, InContext)
|
||||
, Function(InIsolate, InFunction)
|
||||
, Closure(InClosure)
|
||||
, RetSize(InRetSize)
|
||||
{
|
||||
}
|
||||
|
||||
void* CodeLoc;
|
||||
|
||||
v8::Isolate* Isolate;
|
||||
|
||||
v8::Global<v8::Context> Context;
|
||||
|
||||
v8::Global<v8::Function> Function;
|
||||
|
||||
ffi_closure* Closure;
|
||||
|
||||
size_t RetSize;
|
||||
|
||||
v8::Global<v8::ArrayBuffer> Buffer;
|
||||
};
|
||||
|
||||
static void ClosureWrap(ffi_cif* Cif, void* Ret, void** Args, void* UserData)
|
||||
{
|
||||
ClosureInfo* CI = reinterpret_cast<ClosureInfo*>(UserData);
|
||||
|
||||
v8::Isolate* Isolate = CI->Isolate;
|
||||
v8::Isolate::Scope IsolateScope(Isolate);
|
||||
v8::HandleScope HandleScope(Isolate);
|
||||
v8::Local<v8::Context> Context = CI->Context.Get(Isolate);
|
||||
v8::Context::Scope ContextScope(Context);
|
||||
|
||||
v8::Local<v8::Value> Argv[2] = {WrapPointer(Isolate, Ret, CI->RetSize), WrapPointer(Isolate, Args, 0)};
|
||||
CI->Function.Get(CI->Isolate)->Call(Context, Context->Global(), 2, Argv);
|
||||
}
|
||||
|
||||
static void FFIAllocClosure(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Isolate::Scope IsolateScope(Isolate);
|
||||
v8::HandleScope HandleScope(Isolate);
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
v8::Context::Scope ContextScope(Context);
|
||||
|
||||
if (!IsArrayBuffer(Info[0]))
|
||||
{
|
||||
PUERTS_NAMESPACE::FV8Utils::ThrowException(Isolate, "ffi_alloc_closure: Uint32Array expected as #1 argument");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Info[1]->IsFunction())
|
||||
{
|
||||
PUERTS_NAMESPACE::FV8Utils::ThrowException(Isolate, "ffi_alloc_closure: function expected as #2 argument");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Info[2]->IsNumber())
|
||||
{
|
||||
PUERTS_NAMESPACE::FV8Utils::ThrowException(Isolate, "ffi_alloc_closure: number expected as #3 argument");
|
||||
return;
|
||||
}
|
||||
|
||||
ffi_cif* Cif = reinterpret_cast<ffi_cif*>(ArrayBufferData(Info[0]));
|
||||
v8::Local<v8::Function> Callback = v8::Local<v8::Function>::Cast(Info[1]);
|
||||
size_t RetSize = Info[2]->Uint32Value(Context).ToChecked();
|
||||
|
||||
void* CodeLoc;
|
||||
|
||||
ffi_closure* Closure = reinterpret_cast<ffi_closure*>(ffi_closure_alloc(sizeof(ffi_closure), &CodeLoc));
|
||||
if (!Closure)
|
||||
{
|
||||
PUERTS_NAMESPACE::FV8Utils::ThrowException(Isolate, "ffi_alloc_closure: alloc closure fail!");
|
||||
return;
|
||||
}
|
||||
|
||||
v8::Local<v8::ArrayBuffer> AB = v8::ArrayBuffer::New(Isolate, sizeof(ClosureInfo));
|
||||
|
||||
ClosureInfo* CI = new (AB->GetContents().Data()) ClosureInfo(Isolate, Context, Callback, CodeLoc, Closure, RetSize);
|
||||
|
||||
ffi_status status = ffi_prep_closure_loc(Closure, Cif, ClosureWrap, CI, CodeLoc);
|
||||
|
||||
if (status != FFI_OK)
|
||||
{
|
||||
ffi_closure_free(Closure);
|
||||
PUERTS_NAMESPACE::FV8Utils::ThrowException(Isolate, "ffi_alloc_closure: ffi_prep_closure_loc fail!");
|
||||
return;
|
||||
}
|
||||
|
||||
Info.GetReturnValue().Set(v8::Uint8Array::New(AB, 0, sizeof(ClosureInfo)));
|
||||
}
|
||||
|
||||
static void FFIFreeClosure(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Isolate::Scope IsolateScope(Isolate);
|
||||
v8::HandleScope HandleScope(Isolate);
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
v8::Context::Scope ContextScope(Context);
|
||||
|
||||
if (!IsArrayBuffer(Info[0]))
|
||||
{
|
||||
PUERTS_NAMESPACE::FV8Utils::ThrowException(Isolate, "ffi_free_closure: invalid type for #1 argument");
|
||||
return;
|
||||
}
|
||||
|
||||
if (ArrayBufferLength(Info[0]) != sizeof(ClosureInfo))
|
||||
{
|
||||
PUERTS_NAMESPACE::FV8Utils::ThrowException(Isolate, "ffi_free_closure: #1 argument length not match");
|
||||
return;
|
||||
}
|
||||
|
||||
ClosureInfo* CI = reinterpret_cast<ClosureInfo*>(ArrayBufferData(Info[0]));
|
||||
ffi_closure_free(CI->Closure);
|
||||
CI->~ClosureInfo();
|
||||
}
|
||||
|
||||
static void FFICall(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Isolate::Scope IsolateScope(Isolate);
|
||||
v8::HandleScope HandleScope(Isolate);
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
v8::Context::Scope ContextScope(Context);
|
||||
|
||||
if (Info.Length() != 4)
|
||||
{
|
||||
PUERTS_NAMESPACE::FV8Utils::ThrowException(Isolate, "ffi_call(): requires 4 arguments!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!IsArrayBuffer(Info[0]))
|
||||
{
|
||||
PUERTS_NAMESPACE::FV8Utils::ThrowException(Isolate, "ffi_call(): Uint32Array expected as #1 argument");
|
||||
return;
|
||||
}
|
||||
|
||||
if (Info[1]->IsNumber())
|
||||
{
|
||||
if (Info[1]->Uint32Value(Context).ToChecked() >= GFuncArrayLength)
|
||||
{
|
||||
PUERTS_NAMESPACE::FV8Utils::ThrowException(Isolate, "ffi_call(): function index out of range!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
char* Cif = ArrayBufferData(Info[0]);
|
||||
char* FuncPtr = Info[1]->IsNumber() ? reinterpret_cast<char*>(GFuncArray[Info[1]->Uint32Value(Context).ToChecked()])
|
||||
: ArrayBufferData(Info[1]);
|
||||
char* ReturnPtr = ArrayBufferData(Info[2]);
|
||||
char* ArgsPtr = ArrayBufferData(Info[3]);
|
||||
|
||||
#if __OBJC__ || __OBJC2__
|
||||
// @try {
|
||||
#endif
|
||||
ffi_call(
|
||||
reinterpret_cast<ffi_cif*>(Cif), FFI_FN(FuncPtr), reinterpret_cast<void*>(ReturnPtr), reinterpret_cast<void**>(ArgsPtr));
|
||||
#if __OBJC__ || __OBJC2__
|
||||
// } @catch (id ex) {
|
||||
// PUERTS_NAMESPACE::FV8Utils::ThrowException(Isolate, "ffi_call() throw exeption!");
|
||||
// return;
|
||||
// }
|
||||
#endif
|
||||
|
||||
Info.GetReturnValue().SetUndefined();
|
||||
}
|
||||
|
||||
static void WritePointer(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Isolate::Scope IsolateScope(Isolate);
|
||||
v8::HandleScope HandleScope(Isolate);
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
v8::Context::Scope ContextScope(Context);
|
||||
|
||||
if (!IsArrayBuffer(Info[0]))
|
||||
{
|
||||
PUERTS_NAMESPACE::FV8Utils::ThrowException(Isolate, "writePointer: Uint32Array expected as #1 argument");
|
||||
return;
|
||||
}
|
||||
auto Value = Info[1];
|
||||
if (!(Value->IsNull() || IsArrayBuffer(Value)))
|
||||
{
|
||||
PUERTS_NAMESPACE::FV8Utils::ThrowException(Isolate, "writePointer: Uint32Array expected as #3 argument");
|
||||
return;
|
||||
}
|
||||
|
||||
int64_t Offset = GetInt64(Info[2]);
|
||||
char* Ptr = ArrayBufferData(Info[0]) + Offset;
|
||||
|
||||
if (Value->IsNull())
|
||||
{
|
||||
*reinterpret_cast<char**>(Ptr) = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
char* ValuePtr = ArrayBufferData(Value);
|
||||
if (Info.Length() >= 4 && Info[3]->IsNumber())
|
||||
{
|
||||
ValuePtr += GetInt64(Info[3]);
|
||||
}
|
||||
*reinterpret_cast<char**>(Ptr) = ValuePtr;
|
||||
}
|
||||
|
||||
Info.GetReturnValue().SetUndefined();
|
||||
}
|
||||
|
||||
static void ReadPointer(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Isolate::Scope IsolateScope(Isolate);
|
||||
v8::HandleScope HandleScope(Isolate);
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
v8::Context::Scope ContextScope(Context);
|
||||
|
||||
if (!IsArrayBuffer(Info[0]))
|
||||
{
|
||||
PUERTS_NAMESPACE::FV8Utils::ThrowException(Isolate, "readPointer: Uint32Array expected as #1 argument");
|
||||
return;
|
||||
}
|
||||
|
||||
int64_t Offset = GetInt64(Info[1]);
|
||||
char* Ptr = ArrayBufferData(Info[0]) + Offset;
|
||||
|
||||
char* Val = *reinterpret_cast<char**>(Ptr);
|
||||
|
||||
size_t Size = !Info[2]->IsNull() ? Info[2]->Uint32Value(Context).ToChecked() : 0;
|
||||
|
||||
Info.GetReturnValue().Set(WrapPointer(Isolate, Val, Size));
|
||||
}
|
||||
|
||||
static void WriteUTF8String(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Isolate::Scope IsolateScope(Isolate);
|
||||
v8::HandleScope HandleScope(Isolate);
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
v8::Context::Scope ContextScope(Context);
|
||||
|
||||
if (!IsArrayBuffer(Info[0]))
|
||||
{
|
||||
PUERTS_NAMESPACE::FV8Utils::ThrowException(Isolate, "WriteString: Uint32Array expected as #1 argument");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Info[1]->IsString())
|
||||
{
|
||||
PUERTS_NAMESPACE::FV8Utils::ThrowException(Isolate, "WriteString: string expected as #2 argument");
|
||||
return;
|
||||
}
|
||||
|
||||
v8::String::Utf8Value utf8Str(Isolate, Info[1]);
|
||||
|
||||
int64_t Offset = GetInt64(Info[2]);
|
||||
if (utf8Str.length() >= ArrayBufferLength(Info[0]) - Offset)
|
||||
{
|
||||
PUERTS_NAMESPACE::FV8Utils::ThrowException(Isolate, "WriteString: no enough space");
|
||||
return;
|
||||
}
|
||||
|
||||
char* Ptr = ArrayBufferData(Info[0]) + Offset;
|
||||
memcpy(Ptr, *utf8Str, utf8Str.length() + 1);
|
||||
}
|
||||
|
||||
static void ReadUTF8String(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Isolate::Scope IsolateScope(Isolate);
|
||||
v8::HandleScope HandleScope(Isolate);
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
v8::Context::Scope ContextScope(Context);
|
||||
|
||||
if (!IsArrayBuffer(Info[0]))
|
||||
{
|
||||
PUERTS_NAMESPACE::FV8Utils::ThrowException(Isolate, "ReadCString: Uint32Array expected as #1 argument");
|
||||
return;
|
||||
}
|
||||
|
||||
int64_t Offset = GetInt64(Info[1]);
|
||||
char* Ptr = ArrayBufferData(Info[0]) + Offset;
|
||||
|
||||
Info.GetReturnValue().Set(PUERTS_NAMESPACE::FV8Utils::ToV8String(Isolate, Ptr));
|
||||
}
|
||||
|
||||
static void UTF8Length(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Isolate::Scope IsolateScope(Isolate);
|
||||
v8::HandleScope HandleScope(Isolate);
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
v8::Context::Scope ContextScope(Context);
|
||||
|
||||
if (!Info[0]->IsString())
|
||||
{
|
||||
PUERTS_NAMESPACE::FV8Utils::ThrowException(Isolate, "WriteString: string expected as #2 argument");
|
||||
return;
|
||||
}
|
||||
|
||||
v8::String::Utf8Value utf8Str(Isolate, Info[0]);
|
||||
|
||||
Info.GetReturnValue().Set(utf8Str.length());
|
||||
}
|
||||
|
||||
static void Init(v8::Local<v8::Context> Context, v8::Local<v8::Object> Exports)
|
||||
{
|
||||
v8::Isolate* Isolate = Context->GetIsolate();
|
||||
|
||||
Exports
|
||||
->Set(Context, PUERTS_NAMESPACE::FV8Utils::ToV8String(Isolate, "ffi_prep_cif"),
|
||||
v8::FunctionTemplate::New(Isolate, FFIPrepCif)->GetFunction(Context).ToLocalChecked())
|
||||
.Check();
|
||||
|
||||
Exports
|
||||
->Set(Context, PUERTS_NAMESPACE::FV8Utils::ToV8String(Isolate, "ffi_prep_cif_var"),
|
||||
v8::FunctionTemplate::New(Isolate, FFIPrepCifVar)->GetFunction(Context).ToLocalChecked())
|
||||
.Check();
|
||||
|
||||
Exports
|
||||
->Set(Context, PUERTS_NAMESPACE::FV8Utils::ToV8String(Isolate, "ffi_call"),
|
||||
v8::FunctionTemplate::New(Isolate, FFICall)->GetFunction(Context).ToLocalChecked())
|
||||
.Check();
|
||||
|
||||
Exports
|
||||
->Set(Context, PUERTS_NAMESPACE::FV8Utils::ToV8String(Isolate, "writePointer"),
|
||||
v8::FunctionTemplate::New(Isolate, WritePointer)->GetFunction(Context).ToLocalChecked())
|
||||
.Check();
|
||||
|
||||
Exports
|
||||
->Set(Context, PUERTS_NAMESPACE::FV8Utils::ToV8String(Isolate, "readPointer"),
|
||||
v8::FunctionTemplate::New(Isolate, ReadPointer)->GetFunction(Context).ToLocalChecked())
|
||||
.Check();
|
||||
|
||||
Exports
|
||||
->Set(Context, PUERTS_NAMESPACE::FV8Utils::ToV8String(Isolate, "writeUTF8String"),
|
||||
v8::FunctionTemplate::New(Isolate, WriteUTF8String)->GetFunction(Context).ToLocalChecked())
|
||||
.Check();
|
||||
|
||||
Exports
|
||||
->Set(Context, PUERTS_NAMESPACE::FV8Utils::ToV8String(Isolate, "readUTF8String"),
|
||||
v8::FunctionTemplate::New(Isolate, ReadUTF8String)->GetFunction(Context).ToLocalChecked())
|
||||
.Check();
|
||||
|
||||
Exports
|
||||
->Set(Context, PUERTS_NAMESPACE::FV8Utils::ToV8String(Isolate, "UTF8Length"),
|
||||
v8::FunctionTemplate::New(Isolate, UTF8Length)->GetFunction(Context).ToLocalChecked())
|
||||
.Check();
|
||||
|
||||
Exports
|
||||
->Set(Context, PUERTS_NAMESPACE::FV8Utils::ToV8String(Isolate, "ffi_alloc_closure"),
|
||||
v8::FunctionTemplate::New(Isolate, FFIAllocClosure)->GetFunction(Context).ToLocalChecked())
|
||||
.Check();
|
||||
|
||||
Exports
|
||||
->Set(Context, PUERTS_NAMESPACE::FV8Utils::ToV8String(Isolate, "ffi_free_closure"),
|
||||
v8::FunctionTemplate::New(Isolate, FFIFreeClosure)->GetFunction(Context).ToLocalChecked())
|
||||
.Check();
|
||||
|
||||
#define SET_FFI_ENUM(value) \
|
||||
Exports->DefineOwnProperty(Context, PUERTS_NAMESPACE::FV8Utils::ToV8String(Isolate, #value), \
|
||||
v8::Integer::New(Isolate, (uint32_t) (value)), static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontDelete))
|
||||
|
||||
SET_FFI_ENUM(FFI_OK);
|
||||
SET_FFI_ENUM(FFI_BAD_TYPEDEF);
|
||||
SET_FFI_ENUM(FFI_BAD_ABI);
|
||||
|
||||
SET_FFI_ENUM(FFI_DEFAULT_ABI);
|
||||
SET_FFI_ENUM(FFI_FIRST_ABI);
|
||||
SET_FFI_ENUM(FFI_LAST_ABI);
|
||||
SET_FFI_ENUM(FFI_TYPE_STRUCT);
|
||||
#undef SET_FFI_ENUM
|
||||
|
||||
auto Types = v8::Object::New(Isolate);
|
||||
|
||||
#define SET_FFI_TYPE(key, value) \
|
||||
Types->DefineOwnProperty(Context, PUERTS_NAMESPACE::FV8Utils::ToV8String(Isolate, key), \
|
||||
WrapPointer(Isolate, reinterpret_cast<char*>(&value)), static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontDelete))
|
||||
|
||||
SET_FFI_TYPE("void", ffi_type_void);
|
||||
SET_FFI_TYPE("uint8", ffi_type_uint8);
|
||||
SET_FFI_TYPE("int8", ffi_type_sint8);
|
||||
SET_FFI_TYPE("uint16", ffi_type_uint16);
|
||||
SET_FFI_TYPE("int16", ffi_type_sint16);
|
||||
SET_FFI_TYPE("uint32", ffi_type_uint32);
|
||||
SET_FFI_TYPE("int32", ffi_type_sint32);
|
||||
SET_FFI_TYPE("uint64", ffi_type_uint64);
|
||||
SET_FFI_TYPE("int64", ffi_type_sint64);
|
||||
SET_FFI_TYPE("float", ffi_type_float);
|
||||
SET_FFI_TYPE("double", ffi_type_double);
|
||||
SET_FFI_TYPE("pointer", ffi_type_pointer);
|
||||
#undef SET_FFI_TYPE
|
||||
|
||||
Exports->Set(Context, PUERTS_NAMESPACE::FV8Utils::ToV8String(Isolate, "FFI_TYPES"), Types).Check();
|
||||
|
||||
auto SizeOf = v8::Object::New(Isolate);
|
||||
#define SET_SIZEOF(key, type) \
|
||||
SizeOf->DefineOwnProperty(Context, PUERTS_NAMESPACE::FV8Utils::ToV8String(Isolate, key), \
|
||||
v8::Integer::New(Isolate, static_cast<uint32_t>(sizeof(type))), \
|
||||
static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontDelete))
|
||||
|
||||
SET_SIZEOF("uint8", uint8_t);
|
||||
SET_SIZEOF("int8", int8_t);
|
||||
SET_SIZEOF("uint16", uint16_t);
|
||||
SET_SIZEOF("int16", int16_t);
|
||||
SET_SIZEOF("uint32", uint32_t);
|
||||
SET_SIZEOF("int32", int32_t);
|
||||
SET_SIZEOF("uint64", uint64_t);
|
||||
SET_SIZEOF("int64", int64_t);
|
||||
SET_SIZEOF("float", float);
|
||||
SET_SIZEOF("double", double);
|
||||
SET_SIZEOF("pointer", char*);
|
||||
#undef SET_SIZEOF
|
||||
Exports->Set(Context, PUERTS_NAMESPACE::FV8Utils::ToV8String(Isolate, "sizeof"), SizeOf).Check();
|
||||
|
||||
auto AlignOf = v8::Object::New(Isolate);
|
||||
#if _MSC_VER
|
||||
#define SET_ALIGNOF(name, type) \
|
||||
struct s_##name \
|
||||
{ \
|
||||
type a; \
|
||||
}; \
|
||||
AlignOf->DefineOwnProperty(Context, PUERTS_NAMESPACE::FV8Utils::ToV8String(Isolate, #name), \
|
||||
v8::Integer::New(Isolate, static_cast<uint32_t>(alignof(struct s_##name))), \
|
||||
static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontDelete))
|
||||
#else
|
||||
#define SET_ALIGNOF(name, type) \
|
||||
struct s_##name \
|
||||
{ \
|
||||
type a; \
|
||||
}; \
|
||||
AlignOf->DefineOwnProperty(Context, PUERTS_NAMESPACE::FV8Utils::ToV8String(Isolate, #name), \
|
||||
v8::Integer::New(Isolate, static_cast<uint32_t>(__alignof__(struct s_##name))), \
|
||||
static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontDelete))
|
||||
#endif
|
||||
|
||||
SET_ALIGNOF(uint8, uint8_t);
|
||||
SET_ALIGNOF(int8, int8_t);
|
||||
SET_ALIGNOF(uint16, uint16_t);
|
||||
SET_ALIGNOF(int16, int16_t);
|
||||
SET_ALIGNOF(uint32, uint32_t);
|
||||
SET_ALIGNOF(int32, int32_t);
|
||||
SET_ALIGNOF(uint64, uint64_t);
|
||||
SET_ALIGNOF(int64, int64_t);
|
||||
SET_ALIGNOF(float, float);
|
||||
SET_ALIGNOF(double, double);
|
||||
SET_ALIGNOF(pointer, char*);
|
||||
#undef SET_ALIGNOF
|
||||
Exports->Set(Context, PUERTS_NAMESPACE::FV8Utils::ToV8String(Isolate, "alignof"), AlignOf).Check();
|
||||
|
||||
#define SET_Property(key, value) \
|
||||
Exports->DefineOwnProperty(Context, PUERTS_NAMESPACE::FV8Utils::ToV8String(Isolate, key), \
|
||||
v8::Integer::New(Isolate, (uint32_t) (value)), static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontDelete))
|
||||
|
||||
SET_Property("FFI_ARG_SIZE", sizeof(ffi_arg));
|
||||
SET_Property("FFI_SARG_SIZE", sizeof(ffi_sarg));
|
||||
SET_Property("FFI_TYPE_SIZE", sizeof(ffi_type));
|
||||
SET_Property("FFI_CIF_SIZE", sizeof(ffi_cif));
|
||||
SET_Property("POINTER_SIZE", sizeof(char*));
|
||||
#undef SET_Property
|
||||
}
|
||||
|
||||
PUERTS_MODULE(ffi_bindings, Init);
|
||||
|
||||
#else
|
||||
|
||||
void SetFunctionArray(FuncPtr* FuncArray, uint32_t FuncArrayLength)
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,740 @@
|
||||
/*
|
||||
* 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 "FunctionTranslator.h"
|
||||
#include "V8Utils.h"
|
||||
#include "Misc/DefaultValueHelper.h"
|
||||
#include <mutex>
|
||||
|
||||
static TMap<FName, TMap<FName, TMap<FName, FString>>> ParamDefaultMetas;
|
||||
|
||||
static TMap<FName, TMap<FName, FString>>* PC = nullptr;
|
||||
static TMap<FName, FString>* PF = nullptr;
|
||||
|
||||
#if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 2
|
||||
UE_DISABLE_OPTIMIZATION
|
||||
#else
|
||||
PRAGMA_DISABLE_OPTIMIZATION
|
||||
#endif
|
||||
static void ParamDefaultMetasInit()
|
||||
{
|
||||
// PC = &ParamDefaultMetas.Add(TEXT("MainObject"));
|
||||
// PF = &PC->Add(TEXT("DefaultTest"));
|
||||
// PF->Add(TEXT("Str"), TEXT("i am default"));
|
||||
// PF->Add(TEXT("I"), TEXT("10"));
|
||||
// PF->Add(TEXT("Vec"), TEXT("1.100000,2.200000,3.300000"));
|
||||
#include "InitParamDefaultMetas.inl"
|
||||
return;
|
||||
}
|
||||
#if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 2
|
||||
UE_ENABLE_OPTIMIZATION
|
||||
#else
|
||||
PRAGMA_ENABLE_OPTIMIZATION
|
||||
#endif
|
||||
|
||||
std::once_flag ParamDefaultMetasInitFlag;
|
||||
|
||||
TMap<FName, FString>* GetParamDefaultMetaFor(UFunction* InFunction)
|
||||
{
|
||||
std::call_once(ParamDefaultMetasInitFlag, ParamDefaultMetasInit);
|
||||
UClass* OuterClass = InFunction->GetOuterUClass();
|
||||
auto ClassParamDefaultMeta = ParamDefaultMetas.Find(OuterClass->GetFName());
|
||||
if (ClassParamDefaultMeta)
|
||||
{
|
||||
return ClassParamDefaultMeta->Find(InFunction->GetFName());
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
namespace PUERTS_NAMESPACE
|
||||
{
|
||||
static const int ARG_ARRAY_SIZE = 8;
|
||||
|
||||
#if defined(USE_GLOBAL_PARAMS_BUFFER)
|
||||
// Global Buffer, Not thread safe
|
||||
static void* Buffer = nullptr;
|
||||
static int BufferSize = 0;
|
||||
|
||||
static void RequireBuffer(int RequireSize)
|
||||
{
|
||||
if (RequireSize > BufferSize)
|
||||
{
|
||||
if (Buffer)
|
||||
FMemory::Free(Buffer);
|
||||
Buffer = FMemory::Malloc(RequireSize, 16);
|
||||
BufferSize = RequireSize;
|
||||
}
|
||||
}
|
||||
|
||||
class GlobalBufferAutoRelease
|
||||
{
|
||||
public:
|
||||
~GlobalBufferAutoRelease()
|
||||
{
|
||||
if (Buffer)
|
||||
FMemory::Free(Buffer);
|
||||
Buffer = nullptr;
|
||||
BufferSize = 0;
|
||||
}
|
||||
};
|
||||
|
||||
static GlobalBufferAutoRelease Dummy;
|
||||
#endif
|
||||
|
||||
FFunctionTranslator::FFunctionTranslator(UFunction* InFunction, bool IsDelegate)
|
||||
{
|
||||
Init(InFunction, IsDelegate);
|
||||
}
|
||||
void FFunctionTranslator::Init(UFunction* InFunction, bool IsDelegate)
|
||||
{
|
||||
check(InFunction);
|
||||
Function = InFunction;
|
||||
#if WITH_EDITOR
|
||||
FunctionName = Function->GetFName();
|
||||
#endif
|
||||
ParamsBufferSize = InFunction->PropertiesSize > InFunction->ParmsSize ? InFunction->PropertiesSize : InFunction->ParmsSize;
|
||||
|
||||
#if defined(USE_GLOBAL_PARAMS_BUFFER)
|
||||
RequireBuffer(ParamsBufferSize);
|
||||
#endif
|
||||
|
||||
if (IsDelegate)
|
||||
{
|
||||
IsInterfaceFunction = false;
|
||||
IsStatic = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
UClass* OuterClass = InFunction->GetOuterUClass();
|
||||
IsInterfaceFunction = (OuterClass->HasAnyClassFlags(CLASS_Interface) && OuterClass != UInterface::StaticClass());
|
||||
IsStatic = InFunction->HasAnyFunctionFlags(FUNC_Static);
|
||||
}
|
||||
Arguments.clear();
|
||||
|
||||
SkipWorldContextInArg0 = false;
|
||||
for (TFieldIterator<PropertyMacro> It(InFunction); It && (It->PropertyFlags & CPF_Parm); ++It)
|
||||
{
|
||||
PropertyMacro* Property = *It;
|
||||
static const FName WorldContextPinName(TEXT("__WorldContext"));
|
||||
if (IsStatic && !InFunction->IsNative() && Property->GetFName() == WorldContextPinName && Arguments.size() == 0)
|
||||
{
|
||||
SkipWorldContextInArg0 = true;
|
||||
;
|
||||
}
|
||||
if (Property->HasAnyPropertyFlags(CPF_ReturnParm))
|
||||
{
|
||||
Return = FPropertyTranslator::Create(Property);
|
||||
}
|
||||
else
|
||||
{
|
||||
Arguments.push_back(FPropertyTranslator::Create(Property));
|
||||
}
|
||||
}
|
||||
|
||||
ArgumentDefaultValues = nullptr;
|
||||
|
||||
if (!IsDelegate)
|
||||
{
|
||||
TMap<FName, FString>* MetaMap = GetParamDefaultMetaFor(InFunction);
|
||||
if (MetaMap)
|
||||
{
|
||||
for (TFieldIterator<PropertyMacro> ParamIt(InFunction); ParamIt; ++ParamIt)
|
||||
{
|
||||
auto Property = *ParamIt;
|
||||
if (Property->PropertyFlags & CPF_Parm)
|
||||
{
|
||||
if (!(Property->PropertyFlags & CPF_ReturnParm))
|
||||
{
|
||||
// const FName MetadataCppDefaultValueKey(*(FString(TEXT("CPP_Default_")) + Property->GetName()));
|
||||
FString* DefaultValuePtr = nullptr;
|
||||
DefaultValuePtr = MetaMap->Find(Property->GetFName());
|
||||
if (DefaultValuePtr && !DefaultValuePtr->IsEmpty())
|
||||
{
|
||||
// UE_LOG(LogTemp, Warning, TEXT("Meta %s %s"), *Property->GetFName().ToString(), **DefaultValuePtr);
|
||||
if (!ArgumentDefaultValues)
|
||||
{
|
||||
ArgumentDefaultValues = FMemory::Malloc(ParamsBufferSize, 16);
|
||||
InFunction->InitializeStruct(ArgumentDefaultValues);
|
||||
}
|
||||
|
||||
void* PropValuePtr = Property->ContainerPtrToValuePtr<void>(ArgumentDefaultValues);
|
||||
|
||||
if (const StructPropertyMacro* StructProp = CastFieldMacro<StructPropertyMacro>(Property))
|
||||
{
|
||||
if (StructProp->Struct == TBaseStructure<FVector>::Get())
|
||||
{
|
||||
FVector* Vector = (FVector*) PropValuePtr;
|
||||
FDefaultValueHelper::ParseVector(**DefaultValuePtr, *Vector);
|
||||
continue;
|
||||
}
|
||||
else if (StructProp->Struct == TBaseStructure<FVector2D>::Get())
|
||||
{
|
||||
FVector2D* Vector2D = (FVector2D*) PropValuePtr;
|
||||
FDefaultValueHelper::ParseVector2D(**DefaultValuePtr, *Vector2D);
|
||||
continue;
|
||||
}
|
||||
else if (StructProp->Struct == TBaseStructure<FRotator>::Get())
|
||||
{
|
||||
FRotator* Rotator = (FRotator*) PropValuePtr;
|
||||
FDefaultValueHelper::ParseRotator(**DefaultValuePtr, *Rotator);
|
||||
continue;
|
||||
}
|
||||
else if (StructProp->Struct == TBaseStructure<FColor>::Get())
|
||||
{
|
||||
FColor* Color = (FColor*) PropValuePtr;
|
||||
FDefaultValueHelper::ParseColor(**DefaultValuePtr, *Color);
|
||||
continue;
|
||||
}
|
||||
else if (StructProp->Struct == TBaseStructure<FLinearColor>::Get())
|
||||
{
|
||||
FLinearColor* LinearColor = (FLinearColor*) PropValuePtr;
|
||||
LinearColor->InitFromString(**DefaultValuePtr);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
#if ENGINE_MINOR_VERSION > 0 && ENGINE_MAJOR_VERSION > 4
|
||||
Property->ImportText_Direct(**DefaultValuePtr, PropValuePtr, nullptr, PPF_None);
|
||||
#else
|
||||
Property->ImportText(**DefaultValuePtr, PropValuePtr, PPF_None, nullptr);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
v8::Local<v8::FunctionTemplate> FFunctionTranslator::ToFunctionTemplate(v8::Isolate* Isolate)
|
||||
{
|
||||
return v8::FunctionTemplate::New(Isolate, Call, v8::External::New(Isolate, this));
|
||||
}
|
||||
|
||||
void FFunctionTranslator::Call(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
|
||||
FFunctionTranslator* This = static_cast<FFunctionTranslator*>((v8::Local<v8::External>::Cast(Info.Data()))->Value());
|
||||
This->Call(Isolate, Context, Info);
|
||||
}
|
||||
|
||||
void FFunctionTranslator::Call(
|
||||
v8::Isolate* Isolate, v8::Local<v8::Context>& Context, const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
UObject* CallObject = IsStatic ? BindObject.Get() : FV8Utils::GetUObject(Info.Holder());
|
||||
if (!CallObject)
|
||||
{
|
||||
if (IsStatic) //延时初始化
|
||||
{
|
||||
CallObject = Function->GetOuterUClass()->GetDefaultObject();
|
||||
BindObject = CallObject;
|
||||
}
|
||||
if (!CallObject)
|
||||
{
|
||||
FV8Utils::ThrowException(Isolate, "access a null object");
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (FV8Utils::IsReleasedPtr(CallObject))
|
||||
{
|
||||
FV8Utils::ThrowException(Isolate, "access a invalid object");
|
||||
return;
|
||||
}
|
||||
TWeakObjectPtr<UFunction> CallFunction =
|
||||
!IsInterfaceFunction ? Function : (CallObject->GetClass()->FindFunctionByName(Function->GetFName()));
|
||||
#if defined(USE_GLOBAL_PARAMS_BUFFER)
|
||||
void* Params = Buffer;
|
||||
#else
|
||||
void* Params = ParamsBufferSize > 0 ? FMemory_Alloca(ParamsBufferSize) : nullptr;
|
||||
#endif
|
||||
#if WITH_EDITOR
|
||||
if (!CallFunction.IsValid())
|
||||
{
|
||||
CallFunction = CallObject->GetClass()->FindFunctionByName(FunctionName);
|
||||
Init(CallFunction.Get(), false);
|
||||
}
|
||||
#endif
|
||||
|
||||
auto CallFunctionPtr = CallFunction.Get();
|
||||
if ((Function->FunctionFlags & FUNC_Native) && !(Function->FunctionFlags & FUNC_Net) &&
|
||||
!CallFunctionPtr->HasAnyFunctionFlags(FUNC_UbergraphFunction))
|
||||
{
|
||||
FastCall(Isolate, Context, Info, CallObject, CallFunctionPtr, Params);
|
||||
}
|
||||
else
|
||||
{
|
||||
SlowCall(Isolate, Context, Info, CallObject, CallFunctionPtr, Params);
|
||||
}
|
||||
}
|
||||
|
||||
void FFunctionTranslator::SlowCall(v8::Isolate* Isolate, v8::Local<v8::Context>& Context,
|
||||
const v8::FunctionCallbackInfo<v8::Value>& Info, UObject* CallObject, UFunction* CallFunction, void* Params)
|
||||
{
|
||||
if (Params)
|
||||
{
|
||||
FMemory::Memzero(Params, ParamsBufferSize);
|
||||
}
|
||||
|
||||
if (!Call_ProcessParams(Isolate, Context, Info, Params, 0))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
CallObject->UObject::ProcessEvent(CallFunction, Params);
|
||||
|
||||
Call_ProcessReturnAndOutParams(Isolate, Context, Info, Params, 0);
|
||||
}
|
||||
|
||||
void FFunctionTranslator::FastCall(v8::Isolate* Isolate, v8::Local<v8::Context>& Context,
|
||||
const v8::FunctionCallbackInfo<v8::Value>& Info, UObject* CallObject, UFunction* CallFunction, void* Params)
|
||||
{
|
||||
if (Params)
|
||||
{
|
||||
FMemory::Memzero(Params, ParamsBufferSize);
|
||||
if (Return)
|
||||
{
|
||||
Return->Property->InitializeValue_InContainer(Params);
|
||||
}
|
||||
}
|
||||
FFrame NewStack(CallObject, CallFunction, Params, nullptr,
|
||||
#if ENGINE_MINOR_VERSION >= 25 || ENGINE_MAJOR_VERSION > 4
|
||||
Function->ChildProperties
|
||||
#else
|
||||
Function->Children
|
||||
#endif
|
||||
);
|
||||
|
||||
checkSlow(NewStack.Locals || Function->ParmsSize == 0);
|
||||
FOutParmRec** LastOut = &NewStack.OutParms;
|
||||
int Index = 0;
|
||||
for (TFieldIterator<PropertyMacro> It(CallFunction); It && (It->PropertyFlags & CPF_Parm); ++It)
|
||||
{
|
||||
PropertyMacro* Property = *It;
|
||||
FOutParmRec* Out = nullptr;
|
||||
if (Property->HasAnyPropertyFlags(CPF_OutParm))
|
||||
{
|
||||
CA_SUPPRESS(6263)
|
||||
Out = (FOutParmRec*) FMemory_Alloca(sizeof(FOutParmRec));
|
||||
Out->Property = Property;
|
||||
|
||||
if (*LastOut)
|
||||
{
|
||||
(*LastOut)->NextOutParm = Out;
|
||||
LastOut = &(*LastOut)->NextOutParm;
|
||||
}
|
||||
else
|
||||
{
|
||||
*LastOut = Out;
|
||||
}
|
||||
}
|
||||
|
||||
if (Property->HasAnyPropertyFlags(CPF_ReturnParm))
|
||||
{
|
||||
if (Property->HasAnyPropertyFlags(CPF_OutParm))
|
||||
{
|
||||
Out->PropAddr = Property->ContainerPtrToValuePtr<uint8>(Params);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (UNLIKELY(ArgumentDefaultValues && Info[Index]->IsUndefined()))
|
||||
{
|
||||
Property->CopyCompleteValue_InContainer(Params, ArgumentDefaultValues);
|
||||
if (Property->HasAnyPropertyFlags(CPF_OutParm))
|
||||
{
|
||||
Out->PropAddr = Property->ContainerPtrToValuePtr<uint8>(Params);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Property->InitializeValue_InContainer(Params);
|
||||
if (Property->HasAnyPropertyFlags(CPF_OutParm))
|
||||
{
|
||||
if (!Arguments[Index]->JsToUEFastInContainer(
|
||||
Isolate, Context, Info[Index], Params, reinterpret_cast<void**>(&(Out->PropAddr))))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!Arguments[Index]->JsToUEInContainer(Isolate, Context, Info[Index], Params, false))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
++Index;
|
||||
}
|
||||
if (CallFunction->HasAnyFunctionFlags(FUNC_HasOutParms))
|
||||
{
|
||||
if (*LastOut)
|
||||
{
|
||||
(*LastOut)->NextOutParm = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
const bool bHasReturnParam = CallFunction->ReturnValueOffset != MAX_uint16;
|
||||
uint8* ReturnValueAddress = bHasReturnParam ? ((uint8*) Params + CallFunction->ReturnValueOffset) : nullptr;
|
||||
CallFunction->Invoke(CallObject, NewStack, ReturnValueAddress);
|
||||
|
||||
if (Return)
|
||||
{
|
||||
Info.GetReturnValue().Set(Return->UEToJsInContainer(Isolate, Context, Params));
|
||||
Return->Property->DestroyValue_InContainer(Params);
|
||||
}
|
||||
|
||||
LastOut = &NewStack.OutParms;
|
||||
for (int i = 0; i < Arguments.size(); ++i)
|
||||
{
|
||||
auto PropertyFlags = Arguments[i]->Property->PropertyFlags;
|
||||
if (PropertyFlags & CPF_OutParm)
|
||||
{
|
||||
if ((PropertyFlags & CPF_Parm) && (!(PropertyFlags & CPF_ConstParm)) && (!(PropertyFlags & CPF_ReturnParm)))
|
||||
{
|
||||
if ((*LastOut)->PropAddr >= (uint8*) Params && (*LastOut)->PropAddr < ((uint8*) Params + ParamsBufferSize))
|
||||
{
|
||||
Arguments[i]->UEOutToJsInContainer(Isolate, Context, Info[i], Params, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
LastOut = &(*LastOut)->NextOutParm;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
LastOut = &(*LastOut)->NextOutParm;
|
||||
}
|
||||
if (Arguments[i]->ParamShallowCopySize == 0)
|
||||
{
|
||||
Arguments[i]->Property->DestroyValue_InContainer(Params);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FFunctionTranslator::Call(v8::Isolate* Isolate, v8::Local<v8::Context>& Context,
|
||||
const v8::FunctionCallbackInfo<v8::Value>& Info, std::function<void(void*)> OnCall)
|
||||
{
|
||||
#if defined(USE_GLOBAL_PARAMS_BUFFER)
|
||||
void* Params = Buffer;
|
||||
#else
|
||||
void* Params = ParamsBufferSize > 0 ? FMemory_Alloca(ParamsBufferSize) : nullptr;
|
||||
#endif
|
||||
if (Params)
|
||||
FMemory::Memzero(Params, ParamsBufferSize);
|
||||
|
||||
Call_ProcessParams(Isolate, Context, Info, Params, 0);
|
||||
|
||||
OnCall(Params);
|
||||
|
||||
Call_ProcessReturnAndOutParams(Isolate, Context, Info, Params, 0);
|
||||
}
|
||||
|
||||
void FFunctionTranslator::CallJs(v8::Isolate* Isolate, v8::Local<v8::Context>& Context, v8::Local<v8::Function> JsFunction,
|
||||
v8::Local<v8::Value> This, void* Params)
|
||||
{
|
||||
v8::Local<v8::Value>* Args =
|
||||
static_cast<v8::Local<v8::Value>*>(FMemory_Alloca(sizeof(v8::Local<v8::Value>) * Arguments.size()));
|
||||
FMemory::Memset(Args, 0, sizeof(v8::Local<v8::Value>) * Arguments.size());
|
||||
for (int i = 0; i < Arguments.size(); ++i)
|
||||
{
|
||||
Args[i] = Arguments[i]->UEToJsInContainer(Isolate, Context, Params, false);
|
||||
}
|
||||
|
||||
v8::MaybeLocal<v8::Value> Result;
|
||||
if (UNLIKELY(SkipWorldContextInArg0))
|
||||
{
|
||||
Result = JsFunction->Call(Context, This, Arguments.size() - 1, &Args[0] + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
Result = JsFunction->Call(Context, This, Arguments.size(), Args);
|
||||
}
|
||||
|
||||
if (!Result.IsEmpty()) // empty mean exception
|
||||
{
|
||||
if (Return)
|
||||
{
|
||||
Return->JsToUEInContainer(Isolate, Context, Result.ToLocalChecked(), Params, true);
|
||||
}
|
||||
|
||||
for (int i = 0; i < Arguments.size(); ++i)
|
||||
{
|
||||
Arguments[i]->JsToUEOutInContainer(Isolate, Context, Args[i], Params, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static FOutParmRec* GetMatchOutParmRec(FOutParmRec* OutParam, PropertyMacro* OutProperty)
|
||||
{
|
||||
FOutParmRec* Out = OutParam;
|
||||
while (Out)
|
||||
{
|
||||
if (Out->Property == OutProperty)
|
||||
{
|
||||
return Out;
|
||||
}
|
||||
Out = Out->NextOutParm;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void FFunctionTranslator::CallJs(v8::Isolate* Isolate, v8::Local<v8::Context>& Context, v8::Local<v8::Function> JsFunction,
|
||||
v8::Local<v8::Value> This, UObject* ContextObject, FFrame& Stack, void* RESULT_PARAM)
|
||||
{
|
||||
void* Params = Stack.Locals;
|
||||
|
||||
FOutParmRec* NewOutParms = nullptr;
|
||||
|
||||
const bool CallByBP = Stack.Node != Stack.CurrentNativeFunction;
|
||||
|
||||
if (CallByBP)
|
||||
{
|
||||
#if defined(USE_GLOBAL_PARAMS_BUFFER)
|
||||
void* Params = Buffer;
|
||||
#else
|
||||
Params = ParamsBufferSize > 0 ? FMemory_Alloca(ParamsBufferSize) : nullptr;
|
||||
#endif
|
||||
|
||||
if (Params)
|
||||
{
|
||||
FMemory::Memzero(Params, ParamsBufferSize);
|
||||
FOutParmRec** LastOut = &NewOutParms;
|
||||
|
||||
// ScriptCore.cpp
|
||||
for (PropertyMacro* Property = (PropertyMacro*) (
|
||||
#if ENGINE_MINOR_VERSION >= 25 || ENGINE_MAJOR_VERSION > 4
|
||||
Function->ChildProperties
|
||||
#else
|
||||
Function->Children
|
||||
#endif
|
||||
);
|
||||
*Stack.Code != EX_EndFunctionParms; Property = (PropertyMacro*) (Property->Next))
|
||||
{
|
||||
checkfSlow(Property, TEXT("NULL Property in Function %s"), *Function->GetPathName());
|
||||
|
||||
Property->InitializeValue_InContainer(Params);
|
||||
|
||||
if ((Property->PropertyFlags & CPF_ReturnParm) != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
Stack.MostRecentPropertyAddress = nullptr;
|
||||
|
||||
if (Property->PropertyFlags & CPF_OutParm)
|
||||
{
|
||||
Stack.Step(Stack.Object, Property->ContainerPtrToValuePtr<uint8>(Params));
|
||||
|
||||
if (LastOut)
|
||||
{
|
||||
CA_SUPPRESS(6263)
|
||||
FOutParmRec* Out = (FOutParmRec*) FMemory_Alloca(sizeof(FOutParmRec));
|
||||
ensure(Stack.MostRecentPropertyAddress);
|
||||
Out->PropAddr = (Stack.MostRecentPropertyAddress != NULL) ? Stack.MostRecentPropertyAddress
|
||||
: Property->ContainerPtrToValuePtr<uint8>(Params);
|
||||
Out->Property = Property;
|
||||
|
||||
if (*LastOut)
|
||||
{
|
||||
(*LastOut)->NextOutParm = Out;
|
||||
LastOut = &(*LastOut)->NextOutParm;
|
||||
}
|
||||
else
|
||||
{
|
||||
*LastOut = Out;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Stack.Step(Stack.Object, Property->ContainerPtrToValuePtr<uint8>(Params));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (Stack.Code)
|
||||
{
|
||||
check(Stack.PeekCode() == EX_EndFunctionParms);
|
||||
Stack.SkipCode(1); // skip EX_EndFunctionParms
|
||||
}
|
||||
}
|
||||
|
||||
v8::Local<v8::Value>* Args =
|
||||
static_cast<v8::Local<v8::Value>*>(FMemory_Alloca(sizeof(v8::Local<v8::Value>) * Arguments.size()));
|
||||
FMemory::Memset(Args, 0, sizeof(v8::Local<v8::Value>) * Arguments.size());
|
||||
for (int i = 0; i < Arguments.size(); ++i)
|
||||
{
|
||||
const auto Property = Arguments[i]->Property;
|
||||
if (!CallByBP && (Property->PropertyFlags & CPF_OutParm) && Stack.OutParms) // may be fast call
|
||||
{
|
||||
FOutParmRec* Out = Stack.OutParms;
|
||||
|
||||
while (Out->Property != Property)
|
||||
{
|
||||
Out = Out->NextOutParm;
|
||||
checkSlow(Out);
|
||||
}
|
||||
Args[i] = Arguments[i]->UEToJs(Isolate, Context, Out->PropAddr, false);
|
||||
continue;
|
||||
}
|
||||
Args[i] = Arguments[i]->UEToJsInContainer(Isolate, Context, Params, false);
|
||||
}
|
||||
|
||||
v8::MaybeLocal<v8::Value> Result;
|
||||
if (UNLIKELY(SkipWorldContextInArg0))
|
||||
{
|
||||
Result = JsFunction->Call(Context, This, Arguments.size() - 1, &Args[0] + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
Result = JsFunction->Call(Context, This, Arguments.size(), Args);
|
||||
}
|
||||
|
||||
if (!Result.IsEmpty()) // empty mean exception
|
||||
{
|
||||
if (Return)
|
||||
{
|
||||
Return->JsToUE(Isolate, Context, Result.ToLocalChecked(), RESULT_PARAM, true);
|
||||
}
|
||||
|
||||
auto OutParms = NewOutParms ? NewOutParms : Stack.OutParms;
|
||||
|
||||
for (int i = 0; i < Arguments.size(); ++i)
|
||||
{
|
||||
if (Arguments[i]->IsOut())
|
||||
{
|
||||
auto OutParmRec = GetMatchOutParmRec(OutParms, Arguments[i]->Property);
|
||||
if (OutParmRec)
|
||||
{
|
||||
Arguments[i]->JsToUEOut(Isolate, Context, Args[i], OutParmRec->PropAddr, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Params && Params != Stack.Locals)
|
||||
{
|
||||
// destruct properties on the stack, except for out params since we know we didn't use that memory
|
||||
for (PropertyMacro* Destruct = Function->DestructorLink; Destruct; Destruct = Destruct->DestructorLinkNext)
|
||||
{
|
||||
if (!Destruct->HasAnyPropertyFlags(CPF_OutParm))
|
||||
{
|
||||
Destruct->DestroyValue_InContainer(Params);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool FFunctionTranslator::IsValid() const
|
||||
{
|
||||
return Function.IsValid();
|
||||
}
|
||||
|
||||
FExtensionMethodTranslator::FExtensionMethodTranslator(UFunction* InFunction) : FFunctionTranslator(InFunction, false)
|
||||
{
|
||||
TFieldIterator<PropertyMacro> It(InFunction);
|
||||
PropertyMacro* Property = *It;
|
||||
IsUObject = Property->IsA<ObjectPropertyBaseMacro>();
|
||||
Arguments[0] = FPropertyTranslator::Create(Property, true);
|
||||
}
|
||||
|
||||
v8::Local<v8::FunctionTemplate> FExtensionMethodTranslator::ToFunctionTemplate(v8::Isolate* Isolate)
|
||||
{
|
||||
return v8::FunctionTemplate::New(Isolate, CallExtension, v8::External::New(Isolate, this));
|
||||
}
|
||||
|
||||
void FExtensionMethodTranslator::CallExtension(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Isolate::Scope IsolateScope(Isolate);
|
||||
v8::HandleScope HandleScope(Isolate);
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
v8::Context::Scope ContextScope(Context);
|
||||
|
||||
FExtensionMethodTranslator* This =
|
||||
reinterpret_cast<FExtensionMethodTranslator*>((v8::Local<v8::External>::Cast(Info.Data()))->Value());
|
||||
This->CallExtension(Isolate, Context, Info);
|
||||
}
|
||||
|
||||
void FExtensionMethodTranslator::CallExtension(
|
||||
v8::Isolate* Isolate, v8::Local<v8::Context>& Context, const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
#if defined(USE_GLOBAL_PARAMS_BUFFER)
|
||||
void* Params = Buffer;
|
||||
#else
|
||||
void* Params = ParamsBufferSize > 0 ? FMemory_Alloca(ParamsBufferSize) : nullptr;
|
||||
#endif
|
||||
|
||||
if (Params)
|
||||
Function->InitializeStruct(Params);
|
||||
|
||||
if (!Arguments[0]->JsToUEInContainer(Isolate, Context, Info.Holder(), Params, false))
|
||||
{
|
||||
if (Params)
|
||||
{
|
||||
for (int i = 0; i < Arguments.size(); ++i)
|
||||
{
|
||||
if (Arguments[i]->ParamShallowCopySize == 0)
|
||||
{
|
||||
Arguments[i]->Property->DestroyValue_InContainer(Params);
|
||||
}
|
||||
}
|
||||
}
|
||||
FV8Utils::ThrowException(Isolate, "access a invalid object");
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 1; i < Arguments.size(); ++i)
|
||||
{
|
||||
if (UNLIKELY(ArgumentDefaultValues && Info[i - 1]->IsUndefined()))
|
||||
{
|
||||
Arguments[i]->Property->CopyCompleteValue_InContainer(Params, ArgumentDefaultValues);
|
||||
}
|
||||
else if (!Arguments[i]->JsToUEInContainer(Isolate, Context, Info[i - 1], Params, false))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!BindObject.IsValid())
|
||||
{
|
||||
BindObject = Function->GetOuterUClass()->GetDefaultObject();
|
||||
}
|
||||
|
||||
BindObject->UObject::ProcessEvent(Function.Get(), Params);
|
||||
|
||||
if (Return)
|
||||
{
|
||||
Info.GetReturnValue().Set(Return->UEToJsInContainer(Isolate, Context, Params));
|
||||
Return->Property->DestroyValue_InContainer(Params);
|
||||
}
|
||||
|
||||
for (int i = 1; i < Arguments.size(); ++i)
|
||||
{
|
||||
Arguments[i]->UEOutToJsInContainer(Isolate, Context, Info[i - 1], Params, false);
|
||||
}
|
||||
|
||||
// Function->HasAnyFlags()
|
||||
if (!IsUObject) // FScriptStruct, so copy back
|
||||
{
|
||||
auto StructProperty = Arguments[0]->StructProperty;
|
||||
StructProperty->CopySingleValue(FV8Utils::GetPointer(Info.Holder()), StructProperty->ContainerPtrToValuePtr<void>(Params));
|
||||
}
|
||||
|
||||
if (Params)
|
||||
{
|
||||
for (int i = 0; i < Arguments.size(); ++i)
|
||||
{
|
||||
if (Arguments[i]->ParamShallowCopySize == 0)
|
||||
{
|
||||
Arguments[i]->Property->DestroyValue_InContainer(Params);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}; // namespace PUERTS_NAMESPACE
|
||||
@@ -0,0 +1,151 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "CoreUObject.h"
|
||||
#include "PropertyTranslator.h"
|
||||
|
||||
#include "NamespaceDef.h"
|
||||
|
||||
PRAGMA_DISABLE_UNDEFINED_IDENTIFIER_WARNINGS
|
||||
#pragma warning(push, 0)
|
||||
#include "libplatform/libplatform.h"
|
||||
#include "v8.h"
|
||||
#pragma warning(pop)
|
||||
PRAGMA_ENABLE_UNDEFINED_IDENTIFIER_WARNINGS
|
||||
|
||||
namespace PUERTS_NAMESPACE
|
||||
{
|
||||
class FFunctionTranslator
|
||||
{
|
||||
public:
|
||||
explicit FFunctionTranslator(UFunction* InFunction, bool IsDelegate);
|
||||
|
||||
virtual ~FFunctionTranslator()
|
||||
{
|
||||
if (ArgumentDefaultValues)
|
||||
{
|
||||
FMemory::Free(ArgumentDefaultValues);
|
||||
}
|
||||
}
|
||||
|
||||
virtual v8::Local<v8::FunctionTemplate> ToFunctionTemplate(v8::Isolate* Isolate);
|
||||
|
||||
void CallJs(v8::Isolate* Isolate, v8::Local<v8::Context>& Context, v8::Local<v8::Function> JsFunction,
|
||||
v8::Local<v8::Value> This, void* Params);
|
||||
|
||||
void CallJs(v8::Isolate* Isolate, v8::Local<v8::Context>& Context, v8::Local<v8::Function> JsFunction,
|
||||
v8::Local<v8::Value> This, UObject* ContextObject, FFrame& Stack, void* RESULT_PARAM);
|
||||
|
||||
void Call(v8::Isolate* Isolate, v8::Local<v8::Context>& Context, const v8::FunctionCallbackInfo<v8::Value>& Info,
|
||||
std::function<void(void*)> OnCall);
|
||||
|
||||
bool IsValid() const;
|
||||
|
||||
protected:
|
||||
FORCEINLINE bool Call_ProcessParams(v8::Isolate* Isolate, v8::Local<v8::Context>& Context,
|
||||
const v8::FunctionCallbackInfo<v8::Value>& Info, void* Params, int StartPos)
|
||||
{
|
||||
if (Return)
|
||||
{
|
||||
Return->Property->InitializeValue_InContainer(Params);
|
||||
}
|
||||
|
||||
for (int i = StartPos; i < Arguments.size(); ++i)
|
||||
{
|
||||
Arguments[i]->Property->InitializeValue_InContainer(Params);
|
||||
|
||||
if (UNLIKELY(ArgumentDefaultValues && Info[i - StartPos]->IsUndefined()))
|
||||
{
|
||||
Arguments[i]->Property->CopyCompleteValue_InContainer(Params, ArgumentDefaultValues);
|
||||
}
|
||||
else if (!Arguments[i]->JsToUEInContainer(Isolate, Context, Info[i - StartPos], Params, false))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
FORCEINLINE void Call_ProcessReturnAndOutParams(v8::Isolate* Isolate, v8::Local<v8::Context>& Context,
|
||||
const v8::FunctionCallbackInfo<v8::Value>& Info, void* Params, int StartPos)
|
||||
{
|
||||
if (Return)
|
||||
{
|
||||
Info.GetReturnValue().Set(Return->UEToJsInContainer(Isolate, Context, Params));
|
||||
Return->Property->DestroyValue_InContainer(Params);
|
||||
}
|
||||
|
||||
for (int i = StartPos; i < Arguments.size(); ++i)
|
||||
{
|
||||
Arguments[i]->UEOutToJsInContainer(Isolate, Context, Info[i - StartPos], Params, false);
|
||||
if (Arguments[i]->ParamShallowCopySize == 0)
|
||||
{
|
||||
Arguments[i]->Property->DestroyValue_InContainer(Params);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::unique_ptr<FPropertyTranslator>> Arguments;
|
||||
|
||||
std::unique_ptr<FPropertyTranslator> Return;
|
||||
|
||||
TWeakObjectPtr<UFunction> Function;
|
||||
|
||||
bool IsInterfaceFunction;
|
||||
|
||||
TWeakObjectPtr<UObject> BindObject;
|
||||
|
||||
bool IsStatic;
|
||||
|
||||
bool SkipWorldContextInArg0;
|
||||
|
||||
uint32 ParamsBufferSize;
|
||||
|
||||
void* ArgumentDefaultValues;
|
||||
#if WITH_EDITOR
|
||||
FName FunctionName;
|
||||
#endif
|
||||
private:
|
||||
static void Call(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
|
||||
void Call(v8::Isolate* Isolate, v8::Local<v8::Context>& Context, const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
|
||||
void SlowCall(v8::Isolate* Isolate, v8::Local<v8::Context>& Context, const v8::FunctionCallbackInfo<v8::Value>& Info,
|
||||
UObject* CallObject, UFunction* CallFunction, void* Params);
|
||||
|
||||
void FastCall(v8::Isolate* Isolate, v8::Local<v8::Context>& Context, const v8::FunctionCallbackInfo<v8::Value>& Info,
|
||||
UObject* CallObject, UFunction* CallFunction, void* Params);
|
||||
|
||||
void Init(UFunction* InFunction, bool IsDelegate);
|
||||
|
||||
friend class FStructWrapper;
|
||||
friend class FJsEnvImpl;
|
||||
};
|
||||
|
||||
class FExtensionMethodTranslator : public FFunctionTranslator
|
||||
{
|
||||
public:
|
||||
explicit FExtensionMethodTranslator(UFunction* InFunction);
|
||||
|
||||
v8::Local<v8::FunctionTemplate> ToFunctionTemplate(v8::Isolate* Isolate) override;
|
||||
|
||||
private:
|
||||
static void CallExtension(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
|
||||
void CallExtension(v8::Isolate* Isolate, v8::Local<v8::Context>& Context, const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
|
||||
bool IsUObject;
|
||||
};
|
||||
} // namespace PUERTS_NAMESPACE
|
||||
@@ -0,0 +1,754 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// gen by puerts gen tools
|
||||
|
||||
#include "GenHeaders.h"
|
||||
#include "CoreMinimal.h"
|
||||
#include "DataTransfer.h"
|
||||
#include "JSClassRegister.h"
|
||||
|
||||
// <SourceLocation file 'D:\\Program Files\\Epic Games\\UE_4.24\\Engine\\Source\\Runtime\\Core\\Public\\Math/Box2D.h', line 111,
|
||||
// column 22> unsupported method : operator+= FBox2D &(const FVector2D &) __attribute__((thiscall))
|
||||
|
||||
// <SourceLocation file 'D:\\Program Files\\Epic Games\\UE_4.24\\Engine\\Source\\Runtime\\Core\\Public\\Math/Box2D.h', line 130,
|
||||
// column 22> unsupported method : operator+= FBox2D &(const FBox2D &) __attribute__((thiscall))
|
||||
|
||||
static void* _FBox2DNew_(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
if (Info.Length() == 0)
|
||||
{
|
||||
if (true)
|
||||
{
|
||||
FBox2D* Obj = new FBox2D();
|
||||
|
||||
// UE_LOG(LogTemp, Warning, TEXT("_FBox2DNew_:%p"), Obj);
|
||||
return Obj;
|
||||
}
|
||||
}
|
||||
if (Info.Length() == 1)
|
||||
{
|
||||
if (Info[0]->IsNumber())
|
||||
{
|
||||
EForceInit Arg0 = EForceInit(Info[0]->ToInt32(Context).ToLocalChecked()->Value());
|
||||
FBox2D* Obj = new FBox2D(Arg0);
|
||||
|
||||
// UE_LOG(LogTemp, Warning, TEXT("_FBox2DNew_:%p"), Obj);
|
||||
return Obj;
|
||||
}
|
||||
}
|
||||
if (Info.Length() == 2)
|
||||
{
|
||||
if (Info[0]->IsObject() &&
|
||||
|
||||
PUERTS_NAMESPACE::DataTransfer::IsInstanceOf<FVector2D>(Isolate, Info[0]->ToObject(Context).ToLocalChecked()) &&
|
||||
Info[1]->IsObject() &&
|
||||
|
||||
PUERTS_NAMESPACE::DataTransfer::IsInstanceOf<FVector2D>(Isolate, Info[1]->ToObject(Context).ToLocalChecked()))
|
||||
{
|
||||
const FVector2D* Arg0 =
|
||||
PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FVector2D>(Info[0]->ToObject(Context).ToLocalChecked());
|
||||
const FVector2D* Arg1 =
|
||||
PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FVector2D>(Info[1]->ToObject(Context).ToLocalChecked());
|
||||
FBox2D* Obj = new FBox2D(*Arg0, *Arg1);
|
||||
|
||||
// UE_LOG(LogTemp, Warning, TEXT("_FBox2DNew_:%p"), Obj);
|
||||
return Obj;
|
||||
}
|
||||
}
|
||||
if (Info.Length() == 2)
|
||||
{
|
||||
if (Info[0]->IsObject() &&
|
||||
|
||||
PUERTS_NAMESPACE::DataTransfer::IsInstanceOf<FVector2D>(Isolate, Info[0]->ToObject(Context).ToLocalChecked()) &&
|
||||
Info[1]->IsNumber())
|
||||
{
|
||||
const FVector2D* Arg0 =
|
||||
PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FVector2D>(Info[0]->ToObject(Context).ToLocalChecked());
|
||||
const int32 Arg1 = Info[1]->ToInteger(Context).ToLocalChecked()->Value();
|
||||
FBox2D* Obj = new FBox2D(Arg0, Arg1);
|
||||
|
||||
// UE_LOG(LogTemp, Warning, TEXT("_FBox2DNew_:%p"), Obj);
|
||||
return Obj;
|
||||
}
|
||||
}
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "Invalid argument!");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static void _FBox2DDelete_(void* Ptr, void* ClassData, void* EnvData)
|
||||
{
|
||||
FBox2D* Self = static_cast<FBox2D*>(Ptr);
|
||||
// UE_LOG(LogTemp, Warning, TEXT("_FBox2DDelete_:%p"), Self);
|
||||
delete Self;
|
||||
}
|
||||
static void FBox2DM_op_Equality(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
if (Info.Length() == 1)
|
||||
{
|
||||
if (Info[0]->IsObject() &&
|
||||
|
||||
PUERTS_NAMESPACE::DataTransfer::IsInstanceOf<FBox2D>(Isolate, Info[0]->ToObject(Context).ToLocalChecked()))
|
||||
{
|
||||
const FBox2D* Arg0 =
|
||||
PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FBox2D>(Info[0]->ToObject(Context).ToLocalChecked());
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FBox2D>(Info.Holder());
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(
|
||||
Isolate, "[FBox2D::M_op_Equality] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
auto MethodResult = Self->operator==(*Arg0);
|
||||
auto V8Result = v8::Boolean::New(Isolate, MethodResult);
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "Invalid argument!");
|
||||
}
|
||||
|
||||
static void FBox2DM_op_Inequality(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
if (Info.Length() == 1)
|
||||
{
|
||||
if (Info[0]->IsObject() &&
|
||||
|
||||
PUERTS_NAMESPACE::DataTransfer::IsInstanceOf<FBox2D>(Isolate, Info[0]->ToObject(Context).ToLocalChecked()))
|
||||
{
|
||||
const FBox2D* Arg0 =
|
||||
PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FBox2D>(Info[0]->ToObject(Context).ToLocalChecked());
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FBox2D>(Info.Holder());
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(
|
||||
Isolate, "[FBox2D::M_op_Inequality] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
auto MethodResult = Self->operator!=(*Arg0);
|
||||
auto V8Result = v8::Boolean::New(Isolate, MethodResult);
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "Invalid argument!");
|
||||
}
|
||||
|
||||
static void FBox2DM_op_Addition(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
if (Info.Length() == 1)
|
||||
{
|
||||
if (Info[0]->IsObject() &&
|
||||
|
||||
PUERTS_NAMESPACE::DataTransfer::IsInstanceOf<FVector2D>(Isolate, Info[0]->ToObject(Context).ToLocalChecked()))
|
||||
{
|
||||
const FVector2D* Arg0 =
|
||||
PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FVector2D>(Info[0]->ToObject(Context).ToLocalChecked());
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FBox2D>(Info.Holder());
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(
|
||||
Isolate, "[FBox2D::M_op_Addition] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
auto MethodResult = Self->operator+(*Arg0);
|
||||
void* Ptr = new FBox2D(MethodResult);
|
||||
|
||||
auto V8Result = PUERTS_NAMESPACE::DataTransfer::FindOrAddStruct<FBox2D>(Isolate, Context, Ptr, false);
|
||||
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (Info.Length() == 1)
|
||||
{
|
||||
if (Info[0]->IsObject() &&
|
||||
|
||||
PUERTS_NAMESPACE::DataTransfer::IsInstanceOf<FBox2D>(Isolate, Info[0]->ToObject(Context).ToLocalChecked()))
|
||||
{
|
||||
const FBox2D* Arg0 =
|
||||
PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FBox2D>(Info[0]->ToObject(Context).ToLocalChecked());
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FBox2D>(Info.Holder());
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(
|
||||
Isolate, "[FBox2D::M_op_Addition] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
auto MethodResult = Self->operator+(*Arg0);
|
||||
void* Ptr = new FBox2D(MethodResult);
|
||||
|
||||
auto V8Result = PUERTS_NAMESPACE::DataTransfer::FindOrAddStruct<FBox2D>(Isolate, Context, Ptr, false);
|
||||
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "Invalid argument!");
|
||||
}
|
||||
|
||||
static void FBox2DM_set_Item(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
if (Info.Length() == 1)
|
||||
{
|
||||
if (Info[0]->IsNumber())
|
||||
{
|
||||
int32 Arg0 = Info[0]->ToInteger(Context).ToLocalChecked()->Value();
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FBox2D>(Info.Holder());
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(
|
||||
Isolate, "[FBox2D::M_set_Item] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
Self->operator[](Arg0);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "Invalid argument!");
|
||||
}
|
||||
|
||||
static void FBox2DM_ComputeSquaredDistanceToPoint(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
if (Info.Length() == 1)
|
||||
{
|
||||
if (Info[0]->IsObject() &&
|
||||
|
||||
PUERTS_NAMESPACE::DataTransfer::IsInstanceOf<FVector2D>(Isolate, Info[0]->ToObject(Context).ToLocalChecked()))
|
||||
{
|
||||
const FVector2D* Arg0 =
|
||||
PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FVector2D>(Info[0]->ToObject(Context).ToLocalChecked());
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FBox2D>(Info.Holder());
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(
|
||||
Isolate, "[FBox2D::M_ComputeSquaredDistanceToPoint] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
auto MethodResult = Self->ComputeSquaredDistanceToPoint(*Arg0);
|
||||
auto V8Result = v8::Number::New(Isolate, MethodResult);
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "Invalid argument!");
|
||||
}
|
||||
|
||||
static void FBox2DM_ExpandBy(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
if (Info.Length() == 1)
|
||||
{
|
||||
if (Info[0]->IsNumber())
|
||||
{
|
||||
const float Arg0 = Info[0]->ToNumber(Context).ToLocalChecked()->Value();
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FBox2D>(Info.Holder());
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(
|
||||
Isolate, "[FBox2D::M_ExpandBy] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
auto MethodResult = Self->ExpandBy(Arg0);
|
||||
void* Ptr = new FBox2D(MethodResult);
|
||||
|
||||
auto V8Result = PUERTS_NAMESPACE::DataTransfer::FindOrAddStruct<FBox2D>(Isolate, Context, Ptr, false);
|
||||
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "Invalid argument!");
|
||||
}
|
||||
|
||||
static void FBox2DM_GetArea(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
if (Info.Length() == 0)
|
||||
{
|
||||
if (true)
|
||||
{
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FBox2D>(Info.Holder());
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(
|
||||
Isolate, "[FBox2D::M_GetArea] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
auto MethodResult = Self->GetArea();
|
||||
auto V8Result = v8::Number::New(Isolate, MethodResult);
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "Invalid argument!");
|
||||
}
|
||||
|
||||
static void FBox2DM_GetCenter(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
if (Info.Length() == 0)
|
||||
{
|
||||
if (true)
|
||||
{
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FBox2D>(Info.Holder());
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(
|
||||
Isolate, "[FBox2D::M_GetCenter] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
auto MethodResult = Self->GetCenter();
|
||||
void* Ptr = new FVector2D(MethodResult);
|
||||
|
||||
auto V8Result = PUERTS_NAMESPACE::DataTransfer::FindOrAddStruct<FVector2D>(Isolate, Context, Ptr, false);
|
||||
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "Invalid argument!");
|
||||
}
|
||||
|
||||
static void FBox2DM_GetCenterAndExtents(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
if (Info.Length() == 2)
|
||||
{
|
||||
if (Info[0]->IsObject() && PUERTS_NAMESPACE::DataTransfer::UnRef(Isolate, Info[0])->IsObject() &&
|
||||
|
||||
PUERTS_NAMESPACE::DataTransfer::IsInstanceOf<FVector2D>(
|
||||
Isolate, PUERTS_NAMESPACE::DataTransfer::UnRef(Isolate, Info[0])->ToObject(Context).ToLocalChecked()) &&
|
||||
Info[1]->IsObject() && PUERTS_NAMESPACE::DataTransfer::UnRef(Isolate, Info[1])->IsObject() &&
|
||||
|
||||
PUERTS_NAMESPACE::DataTransfer::IsInstanceOf<FVector2D>(
|
||||
Isolate, PUERTS_NAMESPACE::DataTransfer::UnRef(Isolate, Info[1])->ToObject(Context).ToLocalChecked()))
|
||||
{
|
||||
FVector2D* Arg0 = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FVector2D>(
|
||||
PUERTS_NAMESPACE::DataTransfer::UnRef(Isolate, Info[0])->ToObject(Context).ToLocalChecked());
|
||||
FVector2D* Arg1 = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FVector2D>(
|
||||
PUERTS_NAMESPACE::DataTransfer::UnRef(Isolate, Info[1])->ToObject(Context).ToLocalChecked());
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FBox2D>(Info.Holder());
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(
|
||||
Isolate, "[FBox2D::M_GetCenterAndExtents] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
Self->GetCenterAndExtents(*Arg0, *Arg1);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "Invalid argument!");
|
||||
}
|
||||
|
||||
static void FBox2DM_GetClosestPointTo(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
if (Info.Length() == 1)
|
||||
{
|
||||
if (Info[0]->IsObject() &&
|
||||
|
||||
PUERTS_NAMESPACE::DataTransfer::IsInstanceOf<FVector2D>(Isolate, Info[0]->ToObject(Context).ToLocalChecked()))
|
||||
{
|
||||
const FVector2D* Arg0 =
|
||||
PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FVector2D>(Info[0]->ToObject(Context).ToLocalChecked());
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FBox2D>(Info.Holder());
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(
|
||||
Isolate, "[FBox2D::M_GetClosestPointTo] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
auto MethodResult = Self->GetClosestPointTo(*Arg0);
|
||||
void* Ptr = new FVector2D(MethodResult);
|
||||
|
||||
auto V8Result = PUERTS_NAMESPACE::DataTransfer::FindOrAddStruct<FVector2D>(Isolate, Context, Ptr, false);
|
||||
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "Invalid argument!");
|
||||
}
|
||||
|
||||
static void FBox2DM_GetExtent(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
if (Info.Length() == 0)
|
||||
{
|
||||
if (true)
|
||||
{
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FBox2D>(Info.Holder());
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(
|
||||
Isolate, "[FBox2D::M_GetExtent] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
auto MethodResult = Self->GetExtent();
|
||||
void* Ptr = new FVector2D(MethodResult);
|
||||
|
||||
auto V8Result = PUERTS_NAMESPACE::DataTransfer::FindOrAddStruct<FVector2D>(Isolate, Context, Ptr, false);
|
||||
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "Invalid argument!");
|
||||
}
|
||||
|
||||
static void FBox2DM_GetSize(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
if (Info.Length() == 0)
|
||||
{
|
||||
if (true)
|
||||
{
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FBox2D>(Info.Holder());
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(
|
||||
Isolate, "[FBox2D::M_GetSize] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
auto MethodResult = Self->GetSize();
|
||||
void* Ptr = new FVector2D(MethodResult);
|
||||
|
||||
auto V8Result = PUERTS_NAMESPACE::DataTransfer::FindOrAddStruct<FVector2D>(Isolate, Context, Ptr, false);
|
||||
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "Invalid argument!");
|
||||
}
|
||||
|
||||
static void FBox2DM_Init(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
if (Info.Length() == 0)
|
||||
{
|
||||
if (true)
|
||||
{
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FBox2D>(Info.Holder());
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "[FBox2D::M_Init] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
Self->Init();
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "Invalid argument!");
|
||||
}
|
||||
|
||||
static void FBox2DM_Intersect(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
if (Info.Length() == 1)
|
||||
{
|
||||
if (Info[0]->IsObject() &&
|
||||
|
||||
PUERTS_NAMESPACE::DataTransfer::IsInstanceOf<FBox2D>(Isolate, Info[0]->ToObject(Context).ToLocalChecked()))
|
||||
{
|
||||
const FBox2D* Arg0 =
|
||||
PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FBox2D>(Info[0]->ToObject(Context).ToLocalChecked());
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FBox2D>(Info.Holder());
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(
|
||||
Isolate, "[FBox2D::M_Intersect] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
auto MethodResult = Self->Intersect(*Arg0);
|
||||
auto V8Result = v8::Boolean::New(Isolate, MethodResult);
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "Invalid argument!");
|
||||
}
|
||||
|
||||
static void FBox2DM_IsInside(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
if (Info.Length() == 1)
|
||||
{
|
||||
if (Info[0]->IsObject() &&
|
||||
|
||||
PUERTS_NAMESPACE::DataTransfer::IsInstanceOf<FVector2D>(Isolate, Info[0]->ToObject(Context).ToLocalChecked()))
|
||||
{
|
||||
const FVector2D* Arg0 =
|
||||
PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FVector2D>(Info[0]->ToObject(Context).ToLocalChecked());
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FBox2D>(Info.Holder());
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(
|
||||
Isolate, "[FBox2D::M_IsInside] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
auto MethodResult = Self->IsInside(*Arg0);
|
||||
auto V8Result = v8::Boolean::New(Isolate, MethodResult);
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (Info.Length() == 1)
|
||||
{
|
||||
if (Info[0]->IsObject() &&
|
||||
|
||||
PUERTS_NAMESPACE::DataTransfer::IsInstanceOf<FBox2D>(Isolate, Info[0]->ToObject(Context).ToLocalChecked()))
|
||||
{
|
||||
const FBox2D* Arg0 =
|
||||
PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FBox2D>(Info[0]->ToObject(Context).ToLocalChecked());
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FBox2D>(Info.Holder());
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(
|
||||
Isolate, "[FBox2D::M_IsInside] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
auto MethodResult = Self->IsInside(*Arg0);
|
||||
auto V8Result = v8::Boolean::New(Isolate, MethodResult);
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "Invalid argument!");
|
||||
}
|
||||
|
||||
static void FBox2DM_ShiftBy(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
if (Info.Length() == 1)
|
||||
{
|
||||
if (Info[0]->IsObject() &&
|
||||
|
||||
PUERTS_NAMESPACE::DataTransfer::IsInstanceOf<FVector2D>(Isolate, Info[0]->ToObject(Context).ToLocalChecked()))
|
||||
{
|
||||
const FVector2D* Arg0 =
|
||||
PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FVector2D>(Info[0]->ToObject(Context).ToLocalChecked());
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FBox2D>(Info.Holder());
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(
|
||||
Isolate, "[FBox2D::M_ShiftBy] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
auto MethodResult = Self->ShiftBy(*Arg0);
|
||||
void* Ptr = new FBox2D(MethodResult);
|
||||
|
||||
auto V8Result = PUERTS_NAMESPACE::DataTransfer::FindOrAddStruct<FBox2D>(Isolate, Context, Ptr, false);
|
||||
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "Invalid argument!");
|
||||
}
|
||||
|
||||
static void FBox2DM_ToString(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
if (Info.Length() == 0)
|
||||
{
|
||||
if (true)
|
||||
{
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FBox2D>(Info.Holder());
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(
|
||||
Isolate, "[FBox2D::M_ToString] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
auto MethodResult = Self->ToString();
|
||||
auto V8Result =
|
||||
v8::String::NewFromUtf8(Isolate, TCHAR_TO_UTF8(*MethodResult), v8::NewStringType::kNormal).ToLocalChecked();
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "Invalid argument!");
|
||||
}
|
||||
|
||||
static void _FBox2DMinGet_(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FBox2D>(Info.Holder());
|
||||
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "[FBox2D::Min] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
|
||||
auto V8Result = PUERTS_NAMESPACE::DataTransfer::FindOrAddStruct<FVector2D>(Isolate, Context, &(Self->Min), true);
|
||||
|
||||
PUERTS_NAMESPACE::DataTransfer::LinkOuter<FBox2D, FVector2D>(Context, Info.Holder(), V8Result);
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
}
|
||||
static void _FBox2DMinSet_(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FBox2D>(Info.Holder());
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "[FBox2D::Min] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
auto Value = Info[0];
|
||||
|
||||
Self->Min = *PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FVector2D>(Value->ToObject(Context).ToLocalChecked());
|
||||
}
|
||||
static void _FBox2DMaxGet_(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FBox2D>(Info.Holder());
|
||||
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "[FBox2D::Max] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
|
||||
auto V8Result = PUERTS_NAMESPACE::DataTransfer::FindOrAddStruct<FVector2D>(Isolate, Context, &(Self->Max), true);
|
||||
|
||||
PUERTS_NAMESPACE::DataTransfer::LinkOuter<FBox2D, FVector2D>(Context, Info.Holder(), V8Result);
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
}
|
||||
static void _FBox2DMaxSet_(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FBox2D>(Info.Holder());
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "[FBox2D::Max] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
auto Value = Info[0];
|
||||
|
||||
Self->Max = *PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FVector2D>(Value->ToObject(Context).ToLocalChecked());
|
||||
}
|
||||
static void _FBox2DbIsValidGet_(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FBox2D>(Info.Holder());
|
||||
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "[FBox2D::bIsValid] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
|
||||
auto V8Result = v8::Boolean::New(Isolate, Self->bIsValid);
|
||||
PUERTS_NAMESPACE::DataTransfer::LinkOuter<FBox2D, bool>(Context, Info.Holder(), V8Result);
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
}
|
||||
static void _FBox2DbIsValidSet_(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FBox2D>(Info.Holder());
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "[FBox2D::bIsValid] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
auto Value = Info[0];
|
||||
|
||||
Self->bIsValid = Value->ToBoolean(Isolate)->Value();
|
||||
}
|
||||
|
||||
struct AutoRegisterForFBox2D
|
||||
{
|
||||
AutoRegisterForFBox2D()
|
||||
{
|
||||
PUERTS_NAMESPACE::JSClassDefinition Def = JSClassEmptyDefinition;
|
||||
|
||||
static PUERTS_NAMESPACE::JSPropertyInfo Properties[] = {{"Min", _FBox2DMinGet_, _FBox2DMinSet_},
|
||||
{"Max", _FBox2DMaxGet_, _FBox2DMaxSet_}, {"bIsValid", _FBox2DbIsValidGet_, _FBox2DbIsValidSet_}, {0, 0, 0}};
|
||||
|
||||
static PUERTS_NAMESPACE::JSFunctionInfo Methods[] = {{"op_Equality", FBox2DM_op_Equality},
|
||||
{"op_Inequality", FBox2DM_op_Inequality}, {"op_Addition", FBox2DM_op_Addition}, {"set_Item", FBox2DM_set_Item},
|
||||
{"ComputeSquaredDistanceToPoint", FBox2DM_ComputeSquaredDistanceToPoint}, {"ExpandBy", FBox2DM_ExpandBy},
|
||||
{"GetArea", FBox2DM_GetArea}, {"GetCenter", FBox2DM_GetCenter}, {"GetCenterAndExtents", FBox2DM_GetCenterAndExtents},
|
||||
{"GetClosestPointTo", FBox2DM_GetClosestPointTo}, {"GetExtent", FBox2DM_GetExtent}, {"GetSize", FBox2DM_GetSize},
|
||||
{"Init", FBox2DM_Init}, {"Intersect", FBox2DM_Intersect}, {"IsInside", FBox2DM_IsInside}, {"ShiftBy", FBox2DM_ShiftBy},
|
||||
{"ToString", FBox2DM_ToString}, {0, 0}};
|
||||
|
||||
static PUERTS_NAMESPACE::JSFunctionInfo Functions[] = {{0, 0}};
|
||||
|
||||
Def.UETypeName = "Box2D";
|
||||
|
||||
Def.SetInitialize(_FBox2DNew_);
|
||||
Def.Finalize = _FBox2DDelete_;
|
||||
Def.Properties = Properties;
|
||||
Def.Methods = Methods;
|
||||
Def.Functions = Functions;
|
||||
|
||||
PUERTS_NAMESPACE::RegisterJSClass(Def);
|
||||
}
|
||||
};
|
||||
|
||||
AutoRegisterForFBox2D _AutoRegisterForFBox2D_;
|
||||
@@ -0,0 +1,560 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// gen by puerts gen tools
|
||||
|
||||
#include "GenHeaders.h"
|
||||
#include "CoreMinimal.h"
|
||||
#include "DataTransfer.h"
|
||||
#include "JSClassRegister.h"
|
||||
|
||||
// <SourceLocation file 'D:\\Program Files\\Epic Games\\UE_4.24\\Engine\\Source\\Runtime\\Core\\Public\\Math/Color.h', line 483,
|
||||
// column 19> unsupported method : operator+= void (const FColor &) __attribute__((thiscall))
|
||||
|
||||
static void* _FColorNew_(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
if (Info.Length() == 0)
|
||||
{
|
||||
if (true)
|
||||
{
|
||||
FColor* Obj = new FColor();
|
||||
|
||||
// UE_LOG(LogTemp, Warning, TEXT("_FColorNew_:%p"), Obj);
|
||||
return Obj;
|
||||
}
|
||||
}
|
||||
if (Info.Length() == 1)
|
||||
{
|
||||
if (Info[0]->IsNumber())
|
||||
{
|
||||
EForceInit Arg0 = EForceInit(Info[0]->ToInt32(Context).ToLocalChecked()->Value());
|
||||
FColor* Obj = new FColor(Arg0);
|
||||
|
||||
// UE_LOG(LogTemp, Warning, TEXT("_FColorNew_:%p"), Obj);
|
||||
return Obj;
|
||||
}
|
||||
}
|
||||
if (Info.Length() == 4)
|
||||
{
|
||||
if (Info[0]->IsNumber() && Info[1]->IsNumber() && Info[2]->IsNumber() && Info[3]->IsNumber())
|
||||
{
|
||||
uint8 Arg0 = Info[0]->ToInteger(Context).ToLocalChecked()->Value();
|
||||
uint8 Arg1 = Info[1]->ToInteger(Context).ToLocalChecked()->Value();
|
||||
uint8 Arg2 = Info[2]->ToInteger(Context).ToLocalChecked()->Value();
|
||||
uint8 Arg3 = Info[3]->ToInteger(Context).ToLocalChecked()->Value();
|
||||
FColor* Obj = new FColor(Arg0, Arg1, Arg2, Arg3);
|
||||
|
||||
// UE_LOG(LogTemp, Warning, TEXT("_FColorNew_:%p"), Obj);
|
||||
return Obj;
|
||||
}
|
||||
}
|
||||
if (Info.Length() == 1)
|
||||
{
|
||||
if (Info[0]->IsNumber())
|
||||
{
|
||||
uint32 Arg0 = Info[0]->ToInteger(Context).ToLocalChecked()->Value();
|
||||
FColor* Obj = new FColor(Arg0);
|
||||
|
||||
// UE_LOG(LogTemp, Warning, TEXT("_FColorNew_:%p"), Obj);
|
||||
return Obj;
|
||||
}
|
||||
}
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "Invalid argument!");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static void _FColorDelete_(void* Ptr, void* ClassData, void* EnvData)
|
||||
{
|
||||
FColor* Self = static_cast<FColor*>(Ptr);
|
||||
// UE_LOG(LogTemp, Warning, TEXT("_FColorDelete_:%p"), Self);
|
||||
delete Self;
|
||||
}
|
||||
static void FColorM_DWColor(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
if (Info.Length() == 0)
|
||||
{
|
||||
if (true)
|
||||
{
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FColor>(Info.Holder());
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(
|
||||
Isolate, "[FColor::M_DWColor] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
auto MethodResult = Self->DWColor();
|
||||
auto V8Result = v8::Integer::New(Isolate, MethodResult);
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (Info.Length() == 0)
|
||||
{
|
||||
if (true)
|
||||
{
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FColor>(Info.Holder());
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(
|
||||
Isolate, "[FColor::M_DWColor] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
auto MethodResult = Self->DWColor();
|
||||
auto V8Result = v8::Integer::New(Isolate, MethodResult);
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "Invalid argument!");
|
||||
}
|
||||
|
||||
static void FColorM_op_Equality(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
if (Info.Length() == 1)
|
||||
{
|
||||
if (Info[0]->IsObject() &&
|
||||
|
||||
PUERTS_NAMESPACE::DataTransfer::IsInstanceOf<FColor>(Isolate, Info[0]->ToObject(Context).ToLocalChecked()))
|
||||
{
|
||||
const FColor* Arg0 =
|
||||
PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FColor>(Info[0]->ToObject(Context).ToLocalChecked());
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FColor>(Info.Holder());
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(
|
||||
Isolate, "[FColor::M_op_Equality] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
auto MethodResult = Self->operator==(*Arg0);
|
||||
auto V8Result = v8::Boolean::New(Isolate, MethodResult);
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "Invalid argument!");
|
||||
}
|
||||
|
||||
static void FColorM_op_Inequality(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
if (Info.Length() == 1)
|
||||
{
|
||||
if (Info[0]->IsObject() &&
|
||||
|
||||
PUERTS_NAMESPACE::DataTransfer::IsInstanceOf<FColor>(Isolate, Info[0]->ToObject(Context).ToLocalChecked()))
|
||||
{
|
||||
const FColor* Arg0 =
|
||||
PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FColor>(Info[0]->ToObject(Context).ToLocalChecked());
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FColor>(Info.Holder());
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(
|
||||
Isolate, "[FColor::M_op_Inequality] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
auto MethodResult = Self->operator!=(*Arg0);
|
||||
auto V8Result = v8::Boolean::New(Isolate, MethodResult);
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "Invalid argument!");
|
||||
}
|
||||
|
||||
static void FColorM_FromRGBE(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
if (Info.Length() == 0)
|
||||
{
|
||||
if (true)
|
||||
{
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FColor>(Info.Holder());
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(
|
||||
Isolate, "[FColor::M_FromRGBE] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
auto MethodResult = Self->FromRGBE();
|
||||
void* Ptr = new FLinearColor(MethodResult);
|
||||
|
||||
auto V8Result = PUERTS_NAMESPACE::DataTransfer::FindOrAddStruct<FLinearColor>(Isolate, Context, Ptr, false);
|
||||
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "Invalid argument!");
|
||||
}
|
||||
|
||||
static void FColorS_FromHex(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
if (Info.Length() == 1)
|
||||
{
|
||||
if (Info[0]->IsString())
|
||||
{
|
||||
const FString Arg0 = UTF8_TO_TCHAR(*(v8::String::Utf8Value(Isolate, Info[0])));
|
||||
auto MethodResult = FColor::FromHex(Arg0);
|
||||
void* Ptr = new FColor(MethodResult);
|
||||
|
||||
auto V8Result = PUERTS_NAMESPACE::DataTransfer::FindOrAddStruct<FColor>(Isolate, Context, Ptr, false);
|
||||
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "Invalid argument!");
|
||||
}
|
||||
|
||||
static void FColorS_MakeRandomColor(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
if (Info.Length() == 0)
|
||||
{
|
||||
if (true)
|
||||
{
|
||||
auto MethodResult = FColor::MakeRandomColor();
|
||||
void* Ptr = new FColor(MethodResult);
|
||||
|
||||
auto V8Result = PUERTS_NAMESPACE::DataTransfer::FindOrAddStruct<FColor>(Isolate, Context, Ptr, false);
|
||||
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "Invalid argument!");
|
||||
}
|
||||
|
||||
static void FColorS_MakeRedToGreenColorFromScalar(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
if (Info.Length() == 1)
|
||||
{
|
||||
if (Info[0]->IsNumber())
|
||||
{
|
||||
float Arg0 = Info[0]->ToNumber(Context).ToLocalChecked()->Value();
|
||||
auto MethodResult = FColor::MakeRedToGreenColorFromScalar(Arg0);
|
||||
void* Ptr = new FColor(MethodResult);
|
||||
|
||||
auto V8Result = PUERTS_NAMESPACE::DataTransfer::FindOrAddStruct<FColor>(Isolate, Context, Ptr, false);
|
||||
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "Invalid argument!");
|
||||
}
|
||||
|
||||
static void FColorS_MakeFromColorTemperature(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
if (Info.Length() == 1)
|
||||
{
|
||||
if (Info[0]->IsNumber())
|
||||
{
|
||||
float Arg0 = Info[0]->ToNumber(Context).ToLocalChecked()->Value();
|
||||
auto MethodResult = FColor::MakeFromColorTemperature(Arg0);
|
||||
void* Ptr = new FColor(MethodResult);
|
||||
|
||||
auto V8Result = PUERTS_NAMESPACE::DataTransfer::FindOrAddStruct<FColor>(Isolate, Context, Ptr, false);
|
||||
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "Invalid argument!");
|
||||
}
|
||||
|
||||
static void FColorM_WithAlpha(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
if (Info.Length() == 1)
|
||||
{
|
||||
if (Info[0]->IsNumber())
|
||||
{
|
||||
uint8 Arg0 = Info[0]->ToInteger(Context).ToLocalChecked()->Value();
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FColor>(Info.Holder());
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(
|
||||
Isolate, "[FColor::M_WithAlpha] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
auto MethodResult = Self->WithAlpha(Arg0);
|
||||
void* Ptr = new FColor(MethodResult);
|
||||
|
||||
auto V8Result = PUERTS_NAMESPACE::DataTransfer::FindOrAddStruct<FColor>(Isolate, Context, Ptr, false);
|
||||
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "Invalid argument!");
|
||||
}
|
||||
|
||||
static void FColorM_ReinterpretAsLinear(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
if (Info.Length() == 0)
|
||||
{
|
||||
if (true)
|
||||
{
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FColor>(Info.Holder());
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(
|
||||
Isolate, "[FColor::M_ReinterpretAsLinear] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
auto MethodResult = Self->ReinterpretAsLinear();
|
||||
void* Ptr = new FLinearColor(MethodResult);
|
||||
|
||||
auto V8Result = PUERTS_NAMESPACE::DataTransfer::FindOrAddStruct<FLinearColor>(Isolate, Context, Ptr, false);
|
||||
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "Invalid argument!");
|
||||
}
|
||||
|
||||
static void FColorM_ToHex(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
if (Info.Length() == 0)
|
||||
{
|
||||
if (true)
|
||||
{
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FColor>(Info.Holder());
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "[FColor::M_ToHex] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
auto MethodResult = Self->ToHex();
|
||||
auto V8Result =
|
||||
v8::String::NewFromUtf8(Isolate, TCHAR_TO_UTF8(*MethodResult), v8::NewStringType::kNormal).ToLocalChecked();
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "Invalid argument!");
|
||||
}
|
||||
|
||||
static void FColorM_ToString(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
if (Info.Length() == 0)
|
||||
{
|
||||
if (true)
|
||||
{
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FColor>(Info.Holder());
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(
|
||||
Isolate, "[FColor::M_ToString] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
auto MethodResult = Self->ToString();
|
||||
auto V8Result =
|
||||
v8::String::NewFromUtf8(Isolate, TCHAR_TO_UTF8(*MethodResult), v8::NewStringType::kNormal).ToLocalChecked();
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "Invalid argument!");
|
||||
}
|
||||
|
||||
static void FColorM_InitFromString(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
if (Info.Length() == 1)
|
||||
{
|
||||
if (Info[0]->IsString())
|
||||
{
|
||||
const FString Arg0 = UTF8_TO_TCHAR(*(v8::String::Utf8Value(Isolate, Info[0])));
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FColor>(Info.Holder());
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(
|
||||
Isolate, "[FColor::M_InitFromString] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
auto MethodResult = Self->InitFromString(Arg0);
|
||||
auto V8Result = v8::Boolean::New(Isolate, MethodResult);
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "Invalid argument!");
|
||||
}
|
||||
|
||||
static void FColorM_ToPackedARGB(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
if (Info.Length() == 0)
|
||||
{
|
||||
if (true)
|
||||
{
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FColor>(Info.Holder());
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(
|
||||
Isolate, "[FColor::M_ToPackedARGB] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
auto MethodResult = Self->ToPackedARGB();
|
||||
auto V8Result = v8::Integer::New(Isolate, MethodResult);
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "Invalid argument!");
|
||||
}
|
||||
|
||||
static void FColorM_ToPackedABGR(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
if (Info.Length() == 0)
|
||||
{
|
||||
if (true)
|
||||
{
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FColor>(Info.Holder());
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(
|
||||
Isolate, "[FColor::M_ToPackedABGR] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
auto MethodResult = Self->ToPackedABGR();
|
||||
auto V8Result = v8::Integer::New(Isolate, MethodResult);
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "Invalid argument!");
|
||||
}
|
||||
|
||||
static void FColorM_ToPackedRGBA(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
if (Info.Length() == 0)
|
||||
{
|
||||
if (true)
|
||||
{
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FColor>(Info.Holder());
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(
|
||||
Isolate, "[FColor::M_ToPackedRGBA] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
auto MethodResult = Self->ToPackedRGBA();
|
||||
auto V8Result = v8::Integer::New(Isolate, MethodResult);
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "Invalid argument!");
|
||||
}
|
||||
|
||||
static void FColorM_ToPackedBGRA(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
if (Info.Length() == 0)
|
||||
{
|
||||
if (true)
|
||||
{
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FColor>(Info.Holder());
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(
|
||||
Isolate, "[FColor::M_ToPackedBGRA] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
auto MethodResult = Self->ToPackedBGRA();
|
||||
auto V8Result = v8::Integer::New(Isolate, MethodResult);
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "Invalid argument!");
|
||||
}
|
||||
|
||||
struct AutoRegisterForFColor
|
||||
{
|
||||
AutoRegisterForFColor()
|
||||
{
|
||||
PUERTS_NAMESPACE::JSClassDefinition Def = JSClassEmptyDefinition;
|
||||
|
||||
static PUERTS_NAMESPACE::JSPropertyInfo Properties[] = {{0, 0, 0}};
|
||||
|
||||
static PUERTS_NAMESPACE::JSFunctionInfo Methods[] = {{"DWColor", FColorM_DWColor}, {"op_Equality", FColorM_op_Equality},
|
||||
{"op_Inequality", FColorM_op_Inequality}, {"FromRGBE", FColorM_FromRGBE}, {"WithAlpha", FColorM_WithAlpha},
|
||||
{"ReinterpretAsLinear", FColorM_ReinterpretAsLinear}, {"ToHex", FColorM_ToHex}, {"ToString", FColorM_ToString},
|
||||
{"InitFromString", FColorM_InitFromString}, {"ToPackedARGB", FColorM_ToPackedARGB},
|
||||
{"ToPackedABGR", FColorM_ToPackedABGR}, {"ToPackedRGBA", FColorM_ToPackedRGBA}, {"ToPackedBGRA", FColorM_ToPackedBGRA},
|
||||
{0, 0}};
|
||||
|
||||
static PUERTS_NAMESPACE::JSFunctionInfo Functions[] = {{"FromHex", FColorS_FromHex},
|
||||
{"MakeRandomColor", FColorS_MakeRandomColor}, {"MakeRedToGreenColorFromScalar", FColorS_MakeRedToGreenColorFromScalar},
|
||||
{"MakeFromColorTemperature", FColorS_MakeFromColorTemperature}, {0, 0}};
|
||||
|
||||
Def.UETypeName = "Color";
|
||||
|
||||
Def.SetInitialize(_FColorNew_);
|
||||
Def.Finalize = _FColorDelete_;
|
||||
Def.Properties = Properties;
|
||||
Def.Methods = Methods;
|
||||
Def.Functions = Functions;
|
||||
|
||||
PUERTS_NAMESPACE::RegisterJSClass(Def);
|
||||
}
|
||||
};
|
||||
|
||||
AutoRegisterForFColor _AutoRegisterForFColor_;
|
||||
@@ -0,0 +1,424 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// gen by puerts gen tools
|
||||
|
||||
#include "GenHeaders.h"
|
||||
#include "CoreMinimal.h"
|
||||
#include "DataTransfer.h"
|
||||
#include "JSClassRegister.h"
|
||||
|
||||
static void* _FGuidNew_(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
if (Info.Length() == 0)
|
||||
{
|
||||
if (true)
|
||||
{
|
||||
FGuid* Obj = new FGuid();
|
||||
|
||||
// UE_LOG(LogTemp, Warning, TEXT("_FGuidNew_:%p"), Obj);
|
||||
return Obj;
|
||||
}
|
||||
}
|
||||
if (Info.Length() == 4)
|
||||
{
|
||||
if (Info[0]->IsNumber() && Info[1]->IsNumber() && Info[2]->IsNumber() && Info[3]->IsNumber())
|
||||
{
|
||||
uint32 Arg0 = Info[0]->ToInteger(Context).ToLocalChecked()->Value();
|
||||
uint32 Arg1 = Info[1]->ToInteger(Context).ToLocalChecked()->Value();
|
||||
uint32 Arg2 = Info[2]->ToInteger(Context).ToLocalChecked()->Value();
|
||||
uint32 Arg3 = Info[3]->ToInteger(Context).ToLocalChecked()->Value();
|
||||
FGuid* Obj = new FGuid(Arg0, Arg1, Arg2, Arg3);
|
||||
|
||||
// UE_LOG(LogTemp, Warning, TEXT("_FGuidNew_:%p"), Obj);
|
||||
return Obj;
|
||||
}
|
||||
}
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "Invalid argument!");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static void _FGuidDelete_(void* Ptr, void* ClassData, void* EnvData)
|
||||
{
|
||||
FGuid* Self = static_cast<FGuid*>(Ptr);
|
||||
// UE_LOG(LogTemp, Warning, TEXT("_FGuidDelete_:%p"), Self);
|
||||
delete Self;
|
||||
}
|
||||
static void FGuidM_set_Item(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
if (Info.Length() == 1)
|
||||
{
|
||||
if (Info[0]->IsNumber())
|
||||
{
|
||||
int32 Arg0 = Info[0]->ToInteger(Context).ToLocalChecked()->Value();
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FGuid>(Info.Holder());
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(
|
||||
Isolate, "[FGuid::M_set_Item] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
Self->operator[](Arg0);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "Invalid argument!");
|
||||
}
|
||||
|
||||
static void FGuidM_get_Item(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
if (Info.Length() == 1)
|
||||
{
|
||||
if (Info[0]->IsNumber())
|
||||
{
|
||||
int32 Arg0 = Info[0]->ToInteger(Context).ToLocalChecked()->Value();
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FGuid>(Info.Holder());
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(
|
||||
Isolate, "[FGuid::M_get_Item] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
auto MethodResult = Self->operator[](Arg0);
|
||||
auto V8Result = v8::Integer::New(Isolate, MethodResult);
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "Invalid argument!");
|
||||
}
|
||||
|
||||
static void FGuidM_Invalidate(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
if (Info.Length() == 0)
|
||||
{
|
||||
if (true)
|
||||
{
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FGuid>(Info.Holder());
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(
|
||||
Isolate, "[FGuid::M_Invalidate] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
Self->Invalidate();
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "Invalid argument!");
|
||||
}
|
||||
|
||||
static void FGuidM_IsValid(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
if (Info.Length() == 0)
|
||||
{
|
||||
if (true)
|
||||
{
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FGuid>(Info.Holder());
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "[FGuid::M_IsValid] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
auto MethodResult = Self->IsValid();
|
||||
auto V8Result = v8::Boolean::New(Isolate, MethodResult);
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "Invalid argument!");
|
||||
}
|
||||
|
||||
static void FGuidM_ToString(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
if (Info.Length() == 0)
|
||||
{
|
||||
if (true)
|
||||
{
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FGuid>(Info.Holder());
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(
|
||||
Isolate, "[FGuid::M_ToString] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
auto MethodResult = Self->ToString();
|
||||
auto V8Result =
|
||||
v8::String::NewFromUtf8(Isolate, TCHAR_TO_UTF8(*MethodResult), v8::NewStringType::kNormal).ToLocalChecked();
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (Info.Length() == 1)
|
||||
{
|
||||
if (Info[0]->IsNumber())
|
||||
{
|
||||
EGuidFormats Arg0 = EGuidFormats(Info[0]->ToInt32(Context).ToLocalChecked()->Value());
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FGuid>(Info.Holder());
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(
|
||||
Isolate, "[FGuid::M_ToString] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
auto MethodResult = Self->ToString(Arg0);
|
||||
auto V8Result =
|
||||
v8::String::NewFromUtf8(Isolate, TCHAR_TO_UTF8(*MethodResult), v8::NewStringType::kNormal).ToLocalChecked();
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "Invalid argument!");
|
||||
}
|
||||
|
||||
static void FGuidS_NewGuid(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
if (Info.Length() == 0)
|
||||
{
|
||||
if (true)
|
||||
{
|
||||
auto MethodResult = FGuid::NewGuid();
|
||||
void* Ptr = new FGuid(MethodResult);
|
||||
|
||||
auto V8Result = PUERTS_NAMESPACE::DataTransfer::FindOrAddStruct<FGuid>(Isolate, Context, Ptr, false);
|
||||
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "Invalid argument!");
|
||||
}
|
||||
|
||||
static void FGuidS_Parse(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
if (Info.Length() == 2)
|
||||
{
|
||||
if (Info[0]->IsString() && Info[1]->IsObject() && PUERTS_NAMESPACE::DataTransfer::UnRef(Isolate, Info[1])->IsObject() &&
|
||||
|
||||
PUERTS_NAMESPACE::DataTransfer::IsInstanceOf<FGuid>(
|
||||
Isolate, PUERTS_NAMESPACE::DataTransfer::UnRef(Isolate, Info[1])->ToObject(Context).ToLocalChecked()))
|
||||
{
|
||||
const FString Arg0 = UTF8_TO_TCHAR(*(v8::String::Utf8Value(Isolate, Info[0])));
|
||||
FGuid* Arg1 = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FGuid>(
|
||||
PUERTS_NAMESPACE::DataTransfer::UnRef(Isolate, Info[1])->ToObject(Context).ToLocalChecked());
|
||||
auto MethodResult = FGuid::Parse(Arg0, *Arg1);
|
||||
auto V8Result = v8::Boolean::New(Isolate, MethodResult);
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "Invalid argument!");
|
||||
}
|
||||
|
||||
static void FGuidS_ParseExact(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
if (Info.Length() == 3)
|
||||
{
|
||||
if (Info[0]->IsString() && Info[1]->IsNumber() && Info[2]->IsObject() &&
|
||||
PUERTS_NAMESPACE::DataTransfer::UnRef(Isolate, Info[2])->IsObject() &&
|
||||
|
||||
PUERTS_NAMESPACE::DataTransfer::IsInstanceOf<FGuid>(
|
||||
Isolate, PUERTS_NAMESPACE::DataTransfer::UnRef(Isolate, Info[2])->ToObject(Context).ToLocalChecked()))
|
||||
{
|
||||
const FString Arg0 = UTF8_TO_TCHAR(*(v8::String::Utf8Value(Isolate, Info[0])));
|
||||
EGuidFormats Arg1 = EGuidFormats(Info[1]->ToInt32(Context).ToLocalChecked()->Value());
|
||||
FGuid* Arg2 = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FGuid>(
|
||||
PUERTS_NAMESPACE::DataTransfer::UnRef(Isolate, Info[2])->ToObject(Context).ToLocalChecked());
|
||||
auto MethodResult = FGuid::ParseExact(Arg0, Arg1, *Arg2);
|
||||
auto V8Result = v8::Boolean::New(Isolate, MethodResult);
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "Invalid argument!");
|
||||
}
|
||||
|
||||
static void _FGuidAGet_(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FGuid>(Info.Holder());
|
||||
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "[FGuid::A] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
|
||||
auto V8Result = v8::Integer::New(Isolate, Self->A);
|
||||
PUERTS_NAMESPACE::DataTransfer::LinkOuter<FGuid, uint32>(Context, Info.Holder(), V8Result);
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
}
|
||||
static void _FGuidASet_(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FGuid>(Info.Holder());
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "[FGuid::A] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
auto Value = Info[0];
|
||||
|
||||
Self->A = Value->ToInteger(Context).ToLocalChecked()->Value();
|
||||
}
|
||||
static void _FGuidBGet_(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FGuid>(Info.Holder());
|
||||
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "[FGuid::B] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
|
||||
auto V8Result = v8::Integer::New(Isolate, Self->B);
|
||||
PUERTS_NAMESPACE::DataTransfer::LinkOuter<FGuid, uint32>(Context, Info.Holder(), V8Result);
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
}
|
||||
static void _FGuidBSet_(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FGuid>(Info.Holder());
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "[FGuid::B] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
auto Value = Info[0];
|
||||
|
||||
Self->B = Value->ToInteger(Context).ToLocalChecked()->Value();
|
||||
}
|
||||
static void _FGuidCGet_(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FGuid>(Info.Holder());
|
||||
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "[FGuid::C] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
|
||||
auto V8Result = v8::Integer::New(Isolate, Self->C);
|
||||
PUERTS_NAMESPACE::DataTransfer::LinkOuter<FGuid, uint32>(Context, Info.Holder(), V8Result);
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
}
|
||||
static void _FGuidCSet_(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FGuid>(Info.Holder());
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "[FGuid::C] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
auto Value = Info[0];
|
||||
|
||||
Self->C = Value->ToInteger(Context).ToLocalChecked()->Value();
|
||||
}
|
||||
static void _FGuidDGet_(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FGuid>(Info.Holder());
|
||||
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "[FGuid::D] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
|
||||
auto V8Result = v8::Integer::New(Isolate, Self->D);
|
||||
PUERTS_NAMESPACE::DataTransfer::LinkOuter<FGuid, uint32>(Context, Info.Holder(), V8Result);
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
}
|
||||
static void _FGuidDSet_(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FGuid>(Info.Holder());
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "[FGuid::D] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
auto Value = Info[0];
|
||||
|
||||
Self->D = Value->ToInteger(Context).ToLocalChecked()->Value();
|
||||
}
|
||||
|
||||
struct AutoRegisterForFGuid
|
||||
{
|
||||
AutoRegisterForFGuid()
|
||||
{
|
||||
PUERTS_NAMESPACE::JSClassDefinition Def = JSClassEmptyDefinition;
|
||||
|
||||
static PUERTS_NAMESPACE::JSPropertyInfo Properties[] = {{"A", _FGuidAGet_, _FGuidASet_}, {"B", _FGuidBGet_, _FGuidBSet_},
|
||||
{"C", _FGuidCGet_, _FGuidCSet_}, {"D", _FGuidDGet_, _FGuidDSet_}, {0, 0, 0}};
|
||||
|
||||
static PUERTS_NAMESPACE::JSFunctionInfo Methods[] = {{"set_Item", FGuidM_set_Item}, {"get_Item", FGuidM_get_Item},
|
||||
{"Invalidate", FGuidM_Invalidate}, {"IsValid", FGuidM_IsValid}, {"ToString", FGuidM_ToString}, {0, 0}};
|
||||
|
||||
static PUERTS_NAMESPACE::JSFunctionInfo Functions[] = {
|
||||
{"NewGuid", FGuidS_NewGuid}, {"Parse", FGuidS_Parse}, {"ParseExact", FGuidS_ParseExact}, {0, 0}};
|
||||
|
||||
Def.UETypeName = "Guid";
|
||||
|
||||
Def.SetInitialize(_FGuidNew_);
|
||||
Def.Finalize = _FGuidDelete_;
|
||||
Def.Properties = Properties;
|
||||
Def.Methods = Methods;
|
||||
Def.Functions = Functions;
|
||||
|
||||
PUERTS_NAMESPACE::RegisterJSClass(Def);
|
||||
}
|
||||
};
|
||||
|
||||
AutoRegisterForFGuid _AutoRegisterForFGuid_;
|
||||
@@ -0,0 +1,724 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// gen by puerts gen tools
|
||||
|
||||
#include "GenHeaders.h"
|
||||
#include "CoreMinimal.h"
|
||||
#include "DataTransfer.h"
|
||||
#include "JSClassRegister.h"
|
||||
|
||||
// <SourceLocation file 'D:\\Program Files\\Epic Games\\UE_4.24\\Engine\\Source\\Runtime\\Core\\Public\\Math/IntPoint.h', line 60,
|
||||
// column 15> unsupported method : operator() const int32 &(int32) __attribute__((thiscall)) const
|
||||
|
||||
// <SourceLocation file 'D:\\Program Files\\Epic Games\\UE_4.24\\Engine\\Source\\Runtime\\Core\\Public\\Math/IntPoint.h', line 68,
|
||||
// column 9> unsupported method : operator() int32 &(int32) __attribute__((thiscall))
|
||||
|
||||
// <SourceLocation file 'D:\\Program Files\\Epic Games\\UE_4.24\\Engine\\Source\\Runtime\\Core\\Public\\Math/IntPoint.h', line 92,
|
||||
// column 13> unsupported method : operator*= FIntPoint &(int32) __attribute__((thiscall))
|
||||
|
||||
// <SourceLocation file 'D:\\Program Files\\Epic Games\\UE_4.24\\Engine\\Source\\Runtime\\Core\\Public\\Math/IntPoint.h', line 100,
|
||||
// column 13> unsupported method : operator/= FIntPoint &(int32) __attribute__((thiscall))
|
||||
|
||||
// <SourceLocation file 'D:\\Program Files\\Epic Games\\UE_4.24\\Engine\\Source\\Runtime\\Core\\Public\\Math/IntPoint.h', line 108,
|
||||
// column 13> unsupported method : operator+= FIntPoint &(const FIntPoint &) __attribute__((thiscall))
|
||||
|
||||
// <SourceLocation file 'D:\\Program Files\\Epic Games\\UE_4.24\\Engine\\Source\\Runtime\\Core\\Public\\Math/IntPoint.h', line 116,
|
||||
// column 13> unsupported method : operator-= FIntPoint &(const FIntPoint &) __attribute__((thiscall))
|
||||
|
||||
// <SourceLocation file 'D:\\Program Files\\Epic Games\\UE_4.24\\Engine\\Source\\Runtime\\Core\\Public\\Math/IntPoint.h', line 124,
|
||||
// column 13> unsupported method : operator/= FIntPoint &(const FIntPoint &) __attribute__((thiscall))
|
||||
|
||||
// <SourceLocation file 'D:\\Program Files\\Epic Games\\UE_4.24\\Engine\\Source\\Runtime\\Core\\Public\\Math/IntPoint.h', line 132,
|
||||
// column 13> unsupported method : operator= FIntPoint &(const FIntPoint &) __attribute__((thiscall))
|
||||
|
||||
static void* _FIntPointNew_(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
if (Info.Length() == 0)
|
||||
{
|
||||
if (true)
|
||||
{
|
||||
FIntPoint* Obj = new FIntPoint();
|
||||
|
||||
// UE_LOG(LogTemp, Warning, TEXT("_FIntPointNew_:%p"), Obj);
|
||||
return Obj;
|
||||
}
|
||||
}
|
||||
if (Info.Length() == 2)
|
||||
{
|
||||
if (Info[0]->IsNumber() && Info[1]->IsNumber())
|
||||
{
|
||||
int32 Arg0 = Info[0]->ToInteger(Context).ToLocalChecked()->Value();
|
||||
int32 Arg1 = Info[1]->ToInteger(Context).ToLocalChecked()->Value();
|
||||
FIntPoint* Obj = new FIntPoint(Arg0, Arg1);
|
||||
|
||||
// UE_LOG(LogTemp, Warning, TEXT("_FIntPointNew_:%p"), Obj);
|
||||
return Obj;
|
||||
}
|
||||
}
|
||||
if (Info.Length() == 1)
|
||||
{
|
||||
if (Info[0]->IsNumber())
|
||||
{
|
||||
EForceInit Arg0 = EForceInit(Info[0]->ToInt32(Context).ToLocalChecked()->Value());
|
||||
FIntPoint* Obj = new FIntPoint(Arg0);
|
||||
|
||||
// UE_LOG(LogTemp, Warning, TEXT("_FIntPointNew_:%p"), Obj);
|
||||
return Obj;
|
||||
}
|
||||
}
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "Invalid argument!");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static void _FIntPointDelete_(void* Ptr, void* ClassData, void* EnvData)
|
||||
{
|
||||
FIntPoint* Self = static_cast<FIntPoint*>(Ptr);
|
||||
// UE_LOG(LogTemp, Warning, TEXT("_FIntPointDelete_:%p"), Self);
|
||||
delete Self;
|
||||
}
|
||||
static void FIntPointM_op_Equality(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
if (Info.Length() == 1)
|
||||
{
|
||||
if (Info[0]->IsObject() &&
|
||||
|
||||
PUERTS_NAMESPACE::DataTransfer::IsInstanceOf<FIntPoint>(Isolate, Info[0]->ToObject(Context).ToLocalChecked()))
|
||||
{
|
||||
const FIntPoint* Arg0 =
|
||||
PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FIntPoint>(Info[0]->ToObject(Context).ToLocalChecked());
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FIntPoint>(Info.Holder());
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(
|
||||
Isolate, "[FIntPoint::M_op_Equality] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
auto MethodResult = Self->operator==(*Arg0);
|
||||
auto V8Result = v8::Boolean::New(Isolate, MethodResult);
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "Invalid argument!");
|
||||
}
|
||||
|
||||
static void FIntPointM_op_Inequality(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
if (Info.Length() == 1)
|
||||
{
|
||||
if (Info[0]->IsObject() &&
|
||||
|
||||
PUERTS_NAMESPACE::DataTransfer::IsInstanceOf<FIntPoint>(Isolate, Info[0]->ToObject(Context).ToLocalChecked()))
|
||||
{
|
||||
const FIntPoint* Arg0 =
|
||||
PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FIntPoint>(Info[0]->ToObject(Context).ToLocalChecked());
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FIntPoint>(Info.Holder());
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(
|
||||
Isolate, "[FIntPoint::M_op_Inequality] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
auto MethodResult = Self->operator!=(*Arg0);
|
||||
auto V8Result = v8::Boolean::New(Isolate, MethodResult);
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "Invalid argument!");
|
||||
}
|
||||
|
||||
static void FIntPointM_op_Multiply(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
if (Info.Length() == 1)
|
||||
{
|
||||
if (Info[0]->IsNumber())
|
||||
{
|
||||
int32 Arg0 = Info[0]->ToInteger(Context).ToLocalChecked()->Value();
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FIntPoint>(Info.Holder());
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(
|
||||
Isolate, "[FIntPoint::M_op_Multiply] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
auto MethodResult = Self->operator*(Arg0);
|
||||
void* Ptr = new FIntPoint(MethodResult);
|
||||
|
||||
auto V8Result = PUERTS_NAMESPACE::DataTransfer::FindOrAddStruct<FIntPoint>(Isolate, Context, Ptr, false);
|
||||
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "Invalid argument!");
|
||||
}
|
||||
|
||||
static void FIntPointM_op_Division(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
if (Info.Length() == 1)
|
||||
{
|
||||
if (Info[0]->IsNumber())
|
||||
{
|
||||
int32 Arg0 = Info[0]->ToInteger(Context).ToLocalChecked()->Value();
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FIntPoint>(Info.Holder());
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(
|
||||
Isolate, "[FIntPoint::M_op_Division] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
auto MethodResult = Self->operator/(Arg0);
|
||||
void* Ptr = new FIntPoint(MethodResult);
|
||||
|
||||
auto V8Result = PUERTS_NAMESPACE::DataTransfer::FindOrAddStruct<FIntPoint>(Isolate, Context, Ptr, false);
|
||||
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (Info.Length() == 1)
|
||||
{
|
||||
if (Info[0]->IsObject() &&
|
||||
|
||||
PUERTS_NAMESPACE::DataTransfer::IsInstanceOf<FIntPoint>(Isolate, Info[0]->ToObject(Context).ToLocalChecked()))
|
||||
{
|
||||
const FIntPoint* Arg0 =
|
||||
PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FIntPoint>(Info[0]->ToObject(Context).ToLocalChecked());
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FIntPoint>(Info.Holder());
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(
|
||||
Isolate, "[FIntPoint::M_op_Division] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
auto MethodResult = Self->operator/(*Arg0);
|
||||
void* Ptr = new FIntPoint(MethodResult);
|
||||
|
||||
auto V8Result = PUERTS_NAMESPACE::DataTransfer::FindOrAddStruct<FIntPoint>(Isolate, Context, Ptr, false);
|
||||
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "Invalid argument!");
|
||||
}
|
||||
|
||||
static void FIntPointM_op_Addition(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
if (Info.Length() == 1)
|
||||
{
|
||||
if (Info[0]->IsObject() &&
|
||||
|
||||
PUERTS_NAMESPACE::DataTransfer::IsInstanceOf<FIntPoint>(Isolate, Info[0]->ToObject(Context).ToLocalChecked()))
|
||||
{
|
||||
const FIntPoint* Arg0 =
|
||||
PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FIntPoint>(Info[0]->ToObject(Context).ToLocalChecked());
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FIntPoint>(Info.Holder());
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(
|
||||
Isolate, "[FIntPoint::M_op_Addition] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
auto MethodResult = Self->operator+(*Arg0);
|
||||
void* Ptr = new FIntPoint(MethodResult);
|
||||
|
||||
auto V8Result = PUERTS_NAMESPACE::DataTransfer::FindOrAddStruct<FIntPoint>(Isolate, Context, Ptr, false);
|
||||
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "Invalid argument!");
|
||||
}
|
||||
|
||||
static void FIntPointM_op_Subtraction(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
if (Info.Length() == 1)
|
||||
{
|
||||
if (Info[0]->IsObject() &&
|
||||
|
||||
PUERTS_NAMESPACE::DataTransfer::IsInstanceOf<FIntPoint>(Isolate, Info[0]->ToObject(Context).ToLocalChecked()))
|
||||
{
|
||||
const FIntPoint* Arg0 =
|
||||
PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FIntPoint>(Info[0]->ToObject(Context).ToLocalChecked());
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FIntPoint>(Info.Holder());
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(
|
||||
Isolate, "[FIntPoint::M_op_Subtraction] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
auto MethodResult = Self->operator-(*Arg0);
|
||||
void* Ptr = new FIntPoint(MethodResult);
|
||||
|
||||
auto V8Result = PUERTS_NAMESPACE::DataTransfer::FindOrAddStruct<FIntPoint>(Isolate, Context, Ptr, false);
|
||||
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "Invalid argument!");
|
||||
}
|
||||
|
||||
static void FIntPointM_set_Item(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
if (Info.Length() == 1)
|
||||
{
|
||||
if (Info[0]->IsNumber())
|
||||
{
|
||||
int32 Arg0 = Info[0]->ToInteger(Context).ToLocalChecked()->Value();
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FIntPoint>(Info.Holder());
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(
|
||||
Isolate, "[FIntPoint::M_set_Item] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
Self->operator[](Arg0);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "Invalid argument!");
|
||||
}
|
||||
|
||||
static void FIntPointM_get_Item(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
if (Info.Length() == 1)
|
||||
{
|
||||
if (Info[0]->IsNumber())
|
||||
{
|
||||
int32 Arg0 = Info[0]->ToInteger(Context).ToLocalChecked()->Value();
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FIntPoint>(Info.Holder());
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(
|
||||
Isolate, "[FIntPoint::M_get_Item] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
auto MethodResult = Self->operator[](Arg0);
|
||||
auto V8Result = v8::Integer::New(Isolate, MethodResult);
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "Invalid argument!");
|
||||
}
|
||||
|
||||
static void FIntPointM_ComponentMin(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
if (Info.Length() == 1)
|
||||
{
|
||||
if (Info[0]->IsObject() &&
|
||||
|
||||
PUERTS_NAMESPACE::DataTransfer::IsInstanceOf<FIntPoint>(Isolate, Info[0]->ToObject(Context).ToLocalChecked()))
|
||||
{
|
||||
const FIntPoint* Arg0 =
|
||||
PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FIntPoint>(Info[0]->ToObject(Context).ToLocalChecked());
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FIntPoint>(Info.Holder());
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(
|
||||
Isolate, "[FIntPoint::M_ComponentMin] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
auto MethodResult = Self->ComponentMin(*Arg0);
|
||||
void* Ptr = new FIntPoint(MethodResult);
|
||||
|
||||
auto V8Result = PUERTS_NAMESPACE::DataTransfer::FindOrAddStruct<FIntPoint>(Isolate, Context, Ptr, false);
|
||||
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "Invalid argument!");
|
||||
}
|
||||
|
||||
static void FIntPointM_ComponentMax(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
if (Info.Length() == 1)
|
||||
{
|
||||
if (Info[0]->IsObject() &&
|
||||
|
||||
PUERTS_NAMESPACE::DataTransfer::IsInstanceOf<FIntPoint>(Isolate, Info[0]->ToObject(Context).ToLocalChecked()))
|
||||
{
|
||||
const FIntPoint* Arg0 =
|
||||
PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FIntPoint>(Info[0]->ToObject(Context).ToLocalChecked());
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FIntPoint>(Info.Holder());
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(
|
||||
Isolate, "[FIntPoint::M_ComponentMax] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
auto MethodResult = Self->ComponentMax(*Arg0);
|
||||
void* Ptr = new FIntPoint(MethodResult);
|
||||
|
||||
auto V8Result = PUERTS_NAMESPACE::DataTransfer::FindOrAddStruct<FIntPoint>(Isolate, Context, Ptr, false);
|
||||
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "Invalid argument!");
|
||||
}
|
||||
|
||||
static void FIntPointM_GetMax(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
if (Info.Length() == 0)
|
||||
{
|
||||
if (true)
|
||||
{
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FIntPoint>(Info.Holder());
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(
|
||||
Isolate, "[FIntPoint::M_GetMax] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
auto MethodResult = Self->GetMax();
|
||||
auto V8Result = v8::Integer::New(Isolate, MethodResult);
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "Invalid argument!");
|
||||
}
|
||||
|
||||
static void FIntPointM_GetMin(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
if (Info.Length() == 0)
|
||||
{
|
||||
if (true)
|
||||
{
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FIntPoint>(Info.Holder());
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(
|
||||
Isolate, "[FIntPoint::M_GetMin] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
auto MethodResult = Self->GetMin();
|
||||
auto V8Result = v8::Integer::New(Isolate, MethodResult);
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "Invalid argument!");
|
||||
}
|
||||
|
||||
static void FIntPointM_Size(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
if (Info.Length() == 0)
|
||||
{
|
||||
if (true)
|
||||
{
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FIntPoint>(Info.Holder());
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(
|
||||
Isolate, "[FIntPoint::M_Size] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
auto MethodResult = Self->Size();
|
||||
auto V8Result = v8::Integer::New(Isolate, MethodResult);
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "Invalid argument!");
|
||||
}
|
||||
|
||||
static void FIntPointM_SizeSquared(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
if (Info.Length() == 0)
|
||||
{
|
||||
if (true)
|
||||
{
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FIntPoint>(Info.Holder());
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(
|
||||
Isolate, "[FIntPoint::M_SizeSquared] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
auto MethodResult = Self->SizeSquared();
|
||||
auto V8Result = v8::Integer::New(Isolate, MethodResult);
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "Invalid argument!");
|
||||
}
|
||||
|
||||
static void FIntPointM_ToString(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
if (Info.Length() == 0)
|
||||
{
|
||||
if (true)
|
||||
{
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FIntPoint>(Info.Holder());
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(
|
||||
Isolate, "[FIntPoint::M_ToString] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
auto MethodResult = Self->ToString();
|
||||
auto V8Result =
|
||||
v8::String::NewFromUtf8(Isolate, TCHAR_TO_UTF8(*MethodResult), v8::NewStringType::kNormal).ToLocalChecked();
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "Invalid argument!");
|
||||
}
|
||||
|
||||
static void FIntPointS_DivideAndRoundUp(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
if (Info.Length() == 2)
|
||||
{
|
||||
if (Info[0]->IsObject() &&
|
||||
|
||||
PUERTS_NAMESPACE::DataTransfer::IsInstanceOf<FIntPoint>(Isolate, Info[0]->ToObject(Context).ToLocalChecked()) &&
|
||||
Info[1]->IsNumber())
|
||||
{
|
||||
FIntPoint* Arg0 =
|
||||
PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FIntPoint>(Info[0]->ToObject(Context).ToLocalChecked());
|
||||
int32 Arg1 = Info[1]->ToInteger(Context).ToLocalChecked()->Value();
|
||||
auto MethodResult = FIntPoint::DivideAndRoundUp(*Arg0, Arg1);
|
||||
void* Ptr = new FIntPoint(MethodResult);
|
||||
|
||||
auto V8Result = PUERTS_NAMESPACE::DataTransfer::FindOrAddStruct<FIntPoint>(Isolate, Context, Ptr, false);
|
||||
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (Info.Length() == 2)
|
||||
{
|
||||
if (Info[0]->IsObject() &&
|
||||
|
||||
PUERTS_NAMESPACE::DataTransfer::IsInstanceOf<FIntPoint>(Isolate, Info[0]->ToObject(Context).ToLocalChecked()) &&
|
||||
Info[1]->IsObject() &&
|
||||
|
||||
PUERTS_NAMESPACE::DataTransfer::IsInstanceOf<FIntPoint>(Isolate, Info[1]->ToObject(Context).ToLocalChecked()))
|
||||
{
|
||||
FIntPoint* Arg0 =
|
||||
PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FIntPoint>(Info[0]->ToObject(Context).ToLocalChecked());
|
||||
FIntPoint* Arg1 =
|
||||
PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FIntPoint>(Info[1]->ToObject(Context).ToLocalChecked());
|
||||
auto MethodResult = FIntPoint::DivideAndRoundUp(*Arg0, *Arg1);
|
||||
void* Ptr = new FIntPoint(MethodResult);
|
||||
|
||||
auto V8Result = PUERTS_NAMESPACE::DataTransfer::FindOrAddStruct<FIntPoint>(Isolate, Context, Ptr, false);
|
||||
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "Invalid argument!");
|
||||
}
|
||||
|
||||
static void FIntPointS_DivideAndRoundDown(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
if (Info.Length() == 2)
|
||||
{
|
||||
if (Info[0]->IsObject() &&
|
||||
|
||||
PUERTS_NAMESPACE::DataTransfer::IsInstanceOf<FIntPoint>(Isolate, Info[0]->ToObject(Context).ToLocalChecked()) &&
|
||||
Info[1]->IsNumber())
|
||||
{
|
||||
FIntPoint* Arg0 =
|
||||
PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FIntPoint>(Info[0]->ToObject(Context).ToLocalChecked());
|
||||
int32 Arg1 = Info[1]->ToInteger(Context).ToLocalChecked()->Value();
|
||||
auto MethodResult = FIntPoint::DivideAndRoundDown(*Arg0, Arg1);
|
||||
void* Ptr = new FIntPoint(MethodResult);
|
||||
|
||||
auto V8Result = PUERTS_NAMESPACE::DataTransfer::FindOrAddStruct<FIntPoint>(Isolate, Context, Ptr, false);
|
||||
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "Invalid argument!");
|
||||
}
|
||||
|
||||
static void FIntPointS_Num(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
if (Info.Length() == 0)
|
||||
{
|
||||
if (true)
|
||||
{
|
||||
auto MethodResult = FIntPoint::Num();
|
||||
auto V8Result = v8::Integer::New(Isolate, MethodResult);
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "Invalid argument!");
|
||||
}
|
||||
|
||||
static void _FIntPointXGet_(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FIntPoint>(Info.Holder());
|
||||
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "[FIntPoint::X] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
|
||||
auto V8Result = v8::Integer::New(Isolate, Self->X);
|
||||
PUERTS_NAMESPACE::DataTransfer::LinkOuter<FIntPoint, int32>(Context, Info.Holder(), V8Result);
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
}
|
||||
static void _FIntPointXSet_(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FIntPoint>(Info.Holder());
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "[FIntPoint::X] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
auto Value = Info[0];
|
||||
|
||||
Self->X = Value->ToInteger(Context).ToLocalChecked()->Value();
|
||||
}
|
||||
static void _FIntPointYGet_(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FIntPoint>(Info.Holder());
|
||||
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "[FIntPoint::Y] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
|
||||
auto V8Result = v8::Integer::New(Isolate, Self->Y);
|
||||
PUERTS_NAMESPACE::DataTransfer::LinkOuter<FIntPoint, int32>(Context, Info.Holder(), V8Result);
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
}
|
||||
static void _FIntPointYSet_(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FIntPoint>(Info.Holder());
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "[FIntPoint::Y] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
auto Value = Info[0];
|
||||
|
||||
Self->Y = Value->ToInteger(Context).ToLocalChecked()->Value();
|
||||
}
|
||||
|
||||
struct AutoRegisterForFIntPoint
|
||||
{
|
||||
AutoRegisterForFIntPoint()
|
||||
{
|
||||
PUERTS_NAMESPACE::JSClassDefinition Def = JSClassEmptyDefinition;
|
||||
|
||||
static PUERTS_NAMESPACE::JSPropertyInfo Properties[] = {
|
||||
{"X", _FIntPointXGet_, _FIntPointXSet_}, {"Y", _FIntPointYGet_, _FIntPointYSet_}, {0, 0, 0}};
|
||||
|
||||
static PUERTS_NAMESPACE::JSFunctionInfo Methods[] = {{"op_Equality", FIntPointM_op_Equality},
|
||||
{"op_Inequality", FIntPointM_op_Inequality}, {"op_Multiply", FIntPointM_op_Multiply},
|
||||
{"op_Division", FIntPointM_op_Division}, {"op_Addition", FIntPointM_op_Addition},
|
||||
{"op_Subtraction", FIntPointM_op_Subtraction}, {"set_Item", FIntPointM_set_Item}, {"get_Item", FIntPointM_get_Item},
|
||||
{"ComponentMin", FIntPointM_ComponentMin}, {"ComponentMax", FIntPointM_ComponentMax}, {"GetMax", FIntPointM_GetMax},
|
||||
{"GetMin", FIntPointM_GetMin}, {"Size", FIntPointM_Size}, {"SizeSquared", FIntPointM_SizeSquared},
|
||||
{"ToString", FIntPointM_ToString}, {0, 0}};
|
||||
|
||||
static PUERTS_NAMESPACE::JSFunctionInfo Functions[] = {{"DivideAndRoundUp", FIntPointS_DivideAndRoundUp},
|
||||
{"DivideAndRoundDown", FIntPointS_DivideAndRoundDown}, {"Num", FIntPointS_Num}, {0, 0}};
|
||||
|
||||
Def.UETypeName = "IntPoint";
|
||||
|
||||
Def.SetInitialize(_FIntPointNew_);
|
||||
Def.Finalize = _FIntPointDelete_;
|
||||
Def.Properties = Properties;
|
||||
Def.Methods = Methods;
|
||||
Def.Functions = Functions;
|
||||
|
||||
PUERTS_NAMESPACE::RegisterJSClass(Def);
|
||||
}
|
||||
};
|
||||
|
||||
AutoRegisterForFIntPoint _AutoRegisterForFIntPoint_;
|
||||
@@ -0,0 +1,647 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// gen by puerts gen tools
|
||||
|
||||
#include "GenHeaders.h"
|
||||
#include "CoreMinimal.h"
|
||||
#include "DataTransfer.h"
|
||||
#include "JSClassRegister.h"
|
||||
|
||||
// <SourceLocation file 'D:\\Program Files\\Epic Games\\UE_4.24\\Engine\\Source\\Runtime\\Core\\Public\\Math/IntVector.h', line 78,
|
||||
// column 15> unsupported method : operator() const int32 &(int32) __attribute__((thiscall)) const
|
||||
|
||||
// <SourceLocation file 'D:\\Program Files\\Epic Games\\UE_4.24\\Engine\\Source\\Runtime\\Core\\Public\\Math/IntVector.h', line 86,
|
||||
// column 9> unsupported method : operator() int32 &(int32) __attribute__((thiscall))
|
||||
|
||||
// <SourceLocation file 'D:\\Program Files\\Epic Games\\UE_4.24\\Engine\\Source\\Runtime\\Core\\Public\\Math/IntVector.h', line 126,
|
||||
// column 14> unsupported method : operator*= FIntVector &(int32) __attribute__((thiscall))
|
||||
|
||||
// <SourceLocation file 'D:\\Program Files\\Epic Games\\UE_4.24\\Engine\\Source\\Runtime\\Core\\Public\\Math/IntVector.h', line 134,
|
||||
// column 14> unsupported method : operator/= FIntVector &(int32) __attribute__((thiscall))
|
||||
|
||||
// <SourceLocation file 'D:\\Program Files\\Epic Games\\UE_4.24\\Engine\\Source\\Runtime\\Core\\Public\\Math/IntVector.h', line 142,
|
||||
// column 14> unsupported method : operator+= FIntVector &(const FIntVector &) __attribute__((thiscall))
|
||||
|
||||
// <SourceLocation file 'D:\\Program Files\\Epic Games\\UE_4.24\\Engine\\Source\\Runtime\\Core\\Public\\Math/IntVector.h', line 150,
|
||||
// column 14> unsupported method : operator-= FIntVector &(const FIntVector &) __attribute__((thiscall))
|
||||
|
||||
// <SourceLocation file 'D:\\Program Files\\Epic Games\\UE_4.24\\Engine\\Source\\Runtime\\Core\\Public\\Math/IntVector.h', line 158,
|
||||
// column 14> unsupported method : operator= FIntVector &(const FIntVector &) __attribute__((thiscall))
|
||||
|
||||
// <SourceLocation file 'D:\\Program Files\\Epic Games\\UE_4.24\\Engine\\Source\\Runtime\\Core\\Public\\Math/IntVector.h', line 198,
|
||||
// column 13> unsupported method : operator>> FIntVector (int32) __attribute__((thiscall)) const
|
||||
|
||||
// <SourceLocation file 'D:\\Program Files\\Epic Games\\UE_4.24\\Engine\\Source\\Runtime\\Core\\Public\\Math/IntVector.h', line 206,
|
||||
// column 13> unsupported method : operator<< FIntVector (int32) __attribute__((thiscall)) const
|
||||
|
||||
// <SourceLocation file 'D:\\Program Files\\Epic Games\\UE_4.24\\Engine\\Source\\Runtime\\Core\\Public\\Math/IntVector.h', line 214,
|
||||
// column 13> unsupported method : operator& FIntVector (int32) __attribute__((thiscall)) const
|
||||
|
||||
static void* _FIntVectorNew_(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
if (Info.Length() == 0)
|
||||
{
|
||||
if (true)
|
||||
{
|
||||
FIntVector* Obj = new FIntVector();
|
||||
|
||||
// UE_LOG(LogTemp, Warning, TEXT("_FIntVectorNew_:%p"), Obj);
|
||||
return Obj;
|
||||
}
|
||||
}
|
||||
if (Info.Length() == 3)
|
||||
{
|
||||
if (Info[0]->IsNumber() && Info[1]->IsNumber() && Info[2]->IsNumber())
|
||||
{
|
||||
int32 Arg0 = Info[0]->ToInteger(Context).ToLocalChecked()->Value();
|
||||
int32 Arg1 = Info[1]->ToInteger(Context).ToLocalChecked()->Value();
|
||||
int32 Arg2 = Info[2]->ToInteger(Context).ToLocalChecked()->Value();
|
||||
FIntVector* Obj = new FIntVector(Arg0, Arg1, Arg2);
|
||||
|
||||
// UE_LOG(LogTemp, Warning, TEXT("_FIntVectorNew_:%p"), Obj);
|
||||
return Obj;
|
||||
}
|
||||
}
|
||||
if (Info.Length() == 1)
|
||||
{
|
||||
if (Info[0]->IsNumber())
|
||||
{
|
||||
int32 Arg0 = Info[0]->ToInteger(Context).ToLocalChecked()->Value();
|
||||
FIntVector* Obj = new FIntVector(Arg0);
|
||||
|
||||
// UE_LOG(LogTemp, Warning, TEXT("_FIntVectorNew_:%p"), Obj);
|
||||
return Obj;
|
||||
}
|
||||
}
|
||||
if (Info.Length() == 1)
|
||||
{
|
||||
if (Info[0]->IsObject() &&
|
||||
|
||||
PUERTS_NAMESPACE::DataTransfer::IsInstanceOf<FVector>(Isolate, Info[0]->ToObject(Context).ToLocalChecked()))
|
||||
{
|
||||
FVector* Arg0 = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FVector>(Info[0]->ToObject(Context).ToLocalChecked());
|
||||
FIntVector* Obj = new FIntVector(*Arg0);
|
||||
|
||||
// UE_LOG(LogTemp, Warning, TEXT("_FIntVectorNew_:%p"), Obj);
|
||||
return Obj;
|
||||
}
|
||||
}
|
||||
if (Info.Length() == 1)
|
||||
{
|
||||
if (Info[0]->IsNumber())
|
||||
{
|
||||
EForceInit Arg0 = EForceInit(Info[0]->ToInt32(Context).ToLocalChecked()->Value());
|
||||
FIntVector* Obj = new FIntVector(Arg0);
|
||||
|
||||
// UE_LOG(LogTemp, Warning, TEXT("_FIntVectorNew_:%p"), Obj);
|
||||
return Obj;
|
||||
}
|
||||
}
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "Invalid argument!");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static void _FIntVectorDelete_(void* Ptr, void* ClassData, void* EnvData)
|
||||
{
|
||||
FIntVector* Self = static_cast<FIntVector*>(Ptr);
|
||||
// UE_LOG(LogTemp, Warning, TEXT("_FIntVectorDelete_:%p"), Self);
|
||||
delete Self;
|
||||
}
|
||||
static void FIntVectorM_get_Item(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
if (Info.Length() == 1)
|
||||
{
|
||||
if (Info[0]->IsNumber())
|
||||
{
|
||||
int32 Arg0 = Info[0]->ToInteger(Context).ToLocalChecked()->Value();
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FIntVector>(Info.Holder());
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(
|
||||
Isolate, "[FIntVector::M_get_Item] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
auto MethodResult = Self->operator[](Arg0);
|
||||
auto V8Result = v8::Integer::New(Isolate, MethodResult);
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "Invalid argument!");
|
||||
}
|
||||
|
||||
static void FIntVectorM_set_Item(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
if (Info.Length() == 1)
|
||||
{
|
||||
if (Info[0]->IsNumber())
|
||||
{
|
||||
int32 Arg0 = Info[0]->ToInteger(Context).ToLocalChecked()->Value();
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FIntVector>(Info.Holder());
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(
|
||||
Isolate, "[FIntVector::M_set_Item] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
Self->operator[](Arg0);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "Invalid argument!");
|
||||
}
|
||||
|
||||
static void FIntVectorM_op_Equality(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
if (Info.Length() == 1)
|
||||
{
|
||||
if (Info[0]->IsObject() &&
|
||||
|
||||
PUERTS_NAMESPACE::DataTransfer::IsInstanceOf<FIntVector>(Isolate, Info[0]->ToObject(Context).ToLocalChecked()))
|
||||
{
|
||||
const FIntVector* Arg0 =
|
||||
PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FIntVector>(Info[0]->ToObject(Context).ToLocalChecked());
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FIntVector>(Info.Holder());
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(
|
||||
Isolate, "[FIntVector::M_op_Equality] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
auto MethodResult = Self->operator==(*Arg0);
|
||||
auto V8Result = v8::Boolean::New(Isolate, MethodResult);
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "Invalid argument!");
|
||||
}
|
||||
|
||||
static void FIntVectorM_op_Inequality(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
if (Info.Length() == 1)
|
||||
{
|
||||
if (Info[0]->IsObject() &&
|
||||
|
||||
PUERTS_NAMESPACE::DataTransfer::IsInstanceOf<FIntVector>(Isolate, Info[0]->ToObject(Context).ToLocalChecked()))
|
||||
{
|
||||
const FIntVector* Arg0 =
|
||||
PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FIntVector>(Info[0]->ToObject(Context).ToLocalChecked());
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FIntVector>(Info.Holder());
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(
|
||||
Isolate, "[FIntVector::M_op_Inequality] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
auto MethodResult = Self->operator!=(*Arg0);
|
||||
auto V8Result = v8::Boolean::New(Isolate, MethodResult);
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "Invalid argument!");
|
||||
}
|
||||
|
||||
static void FIntVectorM_op_Multiply(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
if (Info.Length() == 1)
|
||||
{
|
||||
if (Info[0]->IsNumber())
|
||||
{
|
||||
int32 Arg0 = Info[0]->ToInteger(Context).ToLocalChecked()->Value();
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FIntVector>(Info.Holder());
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(
|
||||
Isolate, "[FIntVector::M_op_Multiply] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
auto MethodResult = Self->operator*(Arg0);
|
||||
void* Ptr = new FIntVector(MethodResult);
|
||||
|
||||
auto V8Result = PUERTS_NAMESPACE::DataTransfer::FindOrAddStruct<FIntVector>(Isolate, Context, Ptr, false);
|
||||
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "Invalid argument!");
|
||||
}
|
||||
|
||||
static void FIntVectorM_op_Division(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
if (Info.Length() == 1)
|
||||
{
|
||||
if (Info[0]->IsNumber())
|
||||
{
|
||||
int32 Arg0 = Info[0]->ToInteger(Context).ToLocalChecked()->Value();
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FIntVector>(Info.Holder());
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(
|
||||
Isolate, "[FIntVector::M_op_Division] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
auto MethodResult = Self->operator/(Arg0);
|
||||
void* Ptr = new FIntVector(MethodResult);
|
||||
|
||||
auto V8Result = PUERTS_NAMESPACE::DataTransfer::FindOrAddStruct<FIntVector>(Isolate, Context, Ptr, false);
|
||||
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "Invalid argument!");
|
||||
}
|
||||
|
||||
static void FIntVectorM_op_Addition(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
if (Info.Length() == 1)
|
||||
{
|
||||
if (Info[0]->IsObject() &&
|
||||
|
||||
PUERTS_NAMESPACE::DataTransfer::IsInstanceOf<FIntVector>(Isolate, Info[0]->ToObject(Context).ToLocalChecked()))
|
||||
{
|
||||
const FIntVector* Arg0 =
|
||||
PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FIntVector>(Info[0]->ToObject(Context).ToLocalChecked());
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FIntVector>(Info.Holder());
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(
|
||||
Isolate, "[FIntVector::M_op_Addition] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
auto MethodResult = Self->operator+(*Arg0);
|
||||
void* Ptr = new FIntVector(MethodResult);
|
||||
|
||||
auto V8Result = PUERTS_NAMESPACE::DataTransfer::FindOrAddStruct<FIntVector>(Isolate, Context, Ptr, false);
|
||||
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "Invalid argument!");
|
||||
}
|
||||
|
||||
static void FIntVectorM_op_Subtraction(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
if (Info.Length() == 1)
|
||||
{
|
||||
if (Info[0]->IsObject() &&
|
||||
|
||||
PUERTS_NAMESPACE::DataTransfer::IsInstanceOf<FIntVector>(Isolate, Info[0]->ToObject(Context).ToLocalChecked()))
|
||||
{
|
||||
const FIntVector* Arg0 =
|
||||
PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FIntVector>(Info[0]->ToObject(Context).ToLocalChecked());
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FIntVector>(Info.Holder());
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(
|
||||
Isolate, "[FIntVector::M_op_Subtraction] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
auto MethodResult = Self->operator-(*Arg0);
|
||||
void* Ptr = new FIntVector(MethodResult);
|
||||
|
||||
auto V8Result = PUERTS_NAMESPACE::DataTransfer::FindOrAddStruct<FIntVector>(Isolate, Context, Ptr, false);
|
||||
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "Invalid argument!");
|
||||
}
|
||||
|
||||
static void FIntVectorM_IsZero(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
if (Info.Length() == 0)
|
||||
{
|
||||
if (true)
|
||||
{
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FIntVector>(Info.Holder());
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(
|
||||
Isolate, "[FIntVector::M_IsZero] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
auto MethodResult = Self->IsZero();
|
||||
auto V8Result = v8::Boolean::New(Isolate, MethodResult);
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "Invalid argument!");
|
||||
}
|
||||
|
||||
static void FIntVectorM_GetMax(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
if (Info.Length() == 0)
|
||||
{
|
||||
if (true)
|
||||
{
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FIntVector>(Info.Holder());
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(
|
||||
Isolate, "[FIntVector::M_GetMax] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
auto MethodResult = Self->GetMax();
|
||||
auto V8Result = v8::Integer::New(Isolate, MethodResult);
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "Invalid argument!");
|
||||
}
|
||||
|
||||
static void FIntVectorM_GetMin(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
if (Info.Length() == 0)
|
||||
{
|
||||
if (true)
|
||||
{
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FIntVector>(Info.Holder());
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(
|
||||
Isolate, "[FIntVector::M_GetMin] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
auto MethodResult = Self->GetMin();
|
||||
auto V8Result = v8::Integer::New(Isolate, MethodResult);
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "Invalid argument!");
|
||||
}
|
||||
|
||||
static void FIntVectorM_Size(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
if (Info.Length() == 0)
|
||||
{
|
||||
if (true)
|
||||
{
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FIntVector>(Info.Holder());
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(
|
||||
Isolate, "[FIntVector::M_Size] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
auto MethodResult = Self->Size();
|
||||
auto V8Result = v8::Integer::New(Isolate, MethodResult);
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "Invalid argument!");
|
||||
}
|
||||
|
||||
static void FIntVectorM_ToString(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
if (Info.Length() == 0)
|
||||
{
|
||||
if (true)
|
||||
{
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FIntVector>(Info.Holder());
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(
|
||||
Isolate, "[FIntVector::M_ToString] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
auto MethodResult = Self->ToString();
|
||||
auto V8Result =
|
||||
v8::String::NewFromUtf8(Isolate, TCHAR_TO_UTF8(*MethodResult), v8::NewStringType::kNormal).ToLocalChecked();
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "Invalid argument!");
|
||||
}
|
||||
|
||||
static void FIntVectorS_DivideAndRoundUp(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
if (Info.Length() == 2)
|
||||
{
|
||||
if (Info[0]->IsObject() &&
|
||||
|
||||
PUERTS_NAMESPACE::DataTransfer::IsInstanceOf<FIntVector>(Isolate, Info[0]->ToObject(Context).ToLocalChecked()) &&
|
||||
Info[1]->IsNumber())
|
||||
{
|
||||
FIntVector* Arg0 =
|
||||
PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FIntVector>(Info[0]->ToObject(Context).ToLocalChecked());
|
||||
int32 Arg1 = Info[1]->ToInteger(Context).ToLocalChecked()->Value();
|
||||
auto MethodResult = FIntVector::DivideAndRoundUp(*Arg0, Arg1);
|
||||
void* Ptr = new FIntVector(MethodResult);
|
||||
|
||||
auto V8Result = PUERTS_NAMESPACE::DataTransfer::FindOrAddStruct<FIntVector>(Isolate, Context, Ptr, false);
|
||||
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "Invalid argument!");
|
||||
}
|
||||
|
||||
static void FIntVectorS_Num(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
if (Info.Length() == 0)
|
||||
{
|
||||
if (true)
|
||||
{
|
||||
auto MethodResult = FIntVector::Num();
|
||||
auto V8Result = v8::Integer::New(Isolate, MethodResult);
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "Invalid argument!");
|
||||
}
|
||||
|
||||
static void _FIntVectorXGet_(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FIntVector>(Info.Holder());
|
||||
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "[FIntVector::X] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
|
||||
auto V8Result = v8::Integer::New(Isolate, Self->X);
|
||||
PUERTS_NAMESPACE::DataTransfer::LinkOuter<FIntVector, int32>(Context, Info.Holder(), V8Result);
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
}
|
||||
static void _FIntVectorXSet_(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FIntVector>(Info.Holder());
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "[FIntVector::X] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
auto Value = Info[0];
|
||||
|
||||
Self->X = Value->ToInteger(Context).ToLocalChecked()->Value();
|
||||
}
|
||||
static void _FIntVectorYGet_(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FIntVector>(Info.Holder());
|
||||
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "[FIntVector::Y] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
|
||||
auto V8Result = v8::Integer::New(Isolate, Self->Y);
|
||||
PUERTS_NAMESPACE::DataTransfer::LinkOuter<FIntVector, int32>(Context, Info.Holder(), V8Result);
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
}
|
||||
static void _FIntVectorYSet_(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FIntVector>(Info.Holder());
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "[FIntVector::Y] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
auto Value = Info[0];
|
||||
|
||||
Self->Y = Value->ToInteger(Context).ToLocalChecked()->Value();
|
||||
}
|
||||
static void _FIntVectorZGet_(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FIntVector>(Info.Holder());
|
||||
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "[FIntVector::Z] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
|
||||
auto V8Result = v8::Integer::New(Isolate, Self->Z);
|
||||
PUERTS_NAMESPACE::DataTransfer::LinkOuter<FIntVector, int32>(Context, Info.Holder(), V8Result);
|
||||
Info.GetReturnValue().Set(V8Result);
|
||||
}
|
||||
static void _FIntVectorZSet_(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
|
||||
auto Self = PUERTS_NAMESPACE::DataTransfer::GetPointerFast<FIntVector>(Info.Holder());
|
||||
if (!Self)
|
||||
{
|
||||
PUERTS_NAMESPACE::DataTransfer::ThrowException(Isolate, "[FIntVector::Z] Attempt to access a NULL self pointer");
|
||||
return;
|
||||
}
|
||||
auto Value = Info[0];
|
||||
|
||||
Self->Z = Value->ToInteger(Context).ToLocalChecked()->Value();
|
||||
}
|
||||
|
||||
struct AutoRegisterForFIntVector
|
||||
{
|
||||
AutoRegisterForFIntVector()
|
||||
{
|
||||
PUERTS_NAMESPACE::JSClassDefinition Def = JSClassEmptyDefinition;
|
||||
|
||||
static PUERTS_NAMESPACE::JSPropertyInfo Properties[] = {{"X", _FIntVectorXGet_, _FIntVectorXSet_},
|
||||
{"Y", _FIntVectorYGet_, _FIntVectorYSet_}, {"Z", _FIntVectorZGet_, _FIntVectorZSet_}, {0, 0, 0}};
|
||||
|
||||
static PUERTS_NAMESPACE::JSFunctionInfo Methods[] = {{"get_Item", FIntVectorM_get_Item}, {"set_Item", FIntVectorM_set_Item},
|
||||
{"op_Equality", FIntVectorM_op_Equality}, {"op_Inequality", FIntVectorM_op_Inequality},
|
||||
{"op_Multiply", FIntVectorM_op_Multiply}, {"op_Division", FIntVectorM_op_Division},
|
||||
{"op_Addition", FIntVectorM_op_Addition}, {"op_Subtraction", FIntVectorM_op_Subtraction},
|
||||
{"IsZero", FIntVectorM_IsZero}, {"GetMax", FIntVectorM_GetMax}, {"GetMin", FIntVectorM_GetMin},
|
||||
{"Size", FIntVectorM_Size}, {"ToString", FIntVectorM_ToString}, {0, 0}};
|
||||
|
||||
static PUERTS_NAMESPACE::JSFunctionInfo Functions[] = {
|
||||
{"DivideAndRoundUp", FIntVectorS_DivideAndRoundUp}, {"Num", FIntVectorS_Num}, {0, 0}};
|
||||
|
||||
Def.UETypeName = "IntVector";
|
||||
|
||||
Def.SetInitialize(_FIntVectorNew_);
|
||||
Def.Finalize = _FIntVectorDelete_;
|
||||
Def.Properties = Properties;
|
||||
Def.Methods = Methods;
|
||||
Def.Functions = Functions;
|
||||
|
||||
PUERTS_NAMESPACE::RegisterJSClass(Def);
|
||||
}
|
||||
};
|
||||
|
||||
AutoRegisterForFIntVector _AutoRegisterForFIntVector_;
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,66 @@
|
||||
#pragma once
|
||||
|
||||
#if !defined(ENGINE_INDEPENDENT_JSENV)
|
||||
#include "Engine/NetworkObjectList.h"
|
||||
#include "TimerManager.h"
|
||||
#include "Materials/MaterialInstanceDynamic.h"
|
||||
#include "Containers/Array.h"
|
||||
#include "DisplayDebugHelpers.h"
|
||||
#include "Engine/BlueprintGeneratedClass.h"
|
||||
#include "Engine/ActorChannel.h"
|
||||
#include "Engine/NetConnection.h"
|
||||
#include "Engine/Canvas.h"
|
||||
#include "GameFramework/Actor.h"
|
||||
#include "GameFramework/CameraBlockingVolume.h"
|
||||
#include "GameFramework/Character.h"
|
||||
#include "GameFramework/CharacterMovementComponent.h"
|
||||
#include "GameFramework/CheatManager.h"
|
||||
#include "GameFramework/Controller.h"
|
||||
#include "GameFramework/DamageType.h"
|
||||
#include "GameFramework/DebugTextInfo.h"
|
||||
#include "GameFramework/DefaultPawn.h"
|
||||
#include "GameFramework/DefaultPhysicsVolume.h"
|
||||
#include "GameFramework/EngineMessage.h"
|
||||
#include "GameFramework/FloatingPawnMovement.h"
|
||||
#include "GameFramework/ForceFeedbackAttenuation.h"
|
||||
#include "GameFramework/ForceFeedbackEffect.h"
|
||||
#include "GameFramework/GameMode.h"
|
||||
#include "GameFramework/GameModeBase.h"
|
||||
#include "GameFramework/GameNetworkManager.h"
|
||||
#include "GameFramework/GameSession.h"
|
||||
#include "GameFramework/GameState.h"
|
||||
#include "GameFramework/GameStateBase.h"
|
||||
#include "GameFramework/GameUserSettings.h"
|
||||
#include "GameFramework/HUD.h"
|
||||
#include "GameFramework/HUDHitBox.h"
|
||||
#include "GameFramework/Info.h"
|
||||
#include "GameFramework/InputSettings.h"
|
||||
#include "GameFramework/KillZVolume.h"
|
||||
#include "GameFramework/LocalMessage.h"
|
||||
#include "GameFramework/MovementComponent.h"
|
||||
#include "GameFramework/NavMovementComponent.h"
|
||||
#include "GameFramework/OnlineReplStructs.h"
|
||||
#include "GameFramework/OnlineSession.h"
|
||||
#include "GameFramework/PainCausingVolume.h"
|
||||
#include "GameFramework/Pawn.h"
|
||||
#include "GameFramework/PawnMovementComponent.h"
|
||||
#include "GameFramework/PhysicsVolume.h"
|
||||
#include "GameFramework/PlayerController.h"
|
||||
#include "GameFramework/PlayerInput.h"
|
||||
#include "GameFramework/PlayerMuteList.h"
|
||||
#include "GameFramework/PlayerStart.h"
|
||||
#include "GameFramework/PlayerState.h"
|
||||
#include "GameFramework/ProjectileMovementComponent.h"
|
||||
#include "GameFramework/RootMotionSource.h"
|
||||
#include "GameFramework/RotatingMovementComponent.h"
|
||||
#include "GameFramework/SaveGame.h"
|
||||
#include "GameFramework/SimpleReticle.h"
|
||||
#include "GameFramework/SpectatorPawn.h"
|
||||
#include "GameFramework/SpectatorPawnMovement.h"
|
||||
#include "GameFramework/SpringArmComponent.h"
|
||||
#include "GameFramework/TouchInterface.h"
|
||||
#include "GameFramework/Volume.h"
|
||||
#include "GameFramework/WorldSettings.h"
|
||||
|
||||
#include "Runtime/Launch/Resources/Version.h"
|
||||
#endif
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#if PLATFORM_IOS
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#include <pesapi.h>
|
||||
#include <string>
|
||||
|
||||
@interface PesapiFrameworkLoader : NSObject
|
||||
|
||||
@end
|
||||
|
||||
@implementation PesapiFrameworkLoader
|
||||
|
||||
+ (int)load:(NSString*) frameworkName entryClassName:(NSString*)entryClassName funcPtrArray:(pesapi_func_ptr*)funcPtrArray {
|
||||
NSLog(@"load addon name:%@ entry class:%@", frameworkName, entryClassName);
|
||||
|
||||
//for + function
|
||||
Class entryClass = NSClassFromString(entryClassName);
|
||||
if (entryClass) {
|
||||
SEL selector = NSSelectorFromString(@"initlib:");
|
||||
|
||||
//for + function
|
||||
IMP impl = [entryClass methodForSelector:selector];
|
||||
if (impl) {
|
||||
//@try {
|
||||
void* (*entryFunc)(Class, SEL, pesapi_func_ptr*) = (void*(*)(Class,SEL,pesapi_func_ptr*))impl;
|
||||
entryFunc(entryClass, selector, funcPtrArray);
|
||||
return 0;
|
||||
//}
|
||||
//@catch (NSException * e) {
|
||||
// NSLog(@"PesapiFrameworkLoader loadFramework exception: %@", e);
|
||||
//}
|
||||
//@finally {
|
||||
// NSLog(@"PesapiFrameworkLoader loadFramework finally");
|
||||
//}
|
||||
} else {
|
||||
NSLog(@"load addon %@ fail: can not found selector initlib:", frameworkName);
|
||||
}
|
||||
} else {
|
||||
NSLog(@"load addon %@ fail: can not found class:%@", frameworkName, entryClassName);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
int PesapiLoadFramework(std::string frameworkName, std::string entryClassName, pesapi_func_ptr* funcPtrArray)
|
||||
{
|
||||
NSString* p1 = [NSString stringWithUTF8String:frameworkName.c_str()];
|
||||
NSString* p2 = [NSString stringWithUTF8String:entryClassName.c_str()];
|
||||
return [PesapiFrameworkLoader load:p1 entryClassName:p2 funcPtrArray:funcPtrArray];
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* 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 "JSAnimGeneratedClass.h"
|
||||
|
||||
#include "JSGeneratedFunction.h"
|
||||
|
||||
void UJSAnimGeneratedClass::StaticConstructor(const FObjectInitializer& ObjectInitializer)
|
||||
{
|
||||
auto Class = static_cast<UJSAnimGeneratedClass*>(ObjectInitializer.GetClass());
|
||||
auto Object = ObjectInitializer.GetObj();
|
||||
Class->GetSuperClass()->ClassConstructor(ObjectInitializer);
|
||||
|
||||
#ifdef THREAD_SAFE
|
||||
v8::Locker Locker(Class->Isolate);
|
||||
#endif
|
||||
auto PinedDynamicInvoker = Class->DynamicInvoker.Pin();
|
||||
if (PinedDynamicInvoker)
|
||||
{
|
||||
PinedDynamicInvoker->JsConstruct(Class, Object, Class->Constructor, Class->Prototype);
|
||||
}
|
||||
}
|
||||
|
||||
void UJSAnimGeneratedClass::InitPropertiesFromCustomList(uint8* DataPtr, const uint8* DefaultDataPtr)
|
||||
{
|
||||
if (const FCustomPropertyListNode* CustomPropertyList = GetCustomPropertyListForPostConstruction())
|
||||
{
|
||||
UBlueprintGeneratedClass::InitPropertiesFromCustomList(CustomPropertyList, this, DataPtr, DefaultDataPtr);
|
||||
}
|
||||
}
|
||||
|
||||
void UJSAnimGeneratedClass::Release()
|
||||
{
|
||||
for (TFieldIterator<UFunction> It(this, EFieldIteratorFlags::IncludeSuper, EFieldIteratorFlags::ExcludeDeprecated,
|
||||
EFieldIteratorFlags::IncludeInterfaces);
|
||||
It; ++It)
|
||||
{
|
||||
if (auto Function = Cast<UJSGeneratedFunction>(*It))
|
||||
{
|
||||
// UE_LOG(LogTemp, Warning, TEXT("release: %s"), *Function->GetName());
|
||||
Function->JsFunction.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
Constructor.Reset();
|
||||
Prototype.Reset();
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "NamespaceDef.h"
|
||||
|
||||
PRAGMA_DISABLE_UNDEFINED_IDENTIFIER_WARNINGS
|
||||
#pragma warning(push, 0)
|
||||
#include "libplatform/libplatform.h"
|
||||
#include "v8.h"
|
||||
#pragma warning(pop)
|
||||
PRAGMA_ENABLE_UNDEFINED_IDENTIFIER_WARNINGS
|
||||
|
||||
#include "DynamicInvoker.h"
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Animation/AnimBlueprintGeneratedClass.h"
|
||||
#include "JSAnimGeneratedClass.generated.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS()
|
||||
class UJSAnimGeneratedClass : public UAnimBlueprintGeneratedClass
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
void InitPropertiesFromCustomList(uint8* DataPtr, const uint8* DefaultDataPtr) override;
|
||||
|
||||
void Release();
|
||||
|
||||
static void StaticConstructor(const FObjectInitializer& ObjectInitializer);
|
||||
|
||||
public:
|
||||
v8::UniquePersistent<v8::Function> Constructor;
|
||||
|
||||
v8::UniquePersistent<v8::Object> Prototype;
|
||||
|
||||
TWeakPtr<PUERTS_NAMESPACE::IDynamicInvoker, ESPMode::ThreadSafe> DynamicInvoker;
|
||||
|
||||
#ifdef THREAD_SAFE
|
||||
v8::Isolate* Isolate;
|
||||
#endif
|
||||
};
|
||||
@@ -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
|
||||
@@ -0,0 +1,385 @@
|
||||
/*
|
||||
* 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 "JSGeneratedClass.h"
|
||||
#include "Engine/Blueprint.h"
|
||||
#include "JSGeneratedFunction.h"
|
||||
#include "JSWidgetGeneratedClass.h"
|
||||
#include "JSAnimGeneratedClass.h"
|
||||
#include "JSLogger.h"
|
||||
|
||||
#define OLD_METHOD_PREFIX "__puerts_old__"
|
||||
#define MIXIN_METHOD_SUFFIX "__puerts_mixin__"
|
||||
|
||||
UClass* UJSGeneratedClass::Create(const FString& Name, UClass* Parent,
|
||||
TSharedPtr<PUERTS_NAMESPACE::IDynamicInvoker, ESPMode::ThreadSafe> DynamicInvoker, v8::Isolate* Isolate,
|
||||
v8::Local<v8::Function> Constructor, v8::Local<v8::Object> Prototype)
|
||||
{
|
||||
auto Outer = GetTransientPackage();
|
||||
UClass* Class = nullptr;
|
||||
if (Cast<UWidgetBlueprintGeneratedClass>(Parent))
|
||||
{
|
||||
auto JSGeneratedClass = NewObject<UJSWidgetGeneratedClass>(Outer, *Name, RF_Public);
|
||||
#ifdef THREAD_SAFE
|
||||
JSGeneratedClass->Isolate = Isolate;
|
||||
#endif
|
||||
JSGeneratedClass->DynamicInvoker = DynamicInvoker;
|
||||
JSGeneratedClass->Constructor = v8::UniquePersistent<v8::Function>(Isolate, Constructor);
|
||||
JSGeneratedClass->Prototype = v8::UniquePersistent<v8::Object>(Isolate, Prototype);
|
||||
JSGeneratedClass->ClassConstructor = &UJSWidgetGeneratedClass::StaticConstructor;
|
||||
Class = JSGeneratedClass;
|
||||
}
|
||||
else if (Cast<UAnimBlueprintGeneratedClass>(Parent))
|
||||
{
|
||||
auto JSGeneratedClass = NewObject<UJSAnimGeneratedClass>(Outer, *Name, RF_Public);
|
||||
#ifdef THREAD_SAFE
|
||||
JSGeneratedClass->Isolate = Isolate;
|
||||
#endif
|
||||
JSGeneratedClass->DynamicInvoker = DynamicInvoker;
|
||||
JSGeneratedClass->Constructor = v8::UniquePersistent<v8::Function>(Isolate, Constructor);
|
||||
JSGeneratedClass->Prototype = v8::UniquePersistent<v8::Object>(Isolate, Prototype);
|
||||
JSGeneratedClass->ClassConstructor = &UJSAnimGeneratedClass::StaticConstructor;
|
||||
Class = JSGeneratedClass;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto JSGeneratedClass = NewObject<UJSGeneratedClass>(Outer, *Name, RF_Public);
|
||||
#ifdef THREAD_SAFE
|
||||
JSGeneratedClass->Isolate = Isolate;
|
||||
#endif
|
||||
JSGeneratedClass->DynamicInvoker = DynamicInvoker;
|
||||
JSGeneratedClass->Constructor = v8::UniquePersistent<v8::Function>(Isolate, Constructor);
|
||||
JSGeneratedClass->Prototype = v8::UniquePersistent<v8::Object>(Isolate, Prototype);
|
||||
JSGeneratedClass->ClassConstructor = &UJSGeneratedClass::StaticConstructor;
|
||||
Class = JSGeneratedClass;
|
||||
}
|
||||
|
||||
auto Blueprint = NewObject<UBlueprint>(Outer);
|
||||
Blueprint->GeneratedClass = Class;
|
||||
#if ENGINE_MAJOR_VERSION < 5 || WITH_EDITOR
|
||||
Class->ClassGeneratedBy = Blueprint;
|
||||
#endif
|
||||
|
||||
// Set properties we need to regenerate the class with
|
||||
Class->PropertyLink = Parent->PropertyLink;
|
||||
Class->ClassWithin = Parent->ClassWithin;
|
||||
Class->ClassConfigName = Parent->ClassConfigName;
|
||||
|
||||
Class->SetSuperStruct(Parent);
|
||||
Class->ClassFlags |= (Parent->ClassFlags & (CLASS_Inherit | CLASS_ScriptInherit | CLASS_CompiledFromBlueprint));
|
||||
Class->ClassFlags |= CLASS_CompiledFromBlueprint; // AActor::Tick只有有这标记时,才会调用ReceiveTick
|
||||
Class->ClassCastFlags |= Parent->ClassCastFlags;
|
||||
|
||||
return Class;
|
||||
}
|
||||
|
||||
void UJSGeneratedClass::StaticConstructor(const FObjectInitializer& ObjectInitializer)
|
||||
{
|
||||
auto Class = ObjectInitializer.GetClass();
|
||||
auto Object = ObjectInitializer.GetObj();
|
||||
Class->GetSuperClass()->ClassConstructor(ObjectInitializer);
|
||||
|
||||
if (auto JSGeneratedClass = Cast<UJSGeneratedClass>(Class))
|
||||
{
|
||||
#ifdef THREAD_SAFE
|
||||
v8::Locker Locker(JSGeneratedClass->Isolate);
|
||||
#endif
|
||||
auto PinedDynamicInvoker = JSGeneratedClass->DynamicInvoker.Pin();
|
||||
if (PinedDynamicInvoker)
|
||||
{
|
||||
PinedDynamicInvoker->JsConstruct(JSGeneratedClass, Object, JSGeneratedClass->Constructor, JSGeneratedClass->Prototype);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UJSGeneratedClass::Override(v8::Isolate* Isolate, UClass* Class, UFunction* Super, v8::Local<v8::Function> JSImpl,
|
||||
TSharedPtr<PUERTS_NAMESPACE::IDynamicInvoker, ESPMode::ThreadSafe> DynamicInvoker, bool IsNative)
|
||||
{
|
||||
bool Existed = Super->GetOuter() == Class;
|
||||
FName FunctionName = Super->GetFName();
|
||||
if (Existed)
|
||||
{
|
||||
if (auto MaybeJSFunction = Cast<UJSGeneratedFunction>(Super)) //这种情况只需简单替换下js函数
|
||||
{
|
||||
MaybeJSFunction->DynamicInvoker = DynamicInvoker;
|
||||
MaybeJSFunction->FunctionTranslator = std::make_unique<PUERTS_NAMESPACE::FFunctionTranslator>(Super, false);
|
||||
MaybeJSFunction->JsFunction.Reset(Isolate, JSImpl);
|
||||
MaybeJSFunction->SetNativeFunc(&UJSGeneratedFunction::execCallJS);
|
||||
return;
|
||||
}
|
||||
// UE_LOG(LogTemp, Error, TEXT("replace %s of %s"), *Super->GetName(), *Class->GetName());
|
||||
//同一Outer下的同名对象只能有一个...
|
||||
Super->Rename(*FString::Printf(TEXT("%s%s"), TEXT(OLD_METHOD_PREFIX), *Super->GetName()), Class,
|
||||
REN_DontCreateRedirectors | REN_DoNotDirty | REN_ForceNoResetLoaders);
|
||||
Class->AddFunctionToFunctionMap(Super, Super->GetFName());
|
||||
// UE_LOG(LogTemp, Error, TEXT("rename to %s"), *Super->GetName());
|
||||
}
|
||||
|
||||
// UE_LOG(LogTemp, Error, TEXT("new function name %s"), *FunctionName.ToString());
|
||||
UJSGeneratedFunction* Function = Cast<UJSGeneratedFunction>(
|
||||
StaticDuplicateObject(Super, Class, FunctionName, RF_Transient, UJSGeneratedFunction::StaticClass()));
|
||||
|
||||
for (TFieldIterator<UFunction> It(Class, EFieldIteratorFlags::IncludeSuper, EFieldIteratorFlags::ExcludeDeprecated,
|
||||
EFieldIteratorFlags::IncludeInterfaces);
|
||||
It; ++It)
|
||||
{
|
||||
if (*It == Function)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!Existed)
|
||||
{
|
||||
// UE_LOG(LogTemp, Error, TEXT("new function %s"), *FunctionName.ToString());
|
||||
Function->SetSuperStruct(Super);
|
||||
}
|
||||
else
|
||||
{
|
||||
// UE_LOG(LogTemp, Error, TEXT("replace function %s"), *FunctionName.ToString());
|
||||
Function->SetSuperStruct(Super->GetSuperStruct());
|
||||
}
|
||||
|
||||
Function->Bind();
|
||||
Function->StaticLink(true);
|
||||
|
||||
if (IsNative)
|
||||
{
|
||||
Function->FunctionFlags |= FUNC_Native; //让UE不走解析
|
||||
}
|
||||
|
||||
Function->SetNativeFunc(&UJSGeneratedFunction::execCallJS);
|
||||
|
||||
Function->JsFunction = v8::UniquePersistent<v8::Function>(Isolate, JSImpl);
|
||||
Function->DynamicInvoker = DynamicInvoker;
|
||||
Function->FunctionTranslator = std::make_unique<PUERTS_NAMESPACE::FFunctionTranslator>(Function, false);
|
||||
|
||||
if (Existed)
|
||||
{
|
||||
Function->Next = Super->Next;
|
||||
if (Class->Children == Super) // first one
|
||||
{
|
||||
Class->Children = Function;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto P = Class->Children;
|
||||
while (P && P->Next != Super)
|
||||
P = P->Next;
|
||||
check(P);
|
||||
P->Next = Function;
|
||||
}
|
||||
Class->RemoveFunctionFromFunctionMap(Super);
|
||||
}
|
||||
else
|
||||
{
|
||||
Function->Next = Class->Children;
|
||||
Class->Children = Function;
|
||||
}
|
||||
Class->AddFunctionToFunctionMap(Function, Function->GetFName());
|
||||
}
|
||||
|
||||
UFunction* UJSGeneratedClass::Mixin(v8::Isolate* Isolate, UClass* Class, UFunction* Super,
|
||||
TSharedPtr<PUERTS_NAMESPACE::IDynamicInvoker, ESPMode::ThreadSafe> DynamicInvoker, bool TakeJsObjectRef, bool Warning)
|
||||
{
|
||||
bool Existed = Super->GetOuter() == Class;
|
||||
|
||||
if (!Existed)
|
||||
{
|
||||
UFunction* Tmp =
|
||||
Cast<UFunction>(StaticDuplicateObject(Super, Class, Super->GetFName(), RF_AllFlags, UFunction::StaticClass()));
|
||||
Tmp->SetSuperStruct(Super);
|
||||
Tmp->Next = Class->Children;
|
||||
Class->Children = Tmp;
|
||||
Class->AddFunctionToFunctionMap(Tmp, Tmp->GetFName());
|
||||
Tmp->SetFlags(Tmp->GetFlags() | RF_Transient);
|
||||
Super = Tmp;
|
||||
}
|
||||
auto MaybeJSFunction = Cast<UJSGeneratedFunction>(Super);
|
||||
if (!MaybeJSFunction)
|
||||
{
|
||||
MaybeJSFunction = UJSGeneratedFunction::GetJSGeneratedFunctionFromScript(Super);
|
||||
}
|
||||
if (MaybeJSFunction)
|
||||
{
|
||||
if (Warning)
|
||||
{
|
||||
UE_LOG(Puerts, Warning, TEXT("Try to mixin a function[%s:%s] already mixin by anthor vm"), *Class->GetName(),
|
||||
*Super->GetName());
|
||||
}
|
||||
return MaybeJSFunction;
|
||||
}
|
||||
|
||||
const FString FunctionName = *FString::Printf(TEXT("%s%s"), *Super->GetName(), TEXT(MIXIN_METHOD_SUFFIX));
|
||||
|
||||
// "Failed to bind native" warning
|
||||
Class->AddNativeFunction(*FunctionName, &UJSGeneratedFunction::execCallMixin);
|
||||
UJSGeneratedFunction* Function = Cast<UJSGeneratedFunction>(
|
||||
StaticDuplicateObject(Super, Class, *FunctionName, RF_AllFlags, UJSGeneratedFunction::StaticClass()));
|
||||
Function->SetFlags(Function->GetFlags() | RF_Transient);
|
||||
|
||||
for (TFieldIterator<UFunction> It(Class, EFieldIteratorFlags::IncludeSuper, EFieldIteratorFlags::ExcludeDeprecated,
|
||||
EFieldIteratorFlags::IncludeInterfaces);
|
||||
It; ++It)
|
||||
{
|
||||
if (*It == Function)
|
||||
{
|
||||
return Function;
|
||||
}
|
||||
}
|
||||
|
||||
Function->SetSuperStruct(Super->GetSuperStruct());
|
||||
|
||||
Function->DynamicInvoker = DynamicInvoker;
|
||||
Function->FunctionTranslator = std::make_unique<PUERTS_NAMESPACE::FFunctionTranslator>(Super, false);
|
||||
Function->TakeJsObjectRef = TakeJsObjectRef;
|
||||
|
||||
Function->Next = Class->Children;
|
||||
Class->Children = Function;
|
||||
Class->AddFunctionToFunctionMap(Function, Function->GetFName());
|
||||
|
||||
Function->FunctionFlags |= FUNC_Native; //让UE不走解析
|
||||
Function->SetNativeFunc(&UJSGeneratedFunction::execCallMixin);
|
||||
Function->Bind();
|
||||
Function->StaticLink(true);
|
||||
Function->ClearInternalFlags(EInternalObjectFlags::Native);
|
||||
|
||||
if (Class->HasAnyInternalFlags(EInternalObjectFlags::RootSet))
|
||||
{
|
||||
Function->AddToRoot();
|
||||
}
|
||||
|
||||
Function->Original = Super;
|
||||
Function->OriginalFunc = Super->GetNativeFunc();
|
||||
Function->OriginalFunctionFlags = Super->FunctionFlags;
|
||||
Super->FunctionFlags |= FUNC_Native; //让UE不走解析
|
||||
Super->SetNativeFunc(&UJSGeneratedFunction::execCallMixin);
|
||||
Class->AddNativeFunction(*Super->GetName(), &UJSGeneratedFunction::execCallMixin);
|
||||
UJSGeneratedFunction::SetJSGeneratedFunctionToScript(Super, Function);
|
||||
|
||||
return Function;
|
||||
}
|
||||
|
||||
void UJSGeneratedClass::Restore(UClass* Class)
|
||||
{
|
||||
FString OrphanedClassString = FString::Printf(TEXT("ORPHANED_DATA_ONLY_%s"), *Class->GetName());
|
||||
FName OrphanedClassName =
|
||||
MakeUniqueObjectName(GetTransientPackage(), UBlueprintGeneratedClass::StaticClass(), FName(*OrphanedClassString));
|
||||
UClass* OrphanedClass = NewObject<UBlueprintGeneratedClass>(GetTransientPackage(), OrphanedClassName, RF_Public | RF_Transient);
|
||||
#if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION > 0
|
||||
OrphanedClass->CppClassStaticFunctions = Class->CppClassStaticFunctions;
|
||||
#else
|
||||
OrphanedClass->ClassAddReferencedObjects = Class->AddReferencedObjects;
|
||||
#endif
|
||||
OrphanedClass->ClassFlags |= CLASS_CompiledFromBlueprint;
|
||||
#if ENGINE_MAJOR_VERSION < 5 || WITH_EDITOR
|
||||
OrphanedClass->ClassGeneratedBy = Class->ClassGeneratedBy;
|
||||
#endif
|
||||
|
||||
#if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION > 2
|
||||
UField** PP = nullptr;
|
||||
UField* ChildrenPtr = Class->Children.Get();
|
||||
PP = &ChildrenPtr;
|
||||
#else
|
||||
auto PP = &Class->Children;
|
||||
#endif
|
||||
while (*PP)
|
||||
{
|
||||
if (auto JGF = Cast<UJSGeneratedFunction>(*PP)) // to delete
|
||||
{
|
||||
if (JGF->Original)
|
||||
{
|
||||
if (JGF->Script.Num() == 0)
|
||||
{
|
||||
JGF->Original->Script.Empty();
|
||||
}
|
||||
else
|
||||
{
|
||||
JGF->Original->Script = JGF->Script;
|
||||
}
|
||||
JGF->Original->SetNativeFunc(JGF->OriginalFunc);
|
||||
Class->AddNativeFunction(*JGF->Original->GetName(), JGF->OriginalFunc);
|
||||
JGF->Original->FunctionFlags = JGF->OriginalFunctionFlags;
|
||||
}
|
||||
JGF->JsFunction.Reset();
|
||||
|
||||
*PP = JGF->Next;
|
||||
#if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION > 2
|
||||
if (PP == &ChildrenPtr)
|
||||
{
|
||||
Class->Children = ChildrenPtr;
|
||||
}
|
||||
#endif
|
||||
|
||||
Class->RemoveFunctionFromFunctionMap(JGF);
|
||||
if (JGF->IsRooted())
|
||||
{
|
||||
JGF->RemoveFromRoot();
|
||||
}
|
||||
JGF->Rename(nullptr, OrphanedClass, REN_DontCreateRedirectors | REN_DoNotDirty | REN_ForceNoResetLoaders);
|
||||
FLinkerLoad::InvalidateExport(JGF);
|
||||
}
|
||||
else
|
||||
{
|
||||
PP = &(*PP)->Next;
|
||||
}
|
||||
}
|
||||
#if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION > 2
|
||||
PP = &ChildrenPtr;
|
||||
#else
|
||||
PP = &Class->Children;
|
||||
#endif
|
||||
while (*PP)
|
||||
{
|
||||
if (auto Function = Cast<UFunction>(*PP))
|
||||
{
|
||||
if (Function->GetName().StartsWith(TEXT(OLD_METHOD_PREFIX)))
|
||||
{
|
||||
Class->RemoveFunctionFromFunctionMap(Function);
|
||||
Function->Rename(*Function->GetName().Mid(strlen(OLD_METHOD_PREFIX)), Class,
|
||||
REN_DontCreateRedirectors | REN_DoNotDirty | REN_ForceNoResetLoaders);
|
||||
Class->AddFunctionToFunctionMap(Function, Function->GetFName());
|
||||
}
|
||||
}
|
||||
PP = &(*PP)->Next;
|
||||
}
|
||||
Class->ClearFunctionMapsCaches();
|
||||
for (TObjectIterator<UClass> It; It; ++It)
|
||||
{
|
||||
if (Class != *It && It->IsChildOf(Class) && !It->HasAnyClassFlags(CLASS_Abstract) &&
|
||||
!It->GetName().StartsWith(TEXT("REINST_")))
|
||||
{
|
||||
It->ClearFunctionMapsCaches();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UJSGeneratedClass::InitPropertiesFromCustomList(uint8* DataPtr, const uint8* DefaultDataPtr)
|
||||
{
|
||||
if (const FCustomPropertyListNode* CustomPropertyList = GetCustomPropertyListForPostConstruction())
|
||||
{
|
||||
UBlueprintGeneratedClass::InitPropertiesFromCustomList(CustomPropertyList, this, DataPtr, DefaultDataPtr);
|
||||
}
|
||||
}
|
||||
|
||||
void UJSGeneratedClass::Release()
|
||||
{
|
||||
for (TFieldIterator<UFunction> It(this, EFieldIteratorFlags::IncludeSuper, EFieldIteratorFlags::ExcludeDeprecated,
|
||||
EFieldIteratorFlags::IncludeInterfaces);
|
||||
It; ++It)
|
||||
{
|
||||
if (auto Function = Cast<UJSGeneratedFunction>(*It))
|
||||
{
|
||||
// UE_LOG(LogTemp, Warning, TEXT("release: %s"), *Function->GetName());
|
||||
Function->JsFunction.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
Constructor.Reset();
|
||||
Prototype.Reset();
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "NamespaceDef.h"
|
||||
|
||||
PRAGMA_DISABLE_UNDEFINED_IDENTIFIER_WARNINGS
|
||||
#pragma warning(push, 0)
|
||||
#include "libplatform/libplatform.h"
|
||||
#include "v8.h"
|
||||
#pragma warning(pop)
|
||||
PRAGMA_ENABLE_UNDEFINED_IDENTIFIER_WARNINGS
|
||||
|
||||
#include "DynamicInvoker.h"
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Engine/BlueprintGeneratedClass.h"
|
||||
#include "JSGeneratedClass.generated.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS()
|
||||
class UJSGeneratedClass : public UBlueprintGeneratedClass
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
static UClass* Create(const FString& Name, UClass* Parent,
|
||||
TSharedPtr<PUERTS_NAMESPACE::IDynamicInvoker, ESPMode::ThreadSafe> DynamicInvoker, v8::Isolate* Isolate,
|
||||
v8::Local<v8::Function> Constructor, v8::Local<v8::Object> Prototype);
|
||||
|
||||
static void Override(v8::Isolate* Isolate, UClass* Class, UFunction* Super, v8::Local<v8::Function> JSImpl,
|
||||
TSharedPtr<PUERTS_NAMESPACE::IDynamicInvoker, ESPMode::ThreadSafe> DynamicInvoker, bool IsNative);
|
||||
|
||||
static UFunction* Mixin(v8::Isolate* Isolate, UClass* Class, UFunction* Super,
|
||||
TSharedPtr<PUERTS_NAMESPACE::IDynamicInvoker, ESPMode::ThreadSafe> DynamicInvoker, bool TakeJsObjectRef, bool Warning);
|
||||
|
||||
static void Restore(UClass* Class);
|
||||
|
||||
void InitPropertiesFromCustomList(uint8* DataPtr, const uint8* DefaultDataPtr) override;
|
||||
|
||||
void Release();
|
||||
|
||||
static void StaticConstructor(const FObjectInitializer& ObjectInitializer);
|
||||
|
||||
public:
|
||||
v8::UniquePersistent<v8::Function> Constructor;
|
||||
|
||||
v8::UniquePersistent<v8::Object> Prototype;
|
||||
|
||||
TWeakPtr<PUERTS_NAMESPACE::IDynamicInvoker, ESPMode::ThreadSafe> DynamicInvoker;
|
||||
|
||||
#ifdef THREAD_SAFE
|
||||
v8::Isolate* Isolate;
|
||||
#endif
|
||||
};
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* 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 "JSGeneratedFunction.h"
|
||||
|
||||
DEFINE_FUNCTION(UJSGeneratedFunction::execCallJS)
|
||||
{
|
||||
#if !defined(ENGINE_INDEPENDENT_JSENV)
|
||||
UJSGeneratedFunction* Func = Cast<UJSGeneratedFunction>(Stack.CurrentNativeFunction ? Stack.CurrentNativeFunction : Stack.Node);
|
||||
check(Func);
|
||||
// UE_LOG(LogTemp, Warning, TEXT("overrided function called, %s(%p)"), *Func->GetName(), Func);
|
||||
|
||||
if (Func)
|
||||
{
|
||||
auto PinedDynamicInvoker = Func->DynamicInvoker.Pin();
|
||||
if (PinedDynamicInvoker)
|
||||
{
|
||||
PinedDynamicInvoker->InvokeJsMethod(Context, Func, Stack, RESULT_PARAM);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
DEFINE_FUNCTION(UJSGeneratedFunction::execCallMixin)
|
||||
{
|
||||
#if !defined(ENGINE_INDEPENDENT_JSENV)
|
||||
UFunction* Func = Stack.CurrentNativeFunction ? Stack.CurrentNativeFunction : Stack.Node;
|
||||
UJSGeneratedFunction* JsFunc = Cast<UJSGeneratedFunction>(Func);
|
||||
if (!JsFunc)
|
||||
{
|
||||
JsFunc = GetJSGeneratedFunctionFromScript(Func);
|
||||
}
|
||||
check(JsFunc);
|
||||
// UE_LOG(LogTemp, Warning, TEXT("overrided function called, %s(%p)"), *Func->GetName(), Func);
|
||||
|
||||
if (JsFunc)
|
||||
{
|
||||
auto PinedDynamicInvoker = JsFunc->DynamicInvoker.Pin();
|
||||
if (PinedDynamicInvoker)
|
||||
{
|
||||
PinedDynamicInvoker->InvokeMixinMethod(Context, JsFunc, Stack, RESULT_PARAM);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "NamespaceDef.h"
|
||||
|
||||
PRAGMA_DISABLE_UNDEFINED_IDENTIFIER_WARNINGS
|
||||
#pragma warning(push, 0)
|
||||
#include "libplatform/libplatform.h"
|
||||
#include "v8.h"
|
||||
#pragma warning(pop)
|
||||
PRAGMA_ENABLE_UNDEFINED_IDENTIFIER_WARNINGS
|
||||
|
||||
#include "DynamicInvoker.h"
|
||||
#include "FunctionTranslator.h"
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "UObject/NoExportTypes.h"
|
||||
#include "JSGeneratedFunction.generated.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS()
|
||||
class UJSGeneratedFunction : public UFunction
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
DECLARE_FUNCTION(execCallJS);
|
||||
|
||||
DECLARE_FUNCTION(execCallMixin);
|
||||
|
||||
v8::UniquePersistent<v8::Function> JsFunction;
|
||||
|
||||
TWeakPtr<PUERTS_NAMESPACE::IDynamicInvoker, ESPMode::ThreadSafe> DynamicInvoker;
|
||||
|
||||
std::unique_ptr<PUERTS_NAMESPACE::FFunctionTranslator> FunctionTranslator;
|
||||
|
||||
bool TakeJsObjectRef;
|
||||
|
||||
UFunction* Original = nullptr;
|
||||
|
||||
FNativeFuncPtr OriginalFunc = nullptr;
|
||||
|
||||
EFunctionFlags OriginalFunctionFlags;
|
||||
|
||||
static constexpr uint8 GEN_FUNC_MAGIC = 107;
|
||||
|
||||
FORCEINLINE static void SetJSGeneratedFunctionToScript(UFunction* InFunc, UJSGeneratedFunction* JsGenFunc)
|
||||
{
|
||||
JsGenFunc->Script = InFunc->Script;
|
||||
InFunc->Script.Empty();
|
||||
InFunc->Script.AddUninitialized(3 + sizeof(int64));
|
||||
uint8* Code = InFunc->Script.GetData();
|
||||
*(Code++) = EX_ByteConst;
|
||||
*(Code++) = GEN_FUNC_MAGIC;
|
||||
*(Code++) = EX_Int64Const;
|
||||
FPlatformMemory::WriteUnaligned<UJSGeneratedFunction*>(Code, JsGenFunc);
|
||||
}
|
||||
|
||||
FORCEINLINE static UJSGeneratedFunction* GetJSGeneratedFunctionFromScript(UFunction* InFunc)
|
||||
{
|
||||
const uint8* Code = InFunc->Script.GetData();
|
||||
if (Code && InFunc->Script.Num() >= (3 + sizeof(int64)) && EX_ByteConst == Code[0] && GEN_FUNC_MAGIC == Code[1] &&
|
||||
EX_Int64Const == Code[2])
|
||||
{
|
||||
return FPlatformMemory::ReadUnaligned<UJSGeneratedFunction*>(&Code[3]);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* 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 "JSLogger.h"
|
||||
|
||||
DEFINE_LOG_CATEGORY(Puerts);
|
||||
|
||||
namespace PUERTS_NAMESPACE
|
||||
{
|
||||
void FDefaultLogger::Log(const FString& Message) const
|
||||
{
|
||||
UE_LOG(Puerts, Log, TEXT("(0x%p) %s"), this, *Message);
|
||||
}
|
||||
|
||||
void FDefaultLogger::Info(const FString& Message) const
|
||||
{
|
||||
UE_LOG(Puerts, Display, TEXT("(0x%p) %s"), this, *Message);
|
||||
}
|
||||
|
||||
void FDefaultLogger::Warn(const FString& Message) const
|
||||
{
|
||||
UE_LOG(Puerts, Warning, TEXT("(0x%p) %s"), this, *Message);
|
||||
}
|
||||
|
||||
void FDefaultLogger::Error(const FString& Message) const
|
||||
{
|
||||
UE_LOG(Puerts, Error, TEXT("(0x%p) %s"), this, *Message);
|
||||
}
|
||||
|
||||
} // namespace PUERTS_NAMESPACE
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* 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 "JSWidgetGeneratedClass.h"
|
||||
#include "JSGeneratedFunction.h"
|
||||
|
||||
void UJSWidgetGeneratedClass::StaticConstructor(const FObjectInitializer& ObjectInitializer)
|
||||
{
|
||||
auto Class = static_cast<UJSWidgetGeneratedClass*>(ObjectInitializer.GetClass());
|
||||
auto Object = ObjectInitializer.GetObj();
|
||||
Class->GetSuperClass()->ClassConstructor(ObjectInitializer);
|
||||
|
||||
#ifdef THREAD_SAFE
|
||||
v8::Locker Locker(Class->Isolate);
|
||||
#endif
|
||||
auto PinedDynamicInvoker = Class->DynamicInvoker.Pin();
|
||||
if (PinedDynamicInvoker)
|
||||
{
|
||||
PinedDynamicInvoker->JsConstruct(Class, Object, Class->Constructor, Class->Prototype);
|
||||
}
|
||||
}
|
||||
|
||||
void UJSWidgetGeneratedClass::InitPropertiesFromCustomList(uint8* DataPtr, const uint8* DefaultDataPtr)
|
||||
{
|
||||
if (const FCustomPropertyListNode* CustomPropertyList = GetCustomPropertyListForPostConstruction())
|
||||
{
|
||||
UBlueprintGeneratedClass::InitPropertiesFromCustomList(CustomPropertyList, this, DataPtr, DefaultDataPtr);
|
||||
}
|
||||
}
|
||||
|
||||
void UJSWidgetGeneratedClass::Release()
|
||||
{
|
||||
for (TFieldIterator<UFunction> It(this, EFieldIteratorFlags::IncludeSuper, EFieldIteratorFlags::ExcludeDeprecated,
|
||||
EFieldIteratorFlags::IncludeInterfaces);
|
||||
It; ++It)
|
||||
{
|
||||
if (auto Function = Cast<UJSGeneratedFunction>(*It))
|
||||
{
|
||||
// UE_LOG(LogTemp, Warning, TEXT("release: %s"), *Function->GetName());
|
||||
Function->JsFunction.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
Constructor.Reset();
|
||||
Prototype.Reset();
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "NamespaceDef.h"
|
||||
|
||||
PRAGMA_DISABLE_UNDEFINED_IDENTIFIER_WARNINGS
|
||||
#pragma warning(push, 0)
|
||||
#include "libplatform/libplatform.h"
|
||||
#include "v8.h"
|
||||
#pragma warning(pop)
|
||||
PRAGMA_ENABLE_UNDEFINED_IDENTIFIER_WARNINGS
|
||||
|
||||
#include "DynamicInvoker.h"
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Blueprint/WidgetBlueprintGeneratedClass.h"
|
||||
#include "JSWidgetGeneratedClass.generated.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS()
|
||||
class UJSWidgetGeneratedClass : public UWidgetBlueprintGeneratedClass
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
void InitPropertiesFromCustomList(uint8* DataPtr, const uint8* DefaultDataPtr) override;
|
||||
|
||||
static void StaticConstructor(const FObjectInitializer& ObjectInitializer);
|
||||
|
||||
void Release();
|
||||
|
||||
public:
|
||||
v8::UniquePersistent<v8::Function> Constructor;
|
||||
|
||||
v8::UniquePersistent<v8::Object> Prototype;
|
||||
|
||||
TWeakPtr<PUERTS_NAMESPACE::IDynamicInvoker, ESPMode::ThreadSafe> DynamicInvoker;
|
||||
|
||||
#ifdef THREAD_SAFE
|
||||
v8::Isolate* Isolate;
|
||||
#endif
|
||||
};
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* 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 "JsEnv.h"
|
||||
#include "JsEnvImpl.h"
|
||||
|
||||
namespace PUERTS_NAMESPACE
|
||||
{
|
||||
FJsEnv::FJsEnv(const FString& ScriptRoot)
|
||||
{
|
||||
GameScript = std::make_unique<FJsEnvImpl>(ScriptRoot);
|
||||
}
|
||||
|
||||
FJsEnv::FJsEnv(std::shared_ptr<IJSModuleLoader> InModuleLoader, std::shared_ptr<ILogger> InLogger, int InDebugPort,
|
||||
std::function<void(const FString&)> InOnSourceLoadedCallback, const FString InFlags, void* InExternalRuntime,
|
||||
void* InExternalContext)
|
||||
{
|
||||
GameScript = std::make_unique<FJsEnvImpl>(
|
||||
std::move(InModuleLoader), InLogger, InDebugPort, InOnSourceLoadedCallback, InFlags, InExternalRuntime, InExternalContext);
|
||||
}
|
||||
|
||||
void FJsEnv::Start(const FString& ModuleName, const TArray<TPair<FString, UObject*>>& Arguments)
|
||||
{
|
||||
GameScript->Start(ModuleName, Arguments);
|
||||
}
|
||||
|
||||
bool FJsEnv::IdleNotificationDeadline(double DeadlineInSeconds)
|
||||
{
|
||||
return GameScript->IdleNotificationDeadline(DeadlineInSeconds);
|
||||
}
|
||||
|
||||
void FJsEnv::LowMemoryNotification()
|
||||
{
|
||||
GameScript->LowMemoryNotification();
|
||||
}
|
||||
|
||||
void FJsEnv::RequestMinorGarbageCollectionForTesting()
|
||||
{
|
||||
GameScript->RequestMinorGarbageCollectionForTesting();
|
||||
}
|
||||
|
||||
void FJsEnv::RequestFullGarbageCollectionForTesting()
|
||||
{
|
||||
GameScript->RequestFullGarbageCollectionForTesting();
|
||||
}
|
||||
|
||||
void FJsEnv::WaitDebugger(double timeout)
|
||||
{
|
||||
GameScript->WaitDebugger(timeout);
|
||||
}
|
||||
|
||||
#if !defined(ENGINE_INDEPENDENT_JSENV)
|
||||
void FJsEnv::TryBindJs(const class UObjectBase* InObject)
|
||||
{
|
||||
GameScript->TryBindJs(InObject);
|
||||
}
|
||||
|
||||
void FJsEnv::RebindJs()
|
||||
{
|
||||
GameScript->RebindJs();
|
||||
}
|
||||
#endif
|
||||
|
||||
FString FJsEnv::CurrentStackTrace()
|
||||
{
|
||||
return GameScript->CurrentStackTrace();
|
||||
}
|
||||
|
||||
void FJsEnv::InitExtensionMethodsMap()
|
||||
{
|
||||
GameScript->InitExtensionMethodsMap();
|
||||
}
|
||||
|
||||
void FJsEnv::ReloadModule(FName ModuleName, const FString& JsSource)
|
||||
{
|
||||
GameScript->ReloadModule(ModuleName, JsSource);
|
||||
}
|
||||
|
||||
void FJsEnv::ReloadSource(const FString& Path, const std::string& JsSource)
|
||||
{
|
||||
GameScript->ReloadSource(Path, JsSource);
|
||||
}
|
||||
|
||||
void FJsEnv::OnSourceLoaded(std::function<void(const FString&)> Callback)
|
||||
{
|
||||
GameScript->OnSourceLoaded(Callback);
|
||||
}
|
||||
|
||||
} // namespace PUERTS_NAMESPACE
|
||||
@@ -0,0 +1,186 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#if !defined(ENGINE_INDEPENDENT_JSENV)
|
||||
#include "JsEnvGroup.h"
|
||||
#include "JsEnvImpl.h"
|
||||
#include "TsDynamicInvoker.h"
|
||||
#include "DynamicInvoker.h"
|
||||
#include "PuertsNamespaceDef.h"
|
||||
|
||||
namespace PUERTS_NAMESPACE
|
||||
{
|
||||
class FGroupDynamicInvoker : public ITsDynamicInvoker, public IDynamicInvoker
|
||||
{
|
||||
public:
|
||||
FGroupDynamicInvoker(std::vector<FJsEnvImpl*> InJsEnvs) : JsEnvs(InJsEnvs)
|
||||
{
|
||||
}
|
||||
|
||||
FORCEINLINE int GetSelectIndex(UObject* Object)
|
||||
{
|
||||
int Size = JsEnvs.size();
|
||||
int Index = Selector ? Selector(Object, Size) : 0;
|
||||
return (Index > 0 && Index < Size) ? Index : 0;
|
||||
}
|
||||
|
||||
void TsConstruct(UTypeScriptGeneratedClass* Class, UObject* Object) override
|
||||
{
|
||||
// 对于cdo,应该在所有的虚拟机中调用construct,因为cdo并没有明确的jsenv
|
||||
// 不过不大确定cdo的这样判断够不够
|
||||
// JsEnvs[GetSelectIndex(Object)]->TsConstruct(Class, Object);
|
||||
if (Object->HasAnyFlags(RF_ClassDefaultObject | RF_ArchetypeObject | RF_WasLoaded))
|
||||
{
|
||||
for (int i = 0; i < JsEnvs.size(); i++)
|
||||
{
|
||||
JsEnvs[i]->TsConstruct(Class, Object);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
JsEnvs[GetSelectIndex(Object)]->TsConstruct(Class, Object);
|
||||
}
|
||||
}
|
||||
|
||||
void InvokeTsMethod(UObject* ContextObject, UFunction* Function, FFrame& Stack, void* RESULT_PARAM) override
|
||||
{
|
||||
JsEnvs[GetSelectIndex(ContextObject)]->InvokeTsMethod(ContextObject, Function, Stack, RESULT_PARAM);
|
||||
}
|
||||
|
||||
void NotifyReBind(UTypeScriptGeneratedClass* Class) override
|
||||
{
|
||||
for (int i = 0; i < JsEnvs.size(); i++)
|
||||
{
|
||||
JsEnvs[i]->NotifyReBind(Class);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void InvokeDelegateCallback(UDynamicDelegateProxy* Proxy, void* Params) override
|
||||
{
|
||||
ensureMsgf(false, TEXT("InvokeDelegateCallback in GroupDynamicInvoker"));
|
||||
}
|
||||
#if !defined(ENGINE_INDEPENDENT_JSENV)
|
||||
virtual void JsConstruct(UClass* Class, UObject* Object, const v8::UniquePersistent<v8::Function>& Constructor,
|
||||
const v8::UniquePersistent<v8::Object>& Prototype) override
|
||||
{
|
||||
ensureMsgf(false, TEXT("JsConstruct in GroupDynamicInvoker"));
|
||||
}
|
||||
|
||||
virtual void InvokeJsMethod(UObject* ContextObject, UJSGeneratedFunction* Function, FFrame& Stack, void* RESULT_PARAM) override
|
||||
{
|
||||
ensureMsgf(false, TEXT("InvokeJsMethod in GroupDynamicInvoker"));
|
||||
}
|
||||
|
||||
virtual void InvokeMixinMethod(
|
||||
UObject* ContextObject, UJSGeneratedFunction* Function, FFrame& Stack, void* RESULT_PARAM) override
|
||||
{
|
||||
JsEnvs[GetSelectIndex(ContextObject)]->InvokeMixinMethod(ContextObject, Function, Stack, RESULT_PARAM);
|
||||
}
|
||||
#endif
|
||||
|
||||
std::vector<FJsEnvImpl*> JsEnvs;
|
||||
|
||||
std::function<int(UObject*, int)> Selector;
|
||||
|
||||
virtual ~FGroupDynamicInvoker()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
FJsEnvGroup::FJsEnvGroup(int Size, const FString& ScriptRoot)
|
||||
{
|
||||
check(Size > 1);
|
||||
for (int i = 0; i < Size; i++)
|
||||
{
|
||||
JsEnvList.push_back(std::make_shared<FJsEnvImpl>(ScriptRoot));
|
||||
}
|
||||
Init();
|
||||
}
|
||||
|
||||
FJsEnvGroup::FJsEnvGroup(int Size, std::shared_ptr<IJSModuleLoader> InModuleLoader, std::shared_ptr<ILogger> InLogger,
|
||||
int InDebugStartPort, std::function<void(const FString&)> InOnSourceLoadedCallback, const FString InFlags,
|
||||
void* InExternalRuntime, void* InExternalContext)
|
||||
{
|
||||
check(Size > 1);
|
||||
std::shared_ptr<IJSModuleLoader> SharedModuleLoader = std::move(InModuleLoader);
|
||||
for (int i = 0; i < Size; i++)
|
||||
{
|
||||
JsEnvList.push_back(std::make_shared<FJsEnvImpl>(SharedModuleLoader, InLogger, InDebugStartPort + i,
|
||||
InOnSourceLoadedCallback, InFlags, InExternalRuntime, InExternalContext));
|
||||
}
|
||||
Init();
|
||||
}
|
||||
|
||||
void FJsEnvGroup::Init()
|
||||
{
|
||||
std::vector<FJsEnvImpl*> JsEnvs;
|
||||
for (int i = 0; i < JsEnvList.size(); i++)
|
||||
{
|
||||
JsEnvs.push_back(static_cast<FJsEnvImpl*>(JsEnvList[i].get()));
|
||||
}
|
||||
auto GroupDynamicInvoker = MakeShared<FGroupDynamicInvoker, ESPMode::ThreadSafe>(JsEnvs);
|
||||
for (int i = 0; i < JsEnvs.size(); i++)
|
||||
{
|
||||
JsEnvs[i]->TsDynamicInvoker = GroupDynamicInvoker;
|
||||
JsEnvs[i]->MixinInvoker = GroupDynamicInvoker;
|
||||
}
|
||||
}
|
||||
|
||||
FJsEnvGroup::~FJsEnvGroup()
|
||||
{
|
||||
JsEnvList.clear();
|
||||
}
|
||||
|
||||
void FJsEnvGroup::TryBindJs(const class UObjectBase* InObject)
|
||||
{
|
||||
for (int i = 0; i < JsEnvList.size(); i++)
|
||||
{
|
||||
JsEnvList[i]->TryBindJs(InObject);
|
||||
}
|
||||
}
|
||||
|
||||
void FJsEnvGroup::RebindJs()
|
||||
{
|
||||
for (int i = 0; i < JsEnvList.size(); i++)
|
||||
{
|
||||
JsEnvList[i]->RebindJs();
|
||||
}
|
||||
}
|
||||
|
||||
void FJsEnvGroup::InitExtensionMethodsMap()
|
||||
{
|
||||
for (int i = 0; i < JsEnvList.size(); i++)
|
||||
{
|
||||
JsEnvList[i]->InitExtensionMethodsMap();
|
||||
}
|
||||
}
|
||||
|
||||
void FJsEnvGroup::ReloadModule(FName ModuleName, const FString& JsSource)
|
||||
{
|
||||
for (int i = 0; i < JsEnvList.size(); i++)
|
||||
{
|
||||
JsEnvList[i]->ReloadModule(ModuleName, JsSource);
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<IJsEnv> FJsEnvGroup::Get(int Index)
|
||||
{
|
||||
return JsEnvList[Index];
|
||||
}
|
||||
|
||||
void FJsEnvGroup::SetJsEnvSelector(std::function<int(UObject*, int)> InSelector)
|
||||
{
|
||||
auto DynamicInvoker = static_cast<FJsEnvImpl*>(JsEnvList[0].get())->TsDynamicInvoker;
|
||||
if (DynamicInvoker.IsValid())
|
||||
{
|
||||
static_cast<FGroupDynamicInvoker*>(DynamicInvoker.Get())->Selector = InSelector;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace PUERTS_NAMESPACE
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,767 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "JsEnv.h"
|
||||
#include "DynamicDelegateProxy.h"
|
||||
#include "StructWrapper.h"
|
||||
#include "CppObjectMapper.h"
|
||||
#include "V8Utils.h"
|
||||
#include "ObjectMapper.h"
|
||||
#include "JSLogger.h"
|
||||
#include "ObjectRetainer.h"
|
||||
#if !defined(ENGINE_INDEPENDENT_JSENV)
|
||||
#include "TypeScriptGeneratedClass.h"
|
||||
#endif
|
||||
#include "UECompatible.h"
|
||||
#include "ContainerMeta.h"
|
||||
#include "ObjectCacheNode.h"
|
||||
#include <unordered_map>
|
||||
|
||||
#if ENGINE_MINOR_VERSION >= 25 || ENGINE_MAJOR_VERSION > 4
|
||||
#include "UObject/WeakFieldPtr.h"
|
||||
#endif
|
||||
|
||||
PRAGMA_DISABLE_UNDEFINED_IDENTIFIER_WARNINGS
|
||||
#pragma warning(push, 0)
|
||||
#include "libplatform/libplatform.h"
|
||||
#include "v8.h"
|
||||
#pragma warning(pop)
|
||||
PRAGMA_ENABLE_UNDEFINED_IDENTIFIER_WARNINGS
|
||||
|
||||
#include "NamespaceDef.h"
|
||||
|
||||
#include "V8InspectorImpl.h"
|
||||
|
||||
#if defined(WITH_NODEJS)
|
||||
PRAGMA_DISABLE_UNDEFINED_IDENTIFIER_WARNINGS
|
||||
#pragma warning(push, 0)
|
||||
#include "node.h"
|
||||
#include "uv.h"
|
||||
#pragma warning(pop)
|
||||
PRAGMA_ENABLE_UNDEFINED_IDENTIFIER_WARNINGS
|
||||
#endif
|
||||
|
||||
#if USE_WASM3
|
||||
#include "WasmRuntime.h"
|
||||
#include "PuertsWasm/WasmJsFunctionParams.h"
|
||||
#endif
|
||||
|
||||
#if V8_MAJOR_VERSION < 8 || defined(WITH_QUICKJS) || defined(WITH_NODEJS) || (WITH_EDITOR && !defined(FORCE_USE_STATIC_V8_LIB))
|
||||
#define WITH_BACKING_STORE_AUTO_FREE 0
|
||||
#else
|
||||
#define WITH_BACKING_STORE_AUTO_FREE 1
|
||||
#endif
|
||||
|
||||
namespace PUERTS_NAMESPACE
|
||||
{
|
||||
class JSError
|
||||
{
|
||||
public:
|
||||
FString Message;
|
||||
|
||||
JSError()
|
||||
{
|
||||
}
|
||||
|
||||
explicit JSError(const FString& m) : Message(m)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class FJsEnvImpl : public IJsEnv, IObjectMapper, public FUObjectArray::FUObjectDeleteListener
|
||||
{
|
||||
public:
|
||||
explicit FJsEnvImpl(const FString& ScriptRoot);
|
||||
|
||||
FJsEnvImpl(std::shared_ptr<IJSModuleLoader> InModuleLoader, std::shared_ptr<ILogger> InLogger, int InPort,
|
||||
std::function<void(const FString&)> InOnSourceLoadedCallback, const FString InFlags, void* InExternalRuntime,
|
||||
void* InExternalContext);
|
||||
|
||||
virtual ~FJsEnvImpl() override;
|
||||
|
||||
virtual void Start(const FString& ModuleNameOrScript, const TArray<TPair<FString, UObject*>>& Arguments) override;
|
||||
|
||||
virtual bool IdleNotificationDeadline(double DeadlineInSeconds) override;
|
||||
|
||||
virtual void LowMemoryNotification() override;
|
||||
|
||||
virtual void RequestMinorGarbageCollectionForTesting() override;
|
||||
|
||||
virtual void RequestFullGarbageCollectionForTesting() override;
|
||||
|
||||
virtual void WaitDebugger(double timeout) override
|
||||
{
|
||||
#ifdef THREAD_SAFE
|
||||
v8::Locker Locker(MainIsolate);
|
||||
#endif
|
||||
const auto startTime = FDateTime::Now();
|
||||
while (Inspector && !Inspector->Tick())
|
||||
{
|
||||
if (timeout > 0)
|
||||
{
|
||||
auto now = FDateTime::Now();
|
||||
if ((now - startTime).GetTotalSeconds() >= timeout)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(ENGINE_INDEPENDENT_JSENV)
|
||||
virtual void TryBindJs(const class UObjectBase* InObject) override;
|
||||
|
||||
virtual void RebindJs() override;
|
||||
#endif
|
||||
|
||||
virtual FString CurrentStackTrace() override;
|
||||
|
||||
virtual void InitExtensionMethodsMap() override;
|
||||
|
||||
void JsHotReload(FName ModuleName, const FString& JsSource);
|
||||
|
||||
virtual void ReloadModule(FName ModuleName, const FString& JsSource) override;
|
||||
|
||||
virtual void ReloadSource(const FString& Path, const std::string& JsSource) override;
|
||||
|
||||
std::function<void(const FString&)> OnSourceLoadedCallback;
|
||||
|
||||
virtual void OnSourceLoaded(std::function<void(const FString&)> Callback) override;
|
||||
|
||||
public:
|
||||
bool IsTypeScriptGeneratedClass(UClass* Class);
|
||||
|
||||
void SetJsTakeRef(UObject* UEObject, FClassWrapper* ClassWrapper);
|
||||
|
||||
virtual void Bind(FClassWrapper* ClassWrapper, UObject* UEObject, v8::Local<v8::Object> JSObject) override;
|
||||
|
||||
virtual void UnBind(UClass* Class, UObject* UEObject) override;
|
||||
|
||||
virtual void UnBind(UClass* Class, UObject* UEObject, bool ResetPointer);
|
||||
|
||||
v8::Local<v8::Value> FindOrAdd(
|
||||
v8::Isolate* InIsolate, v8::Local<v8::Context>& Context, UClass* Class, UObject* UEObject, bool SkipTypeScriptInitial);
|
||||
|
||||
virtual v8::Local<v8::Value> FindOrAdd(
|
||||
v8::Isolate* InIsolate, v8::Local<v8::Context>& Context, UClass* Class, UObject* UEObject) override;
|
||||
|
||||
virtual void BindStruct(
|
||||
FScriptStructWrapper* ScriptStructWrapper, void* Ptr, v8::Local<v8::Object> JSObject, bool PassByPointer) override;
|
||||
|
||||
virtual void UnBindStruct(FScriptStructWrapper* ScriptStructWrapper, void* Ptr) override;
|
||||
|
||||
virtual void UnBindCppObject(v8::Isolate* Isolate, JSClassDefinition* ClassDefinition, void* Ptr) override;
|
||||
|
||||
virtual v8::Local<v8::Value> FindOrAddStruct(
|
||||
v8::Isolate* Isolate, v8::Local<v8::Context>& Context, UScriptStruct* ScriptStruct, void* Ptr, bool PassByPointer) override;
|
||||
|
||||
virtual void BindCppObject(v8::Isolate* InIsolate, JSClassDefinition* ClassDefinition, void* Ptr,
|
||||
v8::Local<v8::Object> JSObject, bool PassByPointer) override;
|
||||
|
||||
virtual void* GetPrivateData(v8::Local<v8::Context> Context, v8::Local<v8::Object> JSObject) override;
|
||||
|
||||
virtual void SetPrivateData(v8::Local<v8::Context> Context, v8::Local<v8::Object> JSObject, void* Ptr) override;
|
||||
|
||||
virtual v8::MaybeLocal<v8::Function> LoadTypeById(v8::Local<v8::Context> Context, const void* TypeId) override;
|
||||
|
||||
virtual v8::Local<v8::Value> FindOrAddCppObject(
|
||||
v8::Isolate* Isolate, v8::Local<v8::Context>& Context, const void* TypeId, void* Ptr, bool PassByPointer) override;
|
||||
|
||||
virtual void Merge(
|
||||
v8::Isolate* Isolate, v8::Local<v8::Context> Context, v8::Local<v8::Object> Src, UStruct* DesType, void* Des) override;
|
||||
|
||||
enum ContainerType
|
||||
{
|
||||
EArray,
|
||||
EMap,
|
||||
ESet
|
||||
};
|
||||
|
||||
void BindContainer(void* Ptr, v8::Local<v8::Object> JSObject, void (*Callback)(const v8::WeakCallbackInfo<void>& data),
|
||||
bool PassByPointer, ContainerType Type);
|
||||
|
||||
virtual void UnBindContainer(void* Ptr) override;
|
||||
|
||||
virtual v8::Local<v8::Value> FindOrAddContainer(v8::Isolate* Isolate, v8::Local<v8::Context>& Context, PropertyMacro* Property,
|
||||
FScriptArray* Ptr, bool PassByPointer) override;
|
||||
|
||||
virtual v8::Local<v8::Value> FindOrAddContainer(v8::Isolate* Isolate, v8::Local<v8::Context>& Context, PropertyMacro* Property,
|
||||
FScriptSet* Ptr, bool PassByPointer) override;
|
||||
|
||||
virtual v8::Local<v8::Value> FindOrAddContainer(v8::Isolate* Isolate, v8::Local<v8::Context>& Context,
|
||||
PropertyMacro* KeyProperty, PropertyMacro* ValueProperty, FScriptMap* Ptr, bool PassByPointer) override;
|
||||
|
||||
virtual v8::Local<v8::Value> FindOrAddDelegate(v8::Isolate* Isolate, v8::Local<v8::Context>& Context, UObject* Owner,
|
||||
PropertyMacro* Property, void* DelegatePtr, bool PassByPointer) override;
|
||||
|
||||
virtual bool AddToDelegate(
|
||||
v8::Isolate* Isolate, v8::Local<v8::Context>& Context, void* DelegatePtr, v8::Local<v8::Function> JsFunction) override;
|
||||
|
||||
virtual PropertyMacro* FindDelegateProperty(void* DelegatePtr) override;
|
||||
|
||||
virtual FScriptDelegate NewDelegate(v8::Isolate* Isolate, v8::Local<v8::Context>& Context, UObject* Owner,
|
||||
v8::Local<v8::Function> JsFunction, UFunction* SignatureFunction) override;
|
||||
|
||||
void ReleaseManualReleaseDelegate(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
|
||||
virtual bool RemoveFromDelegate(
|
||||
v8::Isolate* Isolate, v8::Local<v8::Context>& Context, void* DelegatePtr, v8::Local<v8::Function> JsFunction) override;
|
||||
|
||||
virtual bool ClearDelegate(v8::Isolate* Isolate, v8::Local<v8::Context>& Context, void* DelegatePtr) override;
|
||||
|
||||
virtual void ExecuteDelegate(v8::Isolate* Isolate, v8::Local<v8::Context>& Context,
|
||||
const v8::FunctionCallbackInfo<v8::Value>& Info, void* DelegatePtr) override;
|
||||
|
||||
virtual bool IsInstanceOf(UStruct* Struct, v8::Local<v8::Object> JsObject) override;
|
||||
|
||||
virtual bool IsInstanceOfCppObject(v8::Isolate* Isolate, const void* TypeId, v8::Local<v8::Object> JsObject) override;
|
||||
|
||||
virtual std::weak_ptr<int> GetJsEnvLifeCycleTracker() override;
|
||||
|
||||
virtual v8::Local<v8::Value> AddSoftObjectPtr(v8::Isolate* Isolate, v8::Local<v8::Context> Context,
|
||||
FSoftObjectPtr* SoftObjectPtr, UClass* Class, bool IsSoftClass) override;
|
||||
|
||||
bool CheckDelegateProxies(float Tick);
|
||||
|
||||
virtual v8::Local<v8::Value> CreateArray(
|
||||
v8::Isolate* Isolate, v8::Local<v8::Context>& Context, FPropertyTranslator* Property, void* ArrayPtr) override;
|
||||
|
||||
void InvokeDelegateCallback(UDynamicDelegateProxy* Proxy, void* Params);
|
||||
|
||||
#if !defined(ENGINE_INDEPENDENT_JSENV)
|
||||
void JsConstruct(UClass* Class, UObject* Object, const v8::UniquePersistent<v8::Function>& Constructor,
|
||||
const v8::UniquePersistent<v8::Object>& Prototype);
|
||||
|
||||
void TsConstruct(UTypeScriptGeneratedClass* Class, UObject* Object);
|
||||
|
||||
void InvokeJsMethod(UObject* ContextObject, UJSGeneratedFunction* Function, FFrame& Stack, void* RESULT_PARAM);
|
||||
|
||||
void InvokeMixinMethod(UObject* ContextObject, UJSGeneratedFunction* Function, FFrame& Stack, void* RESULT_PARAM);
|
||||
|
||||
void TypeScriptInitial(UClass* Class, UObject* Object, const bool TypeScriptClassFound = false);
|
||||
|
||||
void InvokeTsMethod(UObject* ContextObject, UFunction* Function, FFrame& Stack, void* RESULT_PARAM);
|
||||
|
||||
void NotifyReBind(UTypeScriptGeneratedClass* Class);
|
||||
#endif
|
||||
|
||||
v8::UniquePersistent<v8::Function> JsPromiseRejectCallback;
|
||||
|
||||
V8_INLINE static FJsEnvImpl* Get(v8::Isolate* Isolate)
|
||||
{
|
||||
return static_cast<FJsEnvImpl*>(FV8Utils::IsolateData<IObjectMapper>(Isolate));
|
||||
}
|
||||
|
||||
public:
|
||||
#if ENGINE_MINOR_VERSION > 22 || ENGINE_MAJOR_VERSION > 4
|
||||
virtual void OnUObjectArrayShutdown() override
|
||||
{
|
||||
GUObjectArray.RemoveUObjectDeleteListener(static_cast<FUObjectArray::FUObjectDeleteListener*>(this));
|
||||
}
|
||||
#endif
|
||||
virtual void NotifyUObjectDeleted(const class UObjectBase* Object, int32 Index) override;
|
||||
|
||||
void TryReleaseType(UStruct* Struct);
|
||||
|
||||
private:
|
||||
bool LoadFile(const FString& RequiringDir, const FString& ModuleName, FString& OutPath, FString& OutDebugPath,
|
||||
TArray<uint8>& Data, FString& ErrInfo);
|
||||
|
||||
void ExecuteModule(const FString& ModuleName);
|
||||
|
||||
void EvalScript(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
|
||||
void Log(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
|
||||
void SearchModule(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
|
||||
void LoadModule(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
|
||||
v8::Local<v8::Value> UETypeToJsClass(v8::Isolate* Isolate, v8::Local<v8::Context> Context, UField* Type);
|
||||
|
||||
void LoadUEType(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
|
||||
void LoadCppType(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
|
||||
void UEClassToJSClass(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
|
||||
void SetJsTakeRefInTs(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
|
||||
bool GetContainerTypeProperty(v8::Local<v8::Context> Context, v8::Local<v8::Value> Value, PropertyMacro** PropertyPtr);
|
||||
|
||||
void NewContainer(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
|
||||
std::shared_ptr<FStructWrapper> GetStructWrapper(UStruct* InStruct, bool& IsReuseTemplate);
|
||||
|
||||
struct FTemplateInfo
|
||||
{
|
||||
v8::UniquePersistent<v8::FunctionTemplate> Template;
|
||||
std::shared_ptr<FStructWrapper> StructWrapper;
|
||||
};
|
||||
|
||||
FTemplateInfo* GetTemplateInfoOfType(UStruct* Class, bool& Existed);
|
||||
|
||||
v8::Local<v8::Function> GetJsClass(UStruct* Class, v8::Local<v8::Context> Context);
|
||||
|
||||
FPropertyTranslator* GetContainerPropertyTranslator(PropertyMacro* Property);
|
||||
|
||||
void SetTimeout(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
|
||||
void SetFTickerDelegate(const v8::FunctionCallbackInfo<v8::Value>& Info, bool Continue);
|
||||
|
||||
bool TimerCallback(int DelegateHandleId, bool Continue);
|
||||
|
||||
void RemoveFTickerDelegateHandle(int HandleId);
|
||||
|
||||
void SetInterval(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
|
||||
void ClearInterval(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
|
||||
void MergeObject(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
|
||||
void NewObjectByClass(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
|
||||
void NewStructByScriptStruct(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
|
||||
#if !defined(ENGINE_INDEPENDENT_JSENV)
|
||||
void MakeUClass(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
|
||||
TArray<TWeakObjectPtr<UClass>> MixinClasses;
|
||||
void Mixin(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
#endif
|
||||
|
||||
void FindModule(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
|
||||
void DumpStatisticsLog(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
|
||||
void SetInspectorCallback(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
|
||||
void DispatchProtocolMessage(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
|
||||
#ifndef WITH_QUICKJS
|
||||
v8::MaybeLocal<v8::Module> FetchESModuleTree(v8::Local<v8::Context> Context, const FString& FileName);
|
||||
|
||||
v8::MaybeLocal<v8::Module> FetchCJSModuleAsESModule(v8::Local<v8::Context> Context, const FString& ModuleName);
|
||||
|
||||
struct FModuleInfo
|
||||
{
|
||||
v8::Global<v8::Module> Module;
|
||||
TMap<FString, v8::Global<v8::Module>> ResolveCache;
|
||||
v8::Global<v8::Value> CJSValue;
|
||||
};
|
||||
|
||||
std::unordered_multimap<int, FModuleInfo*>::iterator FindModuleInfo(v8::Local<v8::Module> Module);
|
||||
|
||||
static v8::MaybeLocal<v8::Module> ResolveModuleCallback(v8::Local<v8::Context> Context, v8::Local<v8::String> Specifier,
|
||||
#if V8_MAJOR_VERSION >= 9
|
||||
v8::Local<v8::FixedArray> ImportAttributes, // not implement yet
|
||||
#endif
|
||||
v8::Local<v8::Module> Referrer);
|
||||
#endif
|
||||
|
||||
struct ObjectMerger;
|
||||
|
||||
std::unique_ptr<ObjectMerger>& GetObjectMerger(UStruct* Struct);
|
||||
|
||||
struct ObjectMerger
|
||||
{
|
||||
std::map<std::string, std::unique_ptr<FPropertyTranslator>> Fields;
|
||||
UStruct* Struct;
|
||||
FJsEnvImpl* Parent;
|
||||
|
||||
ObjectMerger(FJsEnvImpl* InParent, UStruct* InStruct)
|
||||
{
|
||||
Parent = InParent;
|
||||
Struct = InStruct;
|
||||
for (TFieldIterator<PropertyMacro> It(Struct); It; ++It)
|
||||
{
|
||||
PropertyMacro* Property = *It;
|
||||
TStringConversion<TStringConvert<TCHAR, ANSICHAR>> Name(*Property->GetName());
|
||||
Fields[Name.Get()] = FPropertyTranslator::Create(Property);
|
||||
}
|
||||
}
|
||||
|
||||
void Merge(v8::Isolate* Isolate, v8::Local<v8::Context> Context, v8::Local<v8::Object> JsObject, void* Ptr)
|
||||
{
|
||||
if (auto Class = Cast<UClass>(Struct))
|
||||
{
|
||||
UObject* Object = reinterpret_cast<UObject*>(Ptr);
|
||||
if (!Object->IsValidLowLevel() || UEObjectIsPendingKill(Object) || Object->GetClass() != Class ||
|
||||
FV8Utils::GetPointer(JsObject))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
auto Keys = JsObject->GetOwnPropertyNames(Context).ToLocalChecked();
|
||||
for (decltype(Keys->Length()) i = 0; i < Keys->Length(); ++i)
|
||||
{
|
||||
auto Key = Keys->Get(Context, i).ToLocalChecked();
|
||||
auto Iter = Fields.find(*v8::String::Utf8Value(Isolate, Key));
|
||||
if (Iter != Fields.end())
|
||||
{
|
||||
auto MaybeValue = JsObject->Get(Context, Key);
|
||||
if (!MaybeValue.IsEmpty())
|
||||
{
|
||||
auto Value = MaybeValue.ToLocalChecked();
|
||||
if (Value->IsObject())
|
||||
{
|
||||
auto JsObjectField = Value->ToObject(Context).ToLocalChecked();
|
||||
if (!FV8Utils::GetPointerFast<void>(JsObjectField))
|
||||
{
|
||||
UStruct* FieldStruct = nullptr;
|
||||
if (auto ObjectPropertyBase = CastFieldMacro<ObjectPropertyBaseMacro>(Iter->second->Property))
|
||||
{
|
||||
FieldStruct = ObjectPropertyBase->PropertyClass;
|
||||
}
|
||||
else if (auto StructProperty = CastFieldMacro<StructPropertyMacro>(Iter->second->Property))
|
||||
{
|
||||
FieldStruct = StructProperty->Struct;
|
||||
}
|
||||
if (FieldStruct)
|
||||
{
|
||||
Parent->GetObjectMerger(FieldStruct)
|
||||
->Merge(Isolate, Context, JsObjectField,
|
||||
Iter->second->Property->ContainerPtrToValuePtr<void>(Ptr));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (!Value->IsUndefined())
|
||||
Iter->second->JsToUEInContainer(Isolate, Context, Value, Ptr, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
friend ObjectMerger;
|
||||
|
||||
#if USE_WASM3
|
||||
std::shared_ptr<WasmEnv> PuertsWasmEnv;
|
||||
//在执行module.instance的时候,如果有指定memory,那么这个module对应会创建一个runtime
|
||||
TArray<std::shared_ptr<WasmRuntime>> PuertsWasmRuntimeList;
|
||||
TArray<WasmNormalLinkInfo*> PuertsWasmCachedLinkFunctionList;
|
||||
|
||||
protected:
|
||||
void Wasm_NewMemory(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
void Wasm_MemoryGrowth(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
void Wasm_MemoryBuffer(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
void Wasm_TableGrowth(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
void Wasm_TableSet(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
void Wasm_TableLen(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
void Wasm_Instance(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
void Wasm_OverrideWebAssembly(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
|
||||
#endif
|
||||
|
||||
public:
|
||||
#if !defined(ENGINE_INDEPENDENT_JSENV)
|
||||
class TsDynamicInvokerImpl : public ITsDynamicInvoker
|
||||
{
|
||||
public:
|
||||
TsDynamicInvokerImpl(FJsEnvImpl* InParent) : Parent(InParent)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void TsConstruct(UTypeScriptGeneratedClass* Class, UObject* Object) override
|
||||
{
|
||||
if (Parent)
|
||||
Parent->TsConstruct(Class, Object);
|
||||
}
|
||||
|
||||
virtual void InvokeTsMethod(UObject* ContextObject, UFunction* Function, FFrame& Stack, void* RESULT_PARAM) override
|
||||
{
|
||||
if (Parent)
|
||||
Parent->InvokeTsMethod(ContextObject, Function, Stack, RESULT_PARAM);
|
||||
}
|
||||
|
||||
virtual void NotifyReBind(UTypeScriptGeneratedClass* Class) override
|
||||
{
|
||||
if (Parent)
|
||||
Parent->NotifyReBind(Class);
|
||||
}
|
||||
|
||||
FJsEnvImpl* Parent;
|
||||
};
|
||||
|
||||
TSharedPtr<ITsDynamicInvoker, ESPMode::ThreadSafe> TsDynamicInvoker;
|
||||
|
||||
TSharedPtr<IDynamicInvoker, ESPMode::ThreadSafe> MixinInvoker;
|
||||
#endif
|
||||
private:
|
||||
FObjectRetainer UserObjectRetainer;
|
||||
|
||||
FObjectRetainer SysObjectRetainer;
|
||||
|
||||
std::shared_ptr<IJSModuleLoader> ModuleLoader;
|
||||
|
||||
std::shared_ptr<ILogger> Logger;
|
||||
|
||||
bool Started;
|
||||
|
||||
private:
|
||||
v8::Isolate::CreateParams CreateParams;
|
||||
|
||||
#if defined(WITH_NODEJS)
|
||||
uv_loop_t NodeUVLoop;
|
||||
|
||||
std::unique_ptr<node::ArrayBufferAllocator> NodeArrayBufferAllocator;
|
||||
|
||||
node::IsolateData* NodeIsolateData;
|
||||
|
||||
node::Environment* NodeEnv;
|
||||
|
||||
uv_thread_t PollingThread;
|
||||
|
||||
uv_sem_t PollingSem;
|
||||
|
||||
uv_async_t DummyUVHandle;
|
||||
|
||||
bool PollingClosed = false;
|
||||
|
||||
FGraphEventRef LastJob;
|
||||
|
||||
#if PLATFORM_LINUX
|
||||
int Epoll;
|
||||
#endif
|
||||
|
||||
void StartPolling();
|
||||
|
||||
void UvRunOnce();
|
||||
|
||||
void PollEvents();
|
||||
|
||||
static void OnWatcherQueueChanged(uv_loop_t* loop);
|
||||
|
||||
void WakeupPollingThread();
|
||||
|
||||
void StopPolling();
|
||||
#endif
|
||||
|
||||
v8::Isolate* MainIsolate;
|
||||
|
||||
v8::Global<v8::Context> DefaultContext;
|
||||
|
||||
v8::Global<v8::Function> Require;
|
||||
|
||||
v8::Global<v8::Function> GetESMMain;
|
||||
|
||||
v8::Global<v8::Function> ReloadJs;
|
||||
|
||||
#if !PUERTS_FORCE_CPP_UFUNCTION
|
||||
v8::Global<v8::Function> MergePrototype;
|
||||
#endif
|
||||
|
||||
v8::Global<v8::Function> RemoveListItem;
|
||||
|
||||
v8::Global<v8::Function> GenListApply;
|
||||
|
||||
#if defined(WITH_V8_BYTECODE)
|
||||
v8::Global<v8::Function> GenEmptyCode;
|
||||
#endif
|
||||
|
||||
TMap<UStruct*, FTemplateInfo> TypeToTemplateInfoMap;
|
||||
|
||||
TMap<FString, std::shared_ptr<FStructWrapper>> TypeReflectionMap;
|
||||
|
||||
TMap<UObject*, v8::UniquePersistent<v8::Value>> ObjectMap;
|
||||
|
||||
TMap<void*, FObjectCacheNode> StructCache;
|
||||
|
||||
struct ContainerCacheItem
|
||||
{
|
||||
v8::UniquePersistent<v8::Value> Container;
|
||||
bool NeedRelease;
|
||||
ContainerType Type;
|
||||
};
|
||||
|
||||
TMap<void*, ContainerCacheItem> ContainerCache;
|
||||
|
||||
FCppObjectMapper CppObjectMapper;
|
||||
|
||||
v8::UniquePersistent<v8::FunctionTemplate> ArrayTemplate;
|
||||
|
||||
v8::UniquePersistent<v8::FunctionTemplate> SetTemplate;
|
||||
|
||||
v8::UniquePersistent<v8::FunctionTemplate> MapTemplate;
|
||||
|
||||
v8::UniquePersistent<v8::FunctionTemplate> FixSizeArrayTemplate;
|
||||
|
||||
struct ContainerPropertyInfo
|
||||
{
|
||||
#if ENGINE_MINOR_VERSION < 25 && ENGINE_MAJOR_VERSION < 5
|
||||
TWeakObjectPtr<PropertyMacro> PropertyWeakPtr;
|
||||
#else
|
||||
TWeakFieldPtr<PropertyMacro> PropertyWeakPtr;
|
||||
#endif
|
||||
std::unique_ptr<FPropertyTranslator> PropertyTranslator;
|
||||
};
|
||||
|
||||
std::map<PropertyMacro*, ContainerPropertyInfo> ContainerPropertyMap;
|
||||
|
||||
std::map<UFunction*, std::unique_ptr<FFunctionTranslator>> JsCallbackPrototypeMap;
|
||||
|
||||
std::map<UStruct*, std::unique_ptr<ObjectMerger>> ObjectMergers;
|
||||
|
||||
struct DelegateObjectInfo
|
||||
{
|
||||
v8::UniquePersistent<v8::Object> JSObject; // function to proxy save here
|
||||
TWeakObjectPtr<UObject> Owner; //可用于自动清理
|
||||
DelegatePropertyMacro* DelegateProperty;
|
||||
MulticastDelegatePropertyMacro* MulticastDelegateProperty;
|
||||
UFunction* SignatureFunction;
|
||||
bool PassByPointer;
|
||||
TWeakObjectPtr<UDynamicDelegateProxy> Proxy;
|
||||
v8::UniquePersistent<v8::Array> JsCallbacks;
|
||||
};
|
||||
|
||||
struct TsFunctionInfo
|
||||
{
|
||||
v8::UniquePersistent<v8::Function> JsFunction;
|
||||
|
||||
std::unique_ptr<FFunctionTranslator> FunctionTranslator;
|
||||
};
|
||||
|
||||
class DynamicInvokerImpl : public IDynamicInvoker
|
||||
{
|
||||
public:
|
||||
DynamicInvokerImpl(FJsEnvImpl* InParent) : Parent(InParent)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void InvokeDelegateCallback(UDynamicDelegateProxy* Proxy, void* Params) override
|
||||
{
|
||||
if (Parent)
|
||||
Parent->InvokeDelegateCallback(Proxy, Params);
|
||||
}
|
||||
#if !defined(ENGINE_INDEPENDENT_JSENV)
|
||||
virtual void JsConstruct(UClass* Class, UObject* Object, const v8::UniquePersistent<v8::Function>& Constructor,
|
||||
const v8::UniquePersistent<v8::Object>& Prototype) override
|
||||
{
|
||||
if (Parent)
|
||||
Parent->JsConstruct(Class, Object, Constructor, Prototype);
|
||||
}
|
||||
|
||||
virtual void InvokeJsMethod(
|
||||
UObject* ContextObject, UJSGeneratedFunction* Function, FFrame& Stack, void* RESULT_PARAM) override
|
||||
{
|
||||
if (Parent)
|
||||
Parent->InvokeJsMethod(ContextObject, Function, Stack, RESULT_PARAM);
|
||||
}
|
||||
|
||||
virtual void InvokeMixinMethod(
|
||||
UObject* ContextObject, UJSGeneratedFunction* Function, FFrame& Stack, void* RESULT_PARAM) override
|
||||
{
|
||||
if (Parent)
|
||||
Parent->InvokeMixinMethod(ContextObject, Function, Stack, RESULT_PARAM);
|
||||
}
|
||||
#endif
|
||||
FJsEnvImpl* Parent;
|
||||
};
|
||||
#if !defined(ENGINE_INDEPENDENT_JSENV)
|
||||
struct FBindInfo
|
||||
{
|
||||
FName Name;
|
||||
v8::UniquePersistent<v8::Function> Constructor;
|
||||
v8::UniquePersistent<v8::Object> Prototype;
|
||||
bool InjectNotFinished;
|
||||
};
|
||||
|
||||
TMap<UTypeScriptGeneratedClass*, FBindInfo> BindInfoMap;
|
||||
|
||||
void FinishInjection(UClass* InClass);
|
||||
|
||||
void MakeSureInject(UTypeScriptGeneratedClass* Class, bool ForceReinject, bool RebindObject);
|
||||
#endif
|
||||
TSharedPtr<DynamicInvokerImpl, ESPMode::ThreadSafe> DynamicInvoker;
|
||||
|
||||
TSet<UClass*> GeneratedClasses;
|
||||
|
||||
v8::UniquePersistent<v8::FunctionTemplate> DelegateTemplate;
|
||||
|
||||
v8::UniquePersistent<v8::FunctionTemplate> MulticastDelegateTemplate;
|
||||
|
||||
v8::UniquePersistent<v8::FunctionTemplate> SoftObjectPtrTemplate;
|
||||
|
||||
std::map<void*, DelegateObjectInfo> DelegateMap;
|
||||
|
||||
TMap<UFunction*, TsFunctionInfo> TsFunctionMap;
|
||||
|
||||
TMap<UFunction*, v8::UniquePersistent<v8::Function>> MixinFunctionMap;
|
||||
|
||||
std::map<UStruct*, std::vector<UFunction*>> ExtensionMethodsMap;
|
||||
|
||||
bool ExtensionMethodsMapInited = false;
|
||||
|
||||
struct FTimerInfo
|
||||
{
|
||||
v8::Global<v8::Function> Callback;
|
||||
FUETickDelegateHandle TickerHandle;
|
||||
};
|
||||
uint32_t TimerID = 0;
|
||||
TMap<uint32_t, FTimerInfo> TimerInfos;
|
||||
|
||||
FUETickDelegateHandle DelegateProxiesCheckerHandler;
|
||||
|
||||
V8Inspector* Inspector;
|
||||
|
||||
V8InspectorChannel* InspectorChannel;
|
||||
|
||||
v8::Global<v8::Function> InspectorMessageHandler;
|
||||
|
||||
FContainerMeta ContainerMeta;
|
||||
|
||||
v8::Global<v8::Map> ManualReleaseCallbackMap;
|
||||
|
||||
std::vector<TWeakObjectPtr<UDynamicDelegateProxy>> ManualReleaseCallbackList;
|
||||
|
||||
TMap<UObject*, TArray<TWeakObjectPtr<UDynamicDelegateProxy>>> AutoReleaseCallbacksMap;
|
||||
|
||||
#ifndef WITH_QUICKJS
|
||||
TMap<FString, v8::Global<v8::Module>> PathToModule;
|
||||
|
||||
std::unordered_multimap<int, FModuleInfo*> HashToModuleInfo;
|
||||
#endif
|
||||
|
||||
#ifdef SINGLE_THREAD_VERIFY
|
||||
uint32 BoundThreadId;
|
||||
#endif
|
||||
|
||||
typedef void (FJsEnvImpl::*V8MethodCallback)(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
|
||||
template <V8MethodCallback callback>
|
||||
struct MethodBindingHelper
|
||||
{
|
||||
static void Bind(v8::Isolate* Isolate, v8::Local<v8::Context> Context, v8::Local<v8::Object> Obj, const char* Key,
|
||||
v8::Local<v8::External> This)
|
||||
{
|
||||
Obj->Set(Context, FV8Utils::ToV8String(Isolate, Key),
|
||||
v8::FunctionTemplate::New(
|
||||
Isolate,
|
||||
[](const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
auto Self = static_cast<FJsEnvImpl*>((v8::Local<v8::External>::Cast(Info.Data()))->Value());
|
||||
(Self->*callback)(Info);
|
||||
},
|
||||
This)
|
||||
->GetFunction(Context)
|
||||
.ToLocalChecked())
|
||||
.Check();
|
||||
}
|
||||
};
|
||||
#if defined(WITH_V8_BYTECODE)
|
||||
uint32_t Expect_FlagHash = 0;
|
||||
#if V8_MAJOR_VERSION >= 11
|
||||
uint32_t Expect_ReadOnlySnapshotChecksum = 0;
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace PUERTS_NAMESPACE
|
||||
@@ -0,0 +1,273 @@
|
||||
/*
|
||||
* 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 "JsEnvModule.h"
|
||||
//#include "TGameJSCorePCH.h"
|
||||
#include "HAL/MemoryBase.h"
|
||||
#include "NamespaceDef.h"
|
||||
PRAGMA_DISABLE_UNDEFINED_IDENTIFIER_WARNINGS
|
||||
#if defined(WITH_NODEJS)
|
||||
#pragma warning(push, 0)
|
||||
#include "node.h"
|
||||
#include "uv.h"
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
#pragma warning(push, 0)
|
||||
#include "v8.h"
|
||||
#include "libplatform/libplatform.h"
|
||||
#pragma warning(pop)
|
||||
PRAGMA_ENABLE_UNDEFINED_IDENTIFIER_WARNINGS
|
||||
|
||||
class FMallocWrapper final : public FMalloc
|
||||
{
|
||||
public:
|
||||
FMalloc* InnerMalloc;
|
||||
|
||||
public:
|
||||
FMallocWrapper(FMalloc* InMalloc)
|
||||
{
|
||||
InnerMalloc = InMalloc;
|
||||
}
|
||||
|
||||
virtual void* Malloc(SIZE_T Size, uint32 Alignment) override
|
||||
{
|
||||
if (UNLIKELY(Size == 0))
|
||||
{
|
||||
Size = 1;
|
||||
}
|
||||
return InnerMalloc->Malloc(Size, Alignment);
|
||||
}
|
||||
|
||||
#if ENGINE_MINOR_VERSION >= 25 || ENGINE_MAJOR_VERSION > 4
|
||||
virtual void* TryMalloc(SIZE_T Size, uint32 Alignment) override
|
||||
{
|
||||
if (UNLIKELY(Size == 0))
|
||||
{
|
||||
Size = 1;
|
||||
}
|
||||
return InnerMalloc->TryMalloc(Size, Alignment);
|
||||
}
|
||||
#endif
|
||||
|
||||
virtual void* Realloc(void* Ptr, SIZE_T NewSize, uint32 Alignment) override
|
||||
{
|
||||
return InnerMalloc->Realloc(Ptr, NewSize, Alignment);
|
||||
}
|
||||
|
||||
#if ENGINE_MINOR_VERSION >= 25 || ENGINE_MAJOR_VERSION > 4
|
||||
virtual void* TryRealloc(void* Ptr, SIZE_T NewSize, uint32 Alignment) override
|
||||
{
|
||||
return InnerMalloc->TryRealloc(Ptr, NewSize, Alignment);
|
||||
}
|
||||
#endif
|
||||
|
||||
virtual void Free(void* Ptr) override
|
||||
{
|
||||
return InnerMalloc->Free(Ptr);
|
||||
}
|
||||
|
||||
virtual bool GetAllocationSize(void* Original, SIZE_T& SizeOut) override
|
||||
{
|
||||
return InnerMalloc->GetAllocationSize(Original, SizeOut);
|
||||
}
|
||||
|
||||
virtual bool IsInternallyThreadSafe() const override
|
||||
{
|
||||
return InnerMalloc->IsInternallyThreadSafe();
|
||||
}
|
||||
|
||||
virtual bool ValidateHeap() override
|
||||
{
|
||||
return InnerMalloc->ValidateHeap();
|
||||
}
|
||||
|
||||
virtual const TCHAR* GetDescriptiveName() override
|
||||
{
|
||||
return InnerMalloc->GetDescriptiveName();
|
||||
}
|
||||
|
||||
virtual SIZE_T QuantizeSize(SIZE_T Count, uint32 Alignment) override
|
||||
{
|
||||
return InnerMalloc->QuantizeSize(Count, Alignment);
|
||||
}
|
||||
|
||||
#if ENGINE_MINOR_VERSION > 21 || ENGINE_MAJOR_VERSION > 4
|
||||
virtual void Trim(bool bTrimThreadCaches) override
|
||||
{
|
||||
InnerMalloc->Trim(bTrimThreadCaches);
|
||||
}
|
||||
#else
|
||||
virtual void Trim() override
|
||||
{
|
||||
InnerMalloc->Trim();
|
||||
}
|
||||
#endif
|
||||
|
||||
virtual void SetupTLSCachesOnCurrentThread() override
|
||||
{
|
||||
InnerMalloc->SetupTLSCachesOnCurrentThread();
|
||||
}
|
||||
|
||||
virtual void ClearAndDisableTLSCachesOnCurrentThread() override
|
||||
{
|
||||
InnerMalloc->ClearAndDisableTLSCachesOnCurrentThread();
|
||||
}
|
||||
|
||||
virtual void InitializeStatsMetadata() override
|
||||
{
|
||||
InnerMalloc->InitializeStatsMetadata();
|
||||
}
|
||||
|
||||
virtual bool Exec(UWorld* InWorld, const TCHAR* Cmd, FOutputDevice& Ar) override
|
||||
{
|
||||
return InnerMalloc->Exec(InWorld, Cmd, Ar);
|
||||
}
|
||||
|
||||
virtual void UpdateStats() override
|
||||
{
|
||||
InnerMalloc->UpdateStats();
|
||||
}
|
||||
|
||||
virtual void GetAllocatorStats(FGenericMemoryStats& out_Stats) override
|
||||
{
|
||||
InnerMalloc->GetAllocatorStats(out_Stats);
|
||||
}
|
||||
|
||||
virtual void DumpAllocatorStats(class FOutputDevice& Ar) override
|
||||
{
|
||||
InnerMalloc->DumpAllocatorStats(Ar);
|
||||
}
|
||||
};
|
||||
|
||||
DEFINE_LOG_CATEGORY_STATIC(JsEnvModule, Log, All);
|
||||
|
||||
class FJsEnvModule : public IJsEnvModule
|
||||
{
|
||||
/** IModuleInterface implementation */
|
||||
void StartupModule() override;
|
||||
void ShutdownModule() override;
|
||||
|
||||
FMallocWrapper* MallocWrapper = nullptr;
|
||||
|
||||
public:
|
||||
void* GetV8Platform() override;
|
||||
|
||||
private:
|
||||
#if defined(V8_HAS_WRAP_API_WITHOUT_STL)
|
||||
v8::Platform* platform_;
|
||||
#else
|
||||
std::unique_ptr<v8::Platform> platform_;
|
||||
#endif
|
||||
};
|
||||
|
||||
IMPLEMENT_MODULE(FJsEnvModule, JsEnv)
|
||||
|
||||
void FJsEnvModule::StartupModule()
|
||||
{
|
||||
int* Dummy = new (std::nothrow) int[0];
|
||||
if (!Dummy)
|
||||
{
|
||||
UE_LOG(JsEnvModule, Warning, TEXT("new (std::nothrow) int[0] return nullptr, try fix it!"));
|
||||
MallocWrapper = new FMallocWrapper(GMalloc);
|
||||
GMalloc = MallocWrapper;
|
||||
}
|
||||
delete[] Dummy;
|
||||
|
||||
// This code will execute after your module is loaded into memory (but after global variables are initialized, of course.)
|
||||
#if defined(WITH_NODEJS)
|
||||
platform_ = node::MultiIsolatePlatform::Create(4);
|
||||
#else
|
||||
#if defined(V8_HAS_WRAP_API_WITHOUT_STL)
|
||||
#if defined(USING_SINGLE_THREAD_PLATFORM)
|
||||
platform_ = v8::platform::NewSingleThreadedDefaultPlatform_Without_Stl();
|
||||
#else
|
||||
platform_ = v8::platform::NewDefaultPlatform_Without_Stl();
|
||||
#endif
|
||||
#else
|
||||
#if defined(USING_SINGLE_THREAD_PLATFORM)
|
||||
platform_ = v8::platform::NewSingleThreadedDefaultPlatform();
|
||||
#else
|
||||
platform_ = v8::platform::NewDefaultPlatform();
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if PLATFORM_IOS
|
||||
v8::V8::SetFlagsFromString("--jitless --no-expose-wasm");
|
||||
#endif
|
||||
|
||||
#ifdef WITH_V8_FAST_CALL
|
||||
v8::V8::SetFlagsFromString("--turbo-fast-api-calls");
|
||||
#endif
|
||||
|
||||
#if defined(USING_SINGLE_THREAD_PLATFORM)
|
||||
v8::V8::SetFlagsFromString("--single-threaded");
|
||||
#endif
|
||||
|
||||
#if defined(WITH_V8_BYTECODE)
|
||||
v8::V8::SetFlagsFromString("--no-lazy --no-flush-bytecode --no-enable-lazy-source-positions");
|
||||
#endif
|
||||
|
||||
// v8::V8::SetFlagsFromString("--expose-gc");
|
||||
// v8::V8::SetFlagsFromString("--no-freeze-flags-after-init");
|
||||
|
||||
#if defined(V8_HAS_WRAP_API_WITHOUT_STL)
|
||||
v8::V8::InitializePlatform(platform_);
|
||||
#else
|
||||
v8::V8::InitializePlatform(platform_.get());
|
||||
#endif
|
||||
v8::V8::Initialize();
|
||||
|
||||
#if defined(WITH_NODEJS)
|
||||
int Argc = 1;
|
||||
char* ArgvIn[1];
|
||||
ArgvIn[0] = const_cast<char*>("puerts");
|
||||
char** Argv = uv_setup_args(Argc, ArgvIn);
|
||||
std::vector<std::string> Args(Argv, Argv + Argc);
|
||||
std::vector<std::string> ExecArgs;
|
||||
std::vector<std::string> Errors;
|
||||
int ExitCode = node::InitializeNodeWithArgs(&Args, &ExecArgs, &Errors);
|
||||
for (const std::string& error : Errors)
|
||||
{
|
||||
UE_LOG(LogTemp, Error, TEXT("Initialize Node: %s"), UTF8_TO_TCHAR(error.c_str()));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void FJsEnvModule::ShutdownModule()
|
||||
{
|
||||
// This function may be called during shutdown to clean up your module. For modules that support dynamic reloading,
|
||||
// we call this function before unloading the module.
|
||||
v8::V8::Dispose();
|
||||
#if V8_MAJOR_VERSION > 9
|
||||
v8::V8::DisposePlatform();
|
||||
#else
|
||||
v8::V8::ShutdownPlatform();
|
||||
#endif
|
||||
|
||||
#if defined(V8_HAS_WRAP_API_WITHOUT_STL)
|
||||
v8::platform::DeletePlatform_Without_Stl(platform_);
|
||||
#endif
|
||||
|
||||
if (MallocWrapper && MallocWrapper == GMalloc)
|
||||
{
|
||||
GMalloc = MallocWrapper->InnerMalloc;
|
||||
delete MallocWrapper;
|
||||
MallocWrapper = nullptr;
|
||||
UE_LOG(JsEnvModule, Warning, TEXT("GMalloc restored!"));
|
||||
}
|
||||
}
|
||||
|
||||
void* FJsEnvModule::GetV8Platform()
|
||||
{
|
||||
#if defined(V8_HAS_WRAP_API_WITHOUT_STL)
|
||||
return reinterpret_cast<void*>(platform_);
|
||||
#else
|
||||
return reinterpret_cast<void*>(platform_.get());
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "NamespaceDef.h"
|
||||
|
||||
PRAGMA_DISABLE_UNDEFINED_IDENTIFIER_WARNINGS
|
||||
#pragma warning(push, 0)
|
||||
#include "v8.h"
|
||||
#pragma warning(pop)
|
||||
PRAGMA_ENABLE_UNDEFINED_IDENTIFIER_WARNINGS
|
||||
|
||||
namespace PUERTS_NAMESPACE
|
||||
{
|
||||
class FObjectCacheNode
|
||||
{
|
||||
public:
|
||||
V8_INLINE FObjectCacheNode(const void* TypeId_) : TypeId(TypeId_), UserData(nullptr), Next(nullptr), MustCallFinalize(false)
|
||||
{
|
||||
}
|
||||
|
||||
V8_INLINE FObjectCacheNode(const void* TypeId_, FObjectCacheNode* Next_)
|
||||
: TypeId(TypeId_), UserData(nullptr), Next(Next_), MustCallFinalize(false)
|
||||
{
|
||||
}
|
||||
|
||||
V8_INLINE FObjectCacheNode(FObjectCacheNode&& other) noexcept
|
||||
: TypeId(other.TypeId)
|
||||
, UserData(other.UserData)
|
||||
, Next(other.Next)
|
||||
, Value(std::move(other.Value))
|
||||
, MustCallFinalize(other.MustCallFinalize)
|
||||
{
|
||||
other.TypeId = nullptr;
|
||||
other.UserData = nullptr;
|
||||
other.Next = nullptr;
|
||||
other.MustCallFinalize = false;
|
||||
}
|
||||
|
||||
V8_INLINE FObjectCacheNode& operator=(FObjectCacheNode&& rhs) noexcept
|
||||
{
|
||||
TypeId = rhs.TypeId;
|
||||
Next = rhs.Next;
|
||||
Value = std::move(rhs.Value);
|
||||
UserData = rhs.UserData;
|
||||
MustCallFinalize = rhs.MustCallFinalize;
|
||||
rhs.UserData = nullptr;
|
||||
rhs.TypeId = nullptr;
|
||||
rhs.Next = nullptr;
|
||||
rhs.MustCallFinalize = false;
|
||||
return *this;
|
||||
}
|
||||
|
||||
~FObjectCacheNode()
|
||||
{
|
||||
if (Next)
|
||||
delete Next;
|
||||
}
|
||||
|
||||
V8_INLINE FObjectCacheNode* Find(const void* TypeId_)
|
||||
{
|
||||
if (TypeId_ == TypeId)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
if (Next)
|
||||
{
|
||||
return Next->Find(TypeId_);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
FObjectCacheNode* Remove(const void* TypeId_, bool IsHead)
|
||||
{
|
||||
if (TypeId_ == TypeId)
|
||||
{
|
||||
if (IsHead)
|
||||
{
|
||||
if (Next)
|
||||
{
|
||||
auto PreNext = Next;
|
||||
*this = std::move(*Next);
|
||||
delete PreNext;
|
||||
}
|
||||
else
|
||||
{
|
||||
TypeId = nullptr;
|
||||
Next = nullptr;
|
||||
Value.Reset();
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
if (Next)
|
||||
{
|
||||
auto Removed = Next->Remove(TypeId_, false);
|
||||
if (Removed && Removed == Next) // detach & delete by prev node
|
||||
{
|
||||
Next = Removed->Next;
|
||||
Removed->Next = nullptr;
|
||||
delete Removed;
|
||||
}
|
||||
return Removed;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
V8_INLINE FObjectCacheNode* Add(const void* TypeId_)
|
||||
{
|
||||
Next = new FObjectCacheNode(TypeId_, Next);
|
||||
return Next;
|
||||
}
|
||||
|
||||
const void* TypeId;
|
||||
|
||||
void* UserData;
|
||||
|
||||
FObjectCacheNode* Next;
|
||||
|
||||
v8::UniquePersistent<v8::Value> Value;
|
||||
|
||||
bool MustCallFinalize;
|
||||
|
||||
FObjectCacheNode(const FObjectCacheNode&) = delete;
|
||||
void operator=(const FObjectCacheNode&) = delete;
|
||||
};
|
||||
|
||||
} // namespace PUERTS_NAMESPACE
|
||||
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if USING_IN_UNREAL_ENGINE
|
||||
#include "CoreMinimal.h"
|
||||
#include "PropertyTranslator.h"
|
||||
#include "StructWrapper.h"
|
||||
#endif
|
||||
#include "JSClassRegister.h"
|
||||
|
||||
#include "NamespaceDef.h"
|
||||
|
||||
PRAGMA_DISABLE_UNDEFINED_IDENTIFIER_WARNINGS
|
||||
#pragma warning(push, 0)
|
||||
#include "v8.h"
|
||||
#pragma warning(pop)
|
||||
PRAGMA_ENABLE_UNDEFINED_IDENTIFIER_WARNINGS
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace PUERTS_NAMESPACE
|
||||
{
|
||||
class ICppObjectMapper
|
||||
{
|
||||
public:
|
||||
virtual void BindCppObject(v8::Isolate* Isolate, JSClassDefinition* ClassDefinition, void* Ptr, v8::Local<v8::Object> JSObject,
|
||||
bool PassByPointer) = 0;
|
||||
|
||||
virtual void UnBindCppObject(v8::Isolate* Isolate, JSClassDefinition* ClassDefinition, void* Ptr) = 0;
|
||||
|
||||
virtual v8::Local<v8::Value> FindOrAddCppObject(
|
||||
v8::Isolate* Isolate, v8::Local<v8::Context>& Context, const void* TypeId, void* Ptr, bool PassByPointer) = 0;
|
||||
|
||||
virtual bool IsInstanceOfCppObject(v8::Isolate* Isolate, const void* TypeId, v8::Local<v8::Object> JsObject) = 0;
|
||||
|
||||
virtual void* GetPrivateData(v8::Local<v8::Context> Context, v8::Local<v8::Object> JSObject) = 0;
|
||||
|
||||
virtual void SetPrivateData(v8::Local<v8::Context> Context, v8::Local<v8::Object> JSObject, void* Ptr) = 0;
|
||||
|
||||
virtual v8::MaybeLocal<v8::Function> LoadTypeById(v8::Local<v8::Context> Context, const void* TypeId) = 0;
|
||||
|
||||
virtual std::weak_ptr<int> GetJsEnvLifeCycleTracker() = 0;
|
||||
|
||||
virtual ~ICppObjectMapper()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
#if USING_IN_UNREAL_ENGINE
|
||||
class IObjectMapper : public ICppObjectMapper
|
||||
{
|
||||
public:
|
||||
virtual void Bind(FClassWrapper* ClassWrapper, UObject* UEObject, v8::Local<v8::Object> JSObject) = 0;
|
||||
|
||||
virtual void UnBind(UClass* Class, UObject* UEObject) = 0;
|
||||
|
||||
virtual v8::Local<v8::Value> FindOrAdd(
|
||||
v8::Isolate* Isolate, v8::Local<v8::Context>& Context, UClass* Class, UObject* UEObject) = 0;
|
||||
|
||||
virtual void BindStruct(
|
||||
FScriptStructWrapper* ScriptStructWrapper, void* Ptr, v8::Local<v8::Object> JSObject, bool PassByPointer) = 0;
|
||||
|
||||
virtual void UnBindStruct(FScriptStructWrapper* ScriptStructWrapper, void* Ptr) = 0;
|
||||
|
||||
// PassByPointer为false代表需要在js对象释放时,free相应的内存
|
||||
// 相关信息见该issue:https://github.com/Tencent/puerts/issues/693
|
||||
virtual v8::Local<v8::Value> FindOrAddStruct(
|
||||
v8::Isolate* Isolate, v8::Local<v8::Context>& Context, UScriptStruct* ScriptStruct, void* Ptr, bool PassByPointer) = 0;
|
||||
|
||||
virtual void Merge(
|
||||
v8::Isolate* Isolate, v8::Local<v8::Context> Context, v8::Local<v8::Object> Src, UStruct* DesType, void* Des) = 0;
|
||||
|
||||
virtual void UnBindContainer(void* Ptr) = 0;
|
||||
|
||||
virtual v8::Local<v8::Value> FindOrAddContainer(
|
||||
v8::Isolate* Isolate, v8::Local<v8::Context>& Context, PropertyMacro* Property, FScriptArray* Ptr, bool PassByPointer) = 0;
|
||||
|
||||
virtual v8::Local<v8::Value> FindOrAddContainer(
|
||||
v8::Isolate* Isolate, v8::Local<v8::Context>& Context, PropertyMacro* Property, FScriptSet* Ptr, bool PassByPointer) = 0;
|
||||
|
||||
virtual v8::Local<v8::Value> FindOrAddContainer(v8::Isolate* Isolate, v8::Local<v8::Context>& Context,
|
||||
PropertyMacro* KeyProperty, PropertyMacro* ValueProperty, FScriptMap* Ptr, bool PassByPointer) = 0;
|
||||
|
||||
virtual v8::Local<v8::Value> FindOrAddDelegate(v8::Isolate* Isolate, v8::Local<v8::Context>& Context, UObject* Owner,
|
||||
PropertyMacro* Property, void* DelegatePtr, bool PassByPointer) = 0;
|
||||
|
||||
virtual bool AddToDelegate(
|
||||
v8::Isolate* Isolate, v8::Local<v8::Context>& Context, void* DelegatePtr, v8::Local<v8::Function> JsFunction) = 0;
|
||||
|
||||
virtual PropertyMacro* FindDelegateProperty(void* DelegatePtr) = 0;
|
||||
|
||||
virtual FScriptDelegate NewDelegate(v8::Isolate* Isolate, v8::Local<v8::Context>& Context, UObject* Owner,
|
||||
v8::Local<v8::Function> JsFunction, UFunction* SignatureFunction) = 0;
|
||||
|
||||
virtual bool RemoveFromDelegate(
|
||||
v8::Isolate* Isolate, v8::Local<v8::Context>& Context, void* DelegatePtr, v8::Local<v8::Function> JsFunction) = 0;
|
||||
|
||||
virtual bool ClearDelegate(v8::Isolate* Isolate, v8::Local<v8::Context>& Context, void* DelegatePtr) = 0;
|
||||
|
||||
virtual void ExecuteDelegate(v8::Isolate* Isolate, v8::Local<v8::Context>& Context,
|
||||
const v8::FunctionCallbackInfo<v8::Value>& Info, void* DelegatePtr) = 0;
|
||||
|
||||
virtual v8::Local<v8::Value> CreateArray(
|
||||
v8::Isolate* Isolate, v8::Local<v8::Context>& Context, FPropertyTranslator* Property, void* ArrayPtr) = 0;
|
||||
|
||||
virtual bool IsInstanceOf(UStruct* Struct, v8::Local<v8::Object> JsObject) = 0;
|
||||
|
||||
virtual v8::Local<v8::Value> AddSoftObjectPtr(
|
||||
v8::Isolate* Isolate, v8::Local<v8::Context> Context, FSoftObjectPtr* SoftObjectPtr, UClass* Class, bool IsSoftClass) = 0;
|
||||
};
|
||||
#endif
|
||||
|
||||
} // namespace PUERTS_NAMESPACE
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* 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 "ObjectRetainer.h"
|
||||
#include "PuertsNamespaceDef.h"
|
||||
|
||||
#ifdef THREAD_SAFE
|
||||
PRAGMA_DISABLE_UNDEFINED_IDENTIFIER_WARNINGS
|
||||
#pragma warning(push, 0)
|
||||
#include "v8.h"
|
||||
#pragma warning(pop)
|
||||
PRAGMA_ENABLE_UNDEFINED_IDENTIFIER_WARNINGS
|
||||
#endif
|
||||
|
||||
namespace PUERTS_NAMESPACE
|
||||
{
|
||||
void FObjectRetainer::Retain(UObject* Object)
|
||||
{
|
||||
#ifdef THREAD_SAFE
|
||||
FScopeLock ScopeLock(&RetainedObjectsCritical);
|
||||
#endif
|
||||
if (!RetainedObjects.Contains(Object))
|
||||
{
|
||||
RetainedObjects.Add(Object);
|
||||
}
|
||||
}
|
||||
|
||||
void FObjectRetainer::Release(UObject* Object)
|
||||
{
|
||||
#ifdef THREAD_SAFE
|
||||
FScopeLock ScopeLock(&RetainedObjectsCritical);
|
||||
#endif
|
||||
if (RetainedObjects.Contains(Object))
|
||||
{
|
||||
RetainedObjects.Remove(Object);
|
||||
}
|
||||
}
|
||||
|
||||
void FObjectRetainer::Clear()
|
||||
{
|
||||
#ifdef THREAD_SAFE
|
||||
FScopeLock ScopeLock(&RetainedObjectsCritical);
|
||||
#endif
|
||||
RetainedObjects.Empty();
|
||||
}
|
||||
|
||||
void FObjectRetainer::AddReferencedObjects(FReferenceCollector& Collector)
|
||||
{
|
||||
#ifdef THREAD_SAFE
|
||||
FScopeLock ScopeLock(&RetainedObjectsCritical);
|
||||
#endif
|
||||
Collector.AddReferencedObjects(RetainedObjects);
|
||||
}
|
||||
|
||||
FString FObjectRetainer::GetReferencerName() const
|
||||
{
|
||||
return Name;
|
||||
}
|
||||
|
||||
FObjectRetainer::~FObjectRetainer()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
} // namespace PUERTS_NAMESPACE
|
||||
@@ -0,0 +1,186 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef WITH_QUICKJS
|
||||
|
||||
#include "pesapi.h"
|
||||
#include "CoreMinimal.h"
|
||||
#include "V8Utils.h"
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
||||
#define STRINGIFY_(x) #x
|
||||
#define STRINGIFY(x) STRINGIFY_(x)
|
||||
|
||||
static std::map<std::string, std::string> LoadedModules;
|
||||
|
||||
#if PLATFORM_IOS
|
||||
int PesapiLoadFramework(std::string frameworkName, std::string entryClassName, pesapi_func_ptr* funcPtrArray);
|
||||
#endif
|
||||
|
||||
MSVC_PRAGMA(warning(push))
|
||||
MSVC_PRAGMA(warning(disable : 4191))
|
||||
static pesapi_func_ptr funcs[] = {(pesapi_func_ptr) &pesapi_create_null, (pesapi_func_ptr) &pesapi_create_undefined,
|
||||
(pesapi_func_ptr) &pesapi_create_boolean, (pesapi_func_ptr) &pesapi_create_int32, (pesapi_func_ptr) &pesapi_create_uint32,
|
||||
(pesapi_func_ptr) &pesapi_create_int64, (pesapi_func_ptr) &pesapi_create_uint64, (pesapi_func_ptr) &pesapi_create_double,
|
||||
(pesapi_func_ptr) &pesapi_create_string_utf8, (pesapi_func_ptr) &pesapi_create_binary, (pesapi_func_ptr) &pesapi_create_array,
|
||||
(pesapi_func_ptr) &pesapi_create_object, (pesapi_func_ptr) &pesapi_create_function, (pesapi_func_ptr) &pesapi_create_class,
|
||||
(pesapi_func_ptr) &pesapi_get_value_bool, (pesapi_func_ptr) &pesapi_get_value_int32, (pesapi_func_ptr) &pesapi_get_value_uint32,
|
||||
(pesapi_func_ptr) &pesapi_get_value_int64, (pesapi_func_ptr) &pesapi_get_value_uint64,
|
||||
(pesapi_func_ptr) &pesapi_get_value_double, (pesapi_func_ptr) &pesapi_get_value_string_utf8,
|
||||
(pesapi_func_ptr) &pesapi_get_value_binary, (pesapi_func_ptr) &pesapi_get_array_length, (pesapi_func_ptr) &pesapi_is_null,
|
||||
(pesapi_func_ptr) &pesapi_is_undefined, (pesapi_func_ptr) &pesapi_is_boolean, (pesapi_func_ptr) &pesapi_is_int32,
|
||||
(pesapi_func_ptr) &pesapi_is_uint32, (pesapi_func_ptr) &pesapi_is_int64, (pesapi_func_ptr) &pesapi_is_uint64,
|
||||
(pesapi_func_ptr) &pesapi_is_double, (pesapi_func_ptr) &pesapi_is_string, (pesapi_func_ptr) &pesapi_is_object,
|
||||
(pesapi_func_ptr) &pesapi_is_function, (pesapi_func_ptr) &pesapi_is_binary, (pesapi_func_ptr) &pesapi_is_array,
|
||||
(pesapi_func_ptr) &pesapi_native_object_to_value, (pesapi_func_ptr) &pesapi_get_native_object_ptr,
|
||||
(pesapi_func_ptr) &pesapi_get_native_object_typeid, (pesapi_func_ptr) &pesapi_is_instance_of, (pesapi_func_ptr) &pesapi_boxing,
|
||||
(pesapi_func_ptr) &pesapi_unboxing, (pesapi_func_ptr) &pesapi_update_boxed_value, (pesapi_func_ptr) &pesapi_is_boxed_value,
|
||||
(pesapi_func_ptr) &pesapi_get_args_len, (pesapi_func_ptr) &pesapi_get_arg, (pesapi_func_ptr) &pesapi_get_env,
|
||||
(pesapi_func_ptr) &pesapi_get_this, (pesapi_func_ptr) &pesapi_get_holder, (pesapi_func_ptr) &pesapi_get_userdata,
|
||||
(pesapi_func_ptr) &pesapi_add_return, (pesapi_func_ptr) &pesapi_throw_by_string, (pesapi_func_ptr) &pesapi_create_env_ref,
|
||||
(pesapi_func_ptr) &pesapi_env_ref_is_valid, (pesapi_func_ptr) &pesapi_get_env_from_ref,
|
||||
(pesapi_func_ptr) &pesapi_duplicate_env_ref, (pesapi_func_ptr) &pesapi_release_env_ref, (pesapi_func_ptr) &pesapi_open_scope,
|
||||
(pesapi_func_ptr) &pesapi_open_scope_placement, (pesapi_func_ptr) &pesapi_has_caught,
|
||||
(pesapi_func_ptr) &pesapi_get_exception_as_string, (pesapi_func_ptr) &pesapi_close_scope,
|
||||
(pesapi_func_ptr) &pesapi_close_scope_placement, (pesapi_func_ptr) &pesapi_create_value_ref,
|
||||
(pesapi_func_ptr) &pesapi_duplicate_value_ref, (pesapi_func_ptr) &pesapi_release_value_ref,
|
||||
(pesapi_func_ptr) &pesapi_get_value_from_ref, (pesapi_func_ptr) &pesapi_set_ref_weak, (pesapi_func_ptr) &pesapi_set_owner,
|
||||
(pesapi_func_ptr) &pesapi_get_ref_associated_env, (pesapi_func_ptr) &pesapi_get_ref_internal_fields,
|
||||
(pesapi_func_ptr) &pesapi_get_property, (pesapi_func_ptr) &pesapi_set_property, (pesapi_func_ptr) &pesapi_get_private,
|
||||
(pesapi_func_ptr) &pesapi_set_private, (pesapi_func_ptr) &pesapi_get_property_uint32,
|
||||
(pesapi_func_ptr) &pesapi_set_property_uint32, (pesapi_func_ptr) &pesapi_call_function, (pesapi_func_ptr) &pesapi_eval,
|
||||
(pesapi_func_ptr) &pesapi_global, (pesapi_func_ptr) &pesapi_get_env_private, (pesapi_func_ptr) &pesapi_set_env_private,
|
||||
(pesapi_func_ptr) &pesapi_alloc_type_infos, (pesapi_func_ptr) &pesapi_set_type_info,
|
||||
(pesapi_func_ptr) &pesapi_create_signature_info, (pesapi_func_ptr) &pesapi_alloc_property_descriptors,
|
||||
(pesapi_func_ptr) &pesapi_set_method_info, (pesapi_func_ptr) &pesapi_set_property_info, (pesapi_func_ptr) &pesapi_define_class,
|
||||
(pesapi_func_ptr) &pesapi_get_class_data, (pesapi_func_ptr) &pesapi_trace_native_object_lifecycle,
|
||||
(pesapi_func_ptr) &pesapi_on_class_not_found, (pesapi_func_ptr) &pesapi_class_type_info,
|
||||
(pesapi_func_ptr) &pesapi_find_type_id};
|
||||
MSVC_PRAGMA(warning(pop))
|
||||
|
||||
EXTERN_C_START
|
||||
extern const char* GPesapiModuleName;
|
||||
EXTERN_C_END
|
||||
|
||||
namespace puerts
|
||||
{
|
||||
void LoadPesapiDll(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
if (!Info[0]->IsString())
|
||||
{
|
||||
FV8Utils::ThrowException(Info.GetIsolate(), "#0 argument expect a string");
|
||||
return;
|
||||
}
|
||||
FString Path = FV8Utils::ToFString(Info.GetIsolate(), Info[0]);
|
||||
|
||||
auto Iter = LoadedModules.find(TCHAR_TO_UTF8(*Path));
|
||||
if (Iter != LoadedModules.end())
|
||||
{
|
||||
Info.GetReturnValue().Set(FV8Utils::ToV8String(Info.GetIsolate(), Iter->second.c_str()));
|
||||
return;
|
||||
}
|
||||
|
||||
void* DllHandle = FPlatformProcess::GetDllHandle(*Path);
|
||||
if (!DllHandle)
|
||||
{
|
||||
FV8Utils::ThrowException(Info.GetIsolate(), FString(TEXT("dlopen fail for ")) + Path);
|
||||
return;
|
||||
}
|
||||
|
||||
const FString EntryName = UTF8_TO_TCHAR(STRINGIFY(PESAPI_MODULE_INITIALIZER(dynamic)));
|
||||
auto Init = (const char* (*) (pesapi_func_ptr*) )(uintptr_t) FPlatformProcess::GetDllExport(DllHandle, *EntryName);
|
||||
|
||||
if (Init)
|
||||
{
|
||||
const char* ModuleName = Init(nullptr);
|
||||
GPesapiModuleName = ModuleName;
|
||||
Init(funcs);
|
||||
GPesapiModuleName = nullptr;
|
||||
LoadedModules[TCHAR_TO_UTF8(*Path)] = ModuleName;
|
||||
Info.GetReturnValue().Set(FV8Utils::ToV8String(Info.GetIsolate(), ModuleName));
|
||||
}
|
||||
else
|
||||
{
|
||||
const FString VersionEntryName = UTF8_TO_TCHAR(STRINGIFY(PESAPI_MODULE_VERSION()));
|
||||
auto Ver = (int (*)())(uintptr_t) FPlatformProcess::GetDllExport(DllHandle, *VersionEntryName);
|
||||
if (!Ver)
|
||||
{
|
||||
FV8Utils::ThrowException(Info.GetIsolate(), "can find entry");
|
||||
}
|
||||
else
|
||||
{
|
||||
int PesapiVersion = Ver();
|
||||
FV8Utils::ThrowException(Info.GetIsolate(),
|
||||
FString::Printf(TEXT("pesapi version mismatch, expect: %d, but got %d"), PESAPI_VERSION, PesapiVersion));
|
||||
}
|
||||
FPlatformProcess::FreeDllHandle(DllHandle);
|
||||
}
|
||||
}
|
||||
} // namespace puerts
|
||||
|
||||
static int LoadAddon(const char* path, const char* module_name)
|
||||
{
|
||||
if (LoadedModules.find(path) != LoadedModules.end())
|
||||
{
|
||||
// UE_LOG(LogTemp, Warning, TEXT("Try load addon already loaded: %s"), UTF8_TO_TCHAR(path));
|
||||
return 0;
|
||||
}
|
||||
#if !PLATFORM_IOS
|
||||
void* Handle = FPlatformProcess::GetDllHandle(UTF8_TO_TCHAR(path));
|
||||
if (Handle)
|
||||
{
|
||||
FString EntryName = UTF8_TO_TCHAR(STRINGIFY(PESAPI_MODULE_INITIALIZER(dynamic)));
|
||||
|
||||
auto Init = (const char* (*) (pesapi_func_ptr*) )(uintptr_t) FPlatformProcess::GetDllExport(Handle, *EntryName);
|
||||
if (Init)
|
||||
{
|
||||
const char* ModuleName = Init(nullptr);
|
||||
GPesapiModuleName = ModuleName;
|
||||
Init(funcs);
|
||||
GPesapiModuleName = nullptr;
|
||||
LoadedModules[path] = ModuleName;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
FString VersionEntryName = UTF8_TO_TCHAR(STRINGIFY(PESAPI_MODULE_VERSION()));
|
||||
auto Ver = (int (*)())(uintptr_t) FPlatformProcess::GetDllExport(Handle, *VersionEntryName);
|
||||
if (!Ver)
|
||||
{
|
||||
UE_LOG(LogTemp, Error, TEXT("Could not find entry for: %s"), UTF8_TO_TCHAR(path));
|
||||
}
|
||||
else
|
||||
{
|
||||
int PesapiVersion = Ver();
|
||||
UE_LOG(LogTemp, Error, TEXT("pesapi version mismatch, expect: %d, but got: %d"), PESAPI_VERSION, PesapiVersion);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
UE_LOG(LogTemp, Error, TEXT("Could not load addon: %s"), UTF8_TO_TCHAR(path));
|
||||
}
|
||||
return -1;
|
||||
#else
|
||||
FString EntryName = UTF8_TO_TCHAR(STRINGIFY(PESAPI_MODULE_INITIALIZER(___magic_module_name_xx___)));
|
||||
EntryName = EntryName.Replace(TEXT("___magic_module_name_xx___"), UTF8_TO_TCHAR(module_name));
|
||||
return PesapiLoadFramework(module_name, TCHAR_TO_UTF8(*EntryName), funcs);
|
||||
#endif
|
||||
}
|
||||
|
||||
EXTERN_C_START
|
||||
int pesapi_load_addon(const char* path, const char* module_name)
|
||||
{
|
||||
return LoadAddon(path, module_name);
|
||||
}
|
||||
EXTERN_C_END
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,113 @@
|
||||
#pragma once
|
||||
#include <sstream>
|
||||
#if !defined(PUERTS_NAMESPACE)
|
||||
#if defined(WITH_QJS_NAMESPACE_SUFFIX)
|
||||
#define PUERTS_NAMESPACE puerts_qjs
|
||||
#else
|
||||
#define PUERTS_NAMESPACE puerts
|
||||
#endif
|
||||
#endif
|
||||
|
||||
namespace PUERTS_NAMESPACE
|
||||
{
|
||||
template <typename T>
|
||||
inline void __USE(T&&)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void PromiseRejectCallback(v8::PromiseRejectMessage Message)
|
||||
{
|
||||
auto Promise = Message.GetPromise();
|
||||
auto Isolate = Promise->GetIsolate();
|
||||
auto Event = Message.GetEvent();
|
||||
|
||||
auto JsEngine = T::Get(Isolate);
|
||||
auto Callback = JsEngine->JsPromiseRejectCallback.Get(Isolate);
|
||||
if (Callback.IsEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> Value;
|
||||
|
||||
if (Event == v8::kPromiseRejectWithNoHandler)
|
||||
{
|
||||
Value = Message.GetValue();
|
||||
}
|
||||
else if (Event == v8::kPromiseHandlerAddedAfterReject)
|
||||
{
|
||||
Value = v8::Undefined(Isolate);
|
||||
}
|
||||
else if (Event == v8::kPromiseResolveAfterResolved)
|
||||
{
|
||||
Value = Message.GetValue();
|
||||
}
|
||||
else if (Event == v8::kPromiseRejectAfterResolved)
|
||||
{
|
||||
Value = Message.GetValue();
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (Value.IsEmpty())
|
||||
{
|
||||
Value = v8::Undefined(Isolate);
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> Args[] = {v8::Number::New(Isolate, Event), Promise, Value};
|
||||
__USE(Callback->Call(Isolate->GetCurrentContext(), v8::Undefined(Isolate), 3, Args));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void SetPromiseRejectCallback(const v8::FunctionCallbackInfo<v8::Value>& Args)
|
||||
{
|
||||
auto Isolate = Args.GetIsolate();
|
||||
auto JsEngine = T::Get(Isolate);
|
||||
JsEngine->JsPromiseRejectCallback.Reset(Isolate, Args[0].As<v8::Function>());
|
||||
}
|
||||
|
||||
// TODO: rename this file
|
||||
#ifndef WITH_QUICKJS
|
||||
std::string StackTraceToString(v8::Isolate* InIsolate, v8::Local<v8::StackTrace> InStack)
|
||||
{
|
||||
std::ostringstream stm;
|
||||
for (int i = 0; i < InStack->GetFrameCount(); i++)
|
||||
{
|
||||
v8::Local<v8::StackFrame> StackFrame = InStack->GetFrame(InIsolate, i);
|
||||
v8::String::Utf8Value FuncName(InIsolate, StackFrame->GetFunctionName());
|
||||
v8::String::Utf8Value ScriptName(InIsolate, StackFrame->GetScriptName());
|
||||
const int LineNumber = StackFrame->GetLineNumber();
|
||||
const int Column = StackFrame->GetColumn();
|
||||
|
||||
if (StackFrame->IsEval())
|
||||
{
|
||||
if (StackFrame->GetScriptId() == v8::Message::kNoScriptIdInfo)
|
||||
{
|
||||
stm << " at [eval]:" << LineNumber << ":" << Column << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
stm << " at [eval] (" << (*ScriptName ? *ScriptName : "anonymous") << ":" << LineNumber << ":" << Column << ")"
|
||||
<< std::endl;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (FuncName.length() == 0)
|
||||
{
|
||||
stm << " at " << (*ScriptName ? *ScriptName : "anonymous") << ":" << LineNumber << ":" << Column << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
stm << " at " << *FuncName << "(" << (*ScriptName ? *ScriptName : "anonymous") << ":" << LineNumber << ":" << Column
|
||||
<< ")" << std::endl;
|
||||
}
|
||||
}
|
||||
return stm.str();
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace PUERTS_NAMESPACE
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,202 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "CoreUObject.h"
|
||||
#include "Runtime/Launch/Resources/Version.h"
|
||||
#include "PropertyMacros.h"
|
||||
|
||||
#if ENGINE_MINOR_VERSION >= 25 || ENGINE_MAJOR_VERSION > 4
|
||||
#include "UObject/WeakFieldPtr.h"
|
||||
#endif
|
||||
|
||||
#include "NamespaceDef.h"
|
||||
#include "ArrayBuffer.h"
|
||||
#include "JsObject.h"
|
||||
|
||||
PRAGMA_DISABLE_UNDEFINED_IDENTIFIER_WARNINGS
|
||||
#pragma warning(push, 0)
|
||||
#include "libplatform/libplatform.h"
|
||||
#include "v8.h"
|
||||
#pragma warning(pop)
|
||||
PRAGMA_ENABLE_UNDEFINED_IDENTIFIER_WARNINGS
|
||||
|
||||
namespace PUERTS_NAMESPACE
|
||||
{
|
||||
class FPropertyTranslator
|
||||
{
|
||||
public:
|
||||
static std::unique_ptr<FPropertyTranslator> Create(PropertyMacro* InProperty, bool IgnoreOut = false);
|
||||
|
||||
static void CreateOn(PropertyMacro* InProperty, FPropertyTranslator* InOldProperty);
|
||||
|
||||
FORCEINLINE v8::Local<v8::Value> UEToJsInContainer(
|
||||
v8::Isolate* Isolate, v8::Local<v8::Context>& Context, const void* ContainerPtr, bool PassByPointer = false) const
|
||||
{
|
||||
return UEToJs(Isolate, Context, Property->ContainerPtrToValuePtr<void>(ContainerPtr), PassByPointer);
|
||||
}
|
||||
|
||||
FORCEINLINE bool JsToUEInContainer(v8::Isolate* Isolate, v8::Local<v8::Context>& Context, const v8::Local<v8::Value>& Value,
|
||||
void* ContainerPtr, bool DeepCopy) const
|
||||
{
|
||||
return JsToUE(Isolate, Context, Value, Property->ContainerPtrToValuePtr<void>(ContainerPtr), DeepCopy);
|
||||
}
|
||||
|
||||
FORCEINLINE bool JsToUEFastInContainer(v8::Isolate* Isolate, v8::Local<v8::Context>& Context, const v8::Local<v8::Value>& Value,
|
||||
void* TempBuff, void** OutValuePtr) const
|
||||
{
|
||||
return JsToUEFast(Isolate, Context, Value, Property->ContainerPtrToValuePtr<void>(TempBuff), OutValuePtr);
|
||||
}
|
||||
|
||||
FORCEINLINE void UEOutToJsInContainer(v8::Isolate* Isolate, v8::Local<v8::Context>& Context, const v8::Local<v8::Value>& Value,
|
||||
const void* ContainerPtr, bool PassByPointer) const
|
||||
{
|
||||
UEOutToJs(Isolate, Context, Value, Property->ContainerPtrToValuePtr<void>(ContainerPtr), PassByPointer);
|
||||
}
|
||||
|
||||
FORCEINLINE bool JsToUEOutInContainer(v8::Isolate* Isolate, v8::Local<v8::Context>& Context, const v8::Local<v8::Value>& Value,
|
||||
void* ContainerPtr, bool PassByPointer) const
|
||||
{
|
||||
return JsToUEOut(Isolate, Context, Value, Property->ContainerPtrToValuePtr<void>(ContainerPtr), PassByPointer);
|
||||
}
|
||||
|
||||
virtual v8::Local<v8::Value> UEToJs(
|
||||
v8::Isolate* Isolate, v8::Local<v8::Context>& Context, const void* ValuePtr, bool PassByPointer) const = 0;
|
||||
|
||||
virtual bool JsToUE(v8::Isolate* Isolate, v8::Local<v8::Context>& Context, const v8::Local<v8::Value>& Value, void* ValuePtr,
|
||||
bool DeepCopy) const = 0;
|
||||
|
||||
virtual bool JsToUEFast(v8::Isolate* Isolate, v8::Local<v8::Context>& Context, const v8::Local<v8::Value>& Value,
|
||||
void* TempBuff, void** OutValuePtr) const
|
||||
{
|
||||
*OutValuePtr = TempBuff; // using temp buffer by default
|
||||
return JsToUE(Isolate, Context, Value, TempBuff, false);
|
||||
}
|
||||
|
||||
virtual void Cleanup(void* ContainerPtr) const
|
||||
{
|
||||
}
|
||||
|
||||
virtual void UEOutToJs(v8::Isolate* Isolate, v8::Local<v8::Context>& Context, const v8::Local<v8::Value>& Value,
|
||||
const void* ValuePtr, bool PassByPointer) const
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool JsToUEOut(v8::Isolate* Isolate, v8::Local<v8::Context>& Context, const v8::Local<v8::Value>& Value, void* ValuePtr,
|
||||
bool DeepCopy) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool IsOut() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
explicit FPropertyTranslator(PropertyMacro* InProperty)
|
||||
{
|
||||
Init(InProperty);
|
||||
}
|
||||
|
||||
FORCEINLINE void Init(PropertyMacro* InProperty)
|
||||
{
|
||||
Property = InProperty;
|
||||
PropertyWeakPtr = InProperty;
|
||||
OwnerIsClass = InProperty->GetOwnerClass() != nullptr;
|
||||
NeedLinkOuter = false;
|
||||
if (!OwnerIsClass)
|
||||
{
|
||||
if ((InProperty->IsA<StructPropertyMacro>() && StructProperty->Struct != FArrayBuffer::StaticStruct() &&
|
||||
StructProperty->Struct != FArrayBufferValue::StaticStruct() &&
|
||||
StructProperty->Struct != FJsObject::StaticStruct()) ||
|
||||
InProperty->IsA<MapPropertyMacro>() || InProperty->IsA<ArrayPropertyMacro>() || InProperty->IsA<SetPropertyMacro>())
|
||||
{
|
||||
NeedLinkOuter = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual ~FPropertyTranslator()
|
||||
{
|
||||
}
|
||||
|
||||
union
|
||||
{
|
||||
PropertyMacro* Property;
|
||||
NumericPropertyMacro* NumericProperty;
|
||||
IntPropertyMacro* IntProperty;
|
||||
EnumPropertyMacro* EnumProperty;
|
||||
BoolPropertyMacro* BoolProperty;
|
||||
ObjectPropertyBaseMacro* ObjectBaseProperty;
|
||||
SoftObjectPropertyMacro* SoftObjectProperty;
|
||||
SoftClassPropertyMacro* SoftClassProperty;
|
||||
InterfacePropertyMacro* InterfaceProperty;
|
||||
NamePropertyMacro* NameProperty;
|
||||
StrPropertyMacro* StringProperty;
|
||||
TextPropertyMacro* TextProperty;
|
||||
ArrayPropertyMacro* ArrayProperty;
|
||||
MapPropertyMacro* MapProperty;
|
||||
SetPropertyMacro* SetProperty;
|
||||
StructPropertyMacro* StructProperty;
|
||||
DelegatePropertyMacro* DelegateProperty;
|
||||
MulticastDelegatePropertyMacro* MulticastDelegateProperty;
|
||||
ClassPropertyMacro* ClassProperty;
|
||||
#if ENGINE_MINOR_VERSION >= 25 || ENGINE_MAJOR_VERSION > 4
|
||||
FFieldPathProperty* FieldPathProperty;
|
||||
#endif
|
||||
};
|
||||
|
||||
bool OwnerIsClass;
|
||||
|
||||
bool NeedLinkOuter;
|
||||
|
||||
size_t ParamShallowCopySize = 0;
|
||||
|
||||
std::unique_ptr<FPropertyTranslator> Inner;
|
||||
|
||||
static void Getter(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
|
||||
void Getter(v8::Isolate* Isolate, v8::Local<v8::Context>& Context, const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
|
||||
static void Setter(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
|
||||
void Setter(v8::Isolate* Isolate, v8::Local<v8::Context>& Context, v8::Local<v8::Value> Value,
|
||||
const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
|
||||
static void DelegateGetter(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
|
||||
void SetAccessor(v8::Isolate* Isolate, v8::Local<v8::FunctionTemplate> Template);
|
||||
|
||||
bool IsPropertyValid()
|
||||
{
|
||||
if (!PropertyWeakPtr.IsValid())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#if WITH_EDITOR
|
||||
FProperty* TestP = PropertyWeakPtr.Get();
|
||||
if (TestP != Property)
|
||||
{
|
||||
Init(TestP);
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
#if ENGINE_MINOR_VERSION < 25 && ENGINE_MAJOR_VERSION < 5
|
||||
TWeakObjectPtr<PropertyMacro> PropertyWeakPtr;
|
||||
#else
|
||||
TWeakFieldPtr<PropertyMacro> PropertyWeakPtr;
|
||||
#endif
|
||||
};
|
||||
} // namespace PUERTS_NAMESPACE
|
||||
@@ -0,0 +1,337 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
#if USE_WASM3
|
||||
#include "WasmJsFunctionParams.h"
|
||||
#include "ContainerMeta.h"
|
||||
#include "Misc/FileHelper.h"
|
||||
#include "Serialization/JsonReader.h"
|
||||
#include "WasmRuntime.h"
|
||||
#include "V8Utils.h"
|
||||
#include "JSLogger.h"
|
||||
#include "../ObjectMapper.h"
|
||||
#include "UECompatible.h"
|
||||
#include "WasmModuleInstance.h"
|
||||
#include "GenericPlatform/GenericPlatformMemory.h"
|
||||
|
||||
namespace PUERTS_NAMESPACE
|
||||
{
|
||||
static void NormalInstanceCall(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
IM3Function _Function = static_cast<IM3Function>((v8::Local<v8::External>::Cast(Info.Data()))->Value());
|
||||
int argCount = _Function->funcType->numArgs;
|
||||
check(Info.Length() >= argCount);
|
||||
|
||||
auto Isolate = Info.GetIsolate();
|
||||
auto Context = Isolate->GetCurrentContext();
|
||||
int64* args = (int64*) FMemory_Alloca(sizeof(int64) * argCount);
|
||||
void** argsPointer = (void**) FMemory_Alloca(sizeof(void*) * argCount);
|
||||
for (int Index = 0; Index < argCount; Index++)
|
||||
{
|
||||
const int type = _Function->funcType->types[_Function->funcType->numRets + Index];
|
||||
switch (type)
|
||||
{
|
||||
case c_m3Type_i32:
|
||||
check(Info[Index]->IsNumber());
|
||||
*((int*) (args + Index)) = Info[Index]->Int32Value(Context).ToChecked();
|
||||
argsPointer[Index] = args + Index;
|
||||
break;
|
||||
case c_m3Type_i64:
|
||||
check(Info[Index]->IsBigInt());
|
||||
*(args + Index) = Info[Index]->ToBigInt(Context).ToLocalChecked()->Int64Value();
|
||||
argsPointer[Index] = args + Index;
|
||||
break;
|
||||
case c_m3Type_f32:
|
||||
check(Info[Index]->IsNumber());
|
||||
*((float*) (args + Index)) = (float) Info[Index]->NumberValue(Context).ToChecked();
|
||||
argsPointer[Index] = args + Index;
|
||||
break;
|
||||
case c_m3Type_f64:
|
||||
check(Info[Index]->IsNumber());
|
||||
*((double*) (args + Index)) = Info[Index]->NumberValue(Context).ToChecked();
|
||||
argsPointer[Index] = args + Index;
|
||||
break;
|
||||
default:
|
||||
check(0);
|
||||
}
|
||||
}
|
||||
if (Export_m3_Call(_Function, argCount, (const void**) argsPointer))
|
||||
{
|
||||
check(_Function->funcType->numRets <= 1);
|
||||
if (_Function->funcType->numRets == 1)
|
||||
{
|
||||
int64 RetValue;
|
||||
void* ret[1] = {&RetValue};
|
||||
if (Export_m3_GetResults(_Function, 1, (const void**) ret))
|
||||
{
|
||||
const int type = _Function->funcType->types[0];
|
||||
switch (type)
|
||||
{
|
||||
case c_m3Type_i32:
|
||||
Info.GetReturnValue().Set(*((int*) (&RetValue)));
|
||||
break;
|
||||
case c_m3Type_i64:
|
||||
Info.GetReturnValue().Set(v8::BigInt::New(Isolate, RetValue));
|
||||
break;
|
||||
case c_m3Type_f32:
|
||||
Info.GetReturnValue().Set(*((float*) (&RetValue)));
|
||||
break;
|
||||
case c_m3Type_f64:
|
||||
Info.GetReturnValue().Set(*((double*) (&RetValue)));
|
||||
default:
|
||||
check(0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FV8Utils::ThrowException(Isolate, "call wasm get results failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FV8Utils::ThrowException(Isolate, "call wasm failed");
|
||||
}
|
||||
}
|
||||
|
||||
static const void* NormalInstanceLink(IM3Runtime runtime, IM3ImportContext _ctx, uint64_t* _sp, void* _mem)
|
||||
{
|
||||
IM3Function _Function = _ctx->function;
|
||||
WasmNormalLinkInfo* _Info = (WasmNormalLinkInfo*) _ctx->userdata;
|
||||
check(_Function->funcType->numRets <= 1);
|
||||
uint64_t* raw_sp = _sp;
|
||||
if (_Function->funcType->numRets > 0)
|
||||
{
|
||||
_sp++;
|
||||
}
|
||||
TArray<v8::Local<v8::Value>, TInlineAllocator<20>> Params;
|
||||
check(_Function->funcType->numArgs < 20);
|
||||
for (int i = 0; i < _Function->funcType->numArgs; i++)
|
||||
{
|
||||
const int type = _Function->funcType->types[_Function->funcType->numRets + i];
|
||||
switch (type)
|
||||
{
|
||||
case c_m3Type_i32:
|
||||
Params.Add(v8::Int32::New(_Info->Isolate, *((int32*) (_sp + i))));
|
||||
break;
|
||||
case c_m3Type_i64:
|
||||
Params.Add(v8::BigInt::New(_Info->Isolate, *(_sp + i)));
|
||||
break;
|
||||
case c_m3Type_f32:
|
||||
Params.Add(v8::Number::New(_Info->Isolate, *((float*) (_sp + i))));
|
||||
break;
|
||||
case c_m3Type_f64:
|
||||
Params.Add(v8::Number::New(_Info->Isolate, *((double*) (_sp + i))));
|
||||
break;
|
||||
default:
|
||||
check(0);
|
||||
}
|
||||
}
|
||||
v8::TryCatch TryCatch(_Info->Isolate);
|
||||
auto Ret = _Info->CachedFunction.Get(_Info->Isolate)
|
||||
->Call(_Info->Isolate->GetCurrentContext(), v8::Undefined(_Info->Isolate), Params.Num(), Params.GetData());
|
||||
if (TryCatch.HasCaught())
|
||||
{
|
||||
UE_LOG(Puerts, Error, TEXT("%s"), *FV8Utils::TryCatchToString(_Info->Isolate, &TryCatch));
|
||||
return "some error";
|
||||
}
|
||||
if (_Function->funcType->numRets == 1)
|
||||
{
|
||||
v8::Local<v8::Value> RetValue = Ret.ToLocalChecked();
|
||||
const int type = _Function->funcType->types[0];
|
||||
switch (type)
|
||||
{
|
||||
case c_m3Type_i32:
|
||||
check(RetValue->IsNumber());
|
||||
*((int*) (raw_sp)) = RetValue->Int32Value(_Info->Isolate->GetCurrentContext()).ToChecked();
|
||||
break;
|
||||
case c_m3Type_i64:
|
||||
check(RetValue->IsBigInt());
|
||||
*raw_sp = RetValue->ToBigInt(_Info->Isolate->GetCurrentContext()).ToLocalChecked()->Int64Value();
|
||||
break;
|
||||
case c_m3Type_f32:
|
||||
check(RetValue->IsNumber());
|
||||
*((float*) (raw_sp)) = RetValue->NumberValue(_Info->Isolate->GetCurrentContext()).ToChecked();
|
||||
break;
|
||||
case c_m3Type_f64:
|
||||
check(RetValue->IsNumber());
|
||||
*((double*) (raw_sp)) = RetValue->NumberValue(_Info->Isolate->GetCurrentContext()).ToChecked();
|
||||
break;
|
||||
default:
|
||||
check(0);
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
WasmRuntime* NormalInstanceModule(v8::Isolate* Isolate, v8::Local<v8::Context>& Context, TArray<uint8>& InData,
|
||||
v8::Local<v8::Object>& ExportsObject, v8::Local<v8::Value> ImportsValue,
|
||||
const TArray<std::shared_ptr<WasmRuntime>>& RuntimeList, TArray<WasmNormalLinkInfo*>& CachedLinkFunctionList)
|
||||
{
|
||||
WasmRuntime* UsedRuntime = RuntimeList[0].get();
|
||||
|
||||
v8::Local<v8::Object> MemoryObject;
|
||||
v8::Local<v8::Object> ImportsObject;
|
||||
//需要同时支持使用js mem以及 env memory
|
||||
if (ImportsValue->IsObject())
|
||||
{
|
||||
v8::Local<v8::Object> EnvObject;
|
||||
ImportsObject = ImportsValue.As<v8::Object>();
|
||||
{
|
||||
auto MaybeEnvValue = ImportsObject->Get(Context, FV8Utils::ToV8String(Isolate, "env"));
|
||||
if (!MaybeEnvValue.IsEmpty())
|
||||
{
|
||||
auto EnvValue = MaybeEnvValue.ToLocalChecked();
|
||||
if (EnvValue->IsObject())
|
||||
{
|
||||
EnvObject = EnvValue.As<v8::Object>();
|
||||
|
||||
auto MaybeMemory = EnvObject->Get(Context, FV8Utils::ToV8String(Isolate, "memory"));
|
||||
if (!MaybeMemory.IsEmpty())
|
||||
{
|
||||
auto MemoryValue = MaybeMemory.ToLocalChecked();
|
||||
if (MemoryValue->IsObject())
|
||||
{
|
||||
MemoryObject = MemoryValue.As<v8::Object>();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (EnvObject.IsEmpty())
|
||||
{
|
||||
auto MaybeEnvValue = ImportsObject->Get(Context, FV8Utils::ToV8String(Isolate, "js"));
|
||||
if (!MaybeEnvValue.IsEmpty())
|
||||
{
|
||||
auto EnvValue = MaybeEnvValue.ToLocalChecked();
|
||||
if (EnvValue->IsObject())
|
||||
{
|
||||
EnvObject = EnvValue.As<v8::Object>();
|
||||
|
||||
auto MaybeMemory = EnvObject->Get(Context, FV8Utils::ToV8String(Isolate, "mem"));
|
||||
if (!MaybeMemory.IsEmpty())
|
||||
{
|
||||
auto MemoryValue = MaybeMemory.ToLocalChecked();
|
||||
if (MemoryValue->IsObject())
|
||||
{
|
||||
MemoryObject = MemoryValue.As<v8::Object>();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//默认情况下使用第一个runtime,其他情况使用memory里面指定的
|
||||
if (!MemoryObject.IsEmpty())
|
||||
{
|
||||
int Seq =
|
||||
MemoryObject->Get(Context, FV8Utils::ToV8String(Isolate, "_Seq")).ToLocalChecked()->Int32Value(Context).ToChecked();
|
||||
for (auto r : RuntimeList)
|
||||
{
|
||||
if (r->GetRuntimeSeq() == Seq)
|
||||
{
|
||||
UsedRuntime = r.get();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto CustomLinkFunc = [&](IM3Module _Module) -> bool
|
||||
{
|
||||
if (!ImportsObject.IsEmpty())
|
||||
{
|
||||
auto ModuleNames = ImportsObject->GetOwnPropertyNames(Context).ToLocalChecked();
|
||||
for (decltype(ModuleNames->Length()) j = 0; j < ModuleNames->Length(); ++j)
|
||||
{
|
||||
v8::Local<v8::Value> ModuleName;
|
||||
v8::Local<v8::Value> ModuleValue;
|
||||
if (ModuleNames->Get(Context, j).ToLocal(&ModuleName) &&
|
||||
ImportsObject->Get(Context, ModuleName).ToLocal(&ModuleValue))
|
||||
{
|
||||
auto Module = ModuleValue.As<v8::Object>();
|
||||
v8::String::Utf8Value UtfModuleName(Isolate, ModuleName);
|
||||
auto FunctionNames = Module->GetOwnPropertyNames(Context).ToLocalChecked();
|
||||
for (decltype(FunctionNames->Length()) i = 0; i < FunctionNames->Length(); ++i)
|
||||
{
|
||||
v8::Local<v8::Value> FunctionName;
|
||||
v8::Local<v8::Value> FunctionValue;
|
||||
if (FunctionNames->Get(Context, i).ToLocal(&FunctionName) &&
|
||||
Module->Get(Context, FunctionName).ToLocal(&FunctionValue))
|
||||
{
|
||||
if (FunctionValue->IsFunction())
|
||||
{
|
||||
WasmNormalLinkInfo* NewInfo = new WasmNormalLinkInfo();
|
||||
NewInfo->CachedFunction.Reset(Isolate, FunctionValue.As<v8::Function>());
|
||||
NewInfo->Isolate = Isolate;
|
||||
CachedLinkFunctionList.Add(NewInfo);
|
||||
if (!Export_m3_LinkRawFunctionEx(_Module, *UtfModuleName,
|
||||
(*(v8::String::Utf8Value(Isolate, FunctionName))), nullptr, &NormalInstanceLink, NewInfo))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
WasmModuleInstance* NewInstance = new WasmModuleInstance(InData);
|
||||
if (NewInstance->ParseModule(UsedRuntime->GetEnv()))
|
||||
{
|
||||
//如果没有指明需要import memory,那么使用默认的runtime即可,即便外面传入了memory也不生效
|
||||
if (!NewInstance->GetModule()->memoryImported)
|
||||
{
|
||||
UsedRuntime = RuntimeList[0].get();
|
||||
}
|
||||
|
||||
if (!NewInstance->LoadModule(UsedRuntime, 0, CustomLinkFunc))
|
||||
{
|
||||
delete NewInstance;
|
||||
NewInstance = nullptr;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
delete NewInstance;
|
||||
NewInstance = nullptr;
|
||||
}
|
||||
if (NewInstance && NewInstance->GetAllExportFunctions().Num())
|
||||
{
|
||||
IM3Module _Module = NewInstance->GetModule();
|
||||
for (uint32 i = 0; i < _Module->numFunctions; ++i)
|
||||
{
|
||||
IM3Function f = &_Module->functions[i];
|
||||
if (f->compiled && f->export_name && *(f->export_name))
|
||||
{
|
||||
auto Data = v8::External::New(Isolate, f);
|
||||
auto Func = v8::Function::New(Context, NormalInstanceCall, Data).ToLocalChecked();
|
||||
Func->Set(Context, FV8Utils::ToV8String(Isolate, M3_FUNCTION_KEY), Data);
|
||||
(void) ExportsObject->Set(Context, FV8Utils::ToV8String(Isolate, f->export_name), Func);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (NewInstance->GetModule()->memoryExportName)
|
||||
{
|
||||
(void) ExportsObject->Set(Context, FV8Utils::ToV8String(Isolate, "__memoryExport"),
|
||||
FV8Utils::ToV8String(Isolate, NewInstance->GetModule()->memoryExportName));
|
||||
}
|
||||
if (NewInstance->GetModule()->tableExportName)
|
||||
{
|
||||
(void) ExportsObject->Set(Context, FV8Utils::ToV8String(Isolate, "__tableExport"),
|
||||
FV8Utils::ToV8String(Isolate, NewInstance->GetModule()->tableExportName));
|
||||
(void) ExportsObject->Set(
|
||||
Context, FV8Utils::ToV8String(Isolate, "__moduleIndex"), v8::Integer::New(Isolate, NewInstance->Index));
|
||||
}
|
||||
return UsedRuntime;
|
||||
}
|
||||
|
||||
} // namespace PUERTS_NAMESPACE
|
||||
#endif
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#if USE_WASM3
|
||||
#include "CoreMinimal.h"
|
||||
#include "WasmModule.h"
|
||||
#include "PuertsNamespaceDef.h"
|
||||
|
||||
PRAGMA_DISABLE_UNDEFINED_IDENTIFIER_WARNINGS
|
||||
#pragma warning(push, 0)
|
||||
#include "libplatform/libplatform.h"
|
||||
#include "v8.h"
|
||||
#pragma warning(pop)
|
||||
PRAGMA_ENABLE_UNDEFINED_IDENTIFIER_WARNINGS
|
||||
|
||||
#include "WasmFunction.h"
|
||||
|
||||
#define M3_FUNCTION_KEY "__puerts_inner_m3_func"
|
||||
|
||||
namespace PUERTS_NAMESPACE
|
||||
{
|
||||
struct WasmNormalLinkInfo
|
||||
{
|
||||
v8::UniquePersistent<v8::Function> CachedFunction;
|
||||
v8::Isolate* Isolate;
|
||||
};
|
||||
|
||||
WasmRuntime* NormalInstanceModule(v8::Isolate* Isolate, v8::Local<v8::Context>& Context, TArray<uint8>& InData,
|
||||
v8::Local<v8::Object>& ExportsObject, v8::Local<v8::Value> ImportsValue,
|
||||
const TArray<std::shared_ptr<WasmRuntime>>& RuntimeList, TArray<WasmNormalLinkInfo*>& CachedLinkFunctionList);
|
||||
}; // namespace PUERTS_NAMESPACE
|
||||
#endif
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#if USE_WASM3
|
||||
#include <array>
|
||||
#include <tuple>
|
||||
#include "WasmRuntime.h"
|
||||
#include "WasmModule.h"
|
||||
#include "WasmFunction.h"
|
||||
#include "WasmStaticLink.h"
|
||||
#include "CoreMinimal.h"
|
||||
#include "Binding.hpp"
|
||||
#include "UEDataBinding.hpp"
|
||||
|
||||
struct AutoRegisterForWasmExtension
|
||||
{
|
||||
};
|
||||
AutoRegisterForWasmExtension __AutoRegisterForWasmExtension__;
|
||||
#endif
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#if USE_WASM3
|
||||
#include <array>
|
||||
#include <tuple>
|
||||
#include "WasmRuntime.h"
|
||||
#include "WasmModule.h"
|
||||
#include "WasmFunction.h"
|
||||
#include "WasmStaticLink.h"
|
||||
#include "CoreMinimal.h"
|
||||
#include "Binding.hpp"
|
||||
#include "UEDataBinding.hpp"
|
||||
#include "Kismet/KismetMathLibrary.h"
|
||||
|
||||
float atan2_ue_bind(float X, float Y)
|
||||
{
|
||||
return UKismetMathLibrary::Atan2(X, Y);
|
||||
}
|
||||
|
||||
WASM_BEGIN_LINK_GLOBAL(TestMath, 0)
|
||||
WASM_LINK_GLOBAL(atan2_ue_bind)
|
||||
WASM_END_LINK_GLOBAL(TestMath, 0)
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,89 @@
|
||||
#include "SoftObjectWrapper.h"
|
||||
#include "V8Utils.h"
|
||||
#include "ObjectMapper.h"
|
||||
|
||||
namespace PUERTS_NAMESPACE
|
||||
{
|
||||
v8::Local<v8::FunctionTemplate> FSoftObjectWrapper::ToFunctionTemplate(v8::Isolate* Isolate)
|
||||
{
|
||||
auto Result = v8::FunctionTemplate::New(Isolate);
|
||||
Result->InstanceTemplate()->SetInternalFieldCount(6);
|
||||
Result->PrototypeTemplate()->Set(
|
||||
FV8Utils::ToV8String(Isolate, "LoadSynchronous"), v8::FunctionTemplate::New(Isolate, &LoadSynchronous));
|
||||
Result->PrototypeTemplate()->Set(FV8Utils::ToV8String(Isolate, "Get"), v8::FunctionTemplate::New(Isolate, &Get));
|
||||
return Result;
|
||||
}
|
||||
|
||||
typedef UObject* (*FSoftObjectPtrObjectGetter)(FSoftObjectPtr* Ptr);
|
||||
|
||||
static void GenericObjectGet(const v8::FunctionCallbackInfo<v8::Value>& Info, FSoftObjectPtrObjectGetter Getter)
|
||||
{
|
||||
auto Isolate = Info.GetIsolate();
|
||||
auto Context = Isolate->GetCurrentContext();
|
||||
|
||||
FSoftObjectPtr* Ptr = FV8Utils::GetPointerFast<FSoftObjectPtr>(Info.Holder());
|
||||
if (!Ptr)
|
||||
{
|
||||
FV8Utils::ThrowException(Isolate, "passing a invalid object for FSoftObjectPtr");
|
||||
return;
|
||||
}
|
||||
auto Obj = Getter(Ptr);
|
||||
|
||||
if (Obj)
|
||||
{
|
||||
UClass* PropertyClass = nullptr;
|
||||
if (UObject* Object = FV8Utils::GetUObject(Info.Holder(), 1))
|
||||
{
|
||||
if (FV8Utils::IsReleasedPtr(Object))
|
||||
{
|
||||
FV8Utils::ThrowException(Isolate, "passing a invalid object");
|
||||
return;
|
||||
}
|
||||
PropertyClass = Cast<UClass>(Object);
|
||||
}
|
||||
|
||||
UClass* MetaClass = nullptr;
|
||||
if (UObject* Object = FV8Utils::GetUObject(Info.Holder(), 2))
|
||||
{
|
||||
if (FV8Utils::IsReleasedPtr(Object))
|
||||
{
|
||||
FV8Utils::ThrowException(Isolate, "passing a invalid object");
|
||||
return;
|
||||
}
|
||||
MetaClass = Cast<UClass>(Object);
|
||||
}
|
||||
|
||||
if (PropertyClass && !Obj->GetClass()->IsChildOf(PropertyClass))
|
||||
{
|
||||
// FV8Utils::ThrowException(Isolate, "invalid type");
|
||||
return;
|
||||
}
|
||||
if (MetaClass)
|
||||
{
|
||||
auto Class = Cast<UClass>(Obj);
|
||||
if (!Class)
|
||||
{
|
||||
// FV8Utils::ThrowException(Isolate, "not a class");
|
||||
return;
|
||||
}
|
||||
if (!Class->IsChildOf(MetaClass))
|
||||
{
|
||||
// FV8Utils::ThrowException(Isolate, "not a expect class");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Info.GetReturnValue().Set(FV8Utils::IsolateData<IObjectMapper>(Isolate)->FindOrAdd(Isolate, Context, Obj->GetClass(), Obj));
|
||||
}
|
||||
}
|
||||
|
||||
void FSoftObjectWrapper::LoadSynchronous(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
GenericObjectGet(Info, [](FSoftObjectPtr* Ptr) { return Ptr->LoadSynchronous(); });
|
||||
}
|
||||
|
||||
void FSoftObjectWrapper::Get(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
GenericObjectGet(Info, [](FSoftObjectPtr* Ptr) { return Ptr->Get(); });
|
||||
}
|
||||
} // namespace PUERTS_NAMESPACE
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
|
||||
#include "NamespaceDef.h"
|
||||
|
||||
PRAGMA_DISABLE_UNDEFINED_IDENTIFIER_WARNINGS
|
||||
#pragma warning(push, 0)
|
||||
#include "libplatform/libplatform.h"
|
||||
#include "v8.h"
|
||||
#pragma warning(pop)
|
||||
PRAGMA_ENABLE_UNDEFINED_IDENTIFIER_WARNINGS
|
||||
|
||||
namespace PUERTS_NAMESPACE
|
||||
{
|
||||
class FSoftObjectWrapper
|
||||
{
|
||||
public:
|
||||
static v8::Local<v8::FunctionTemplate> ToFunctionTemplate(v8::Isolate* Isolate);
|
||||
|
||||
private:
|
||||
static void LoadSynchronous(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
|
||||
static void Get(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
};
|
||||
} // namespace PUERTS_NAMESPACE
|
||||
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
#if WITH_EDITOR
|
||||
#include "SourceFileWatcher.h"
|
||||
#include "DirectoryWatcherModule.h"
|
||||
#include "Modules/ModuleManager.h"
|
||||
#include "JSLogger.h"
|
||||
#include "Misc/ScopeLock.h"
|
||||
|
||||
namespace PUERTS_NAMESPACE
|
||||
{
|
||||
FSourceFileWatcher::FSourceFileWatcher(std::function<void(const FString&)> InOnWatchedFileChanged)
|
||||
: OnWatchedFileChanged(InOnWatchedFileChanged)
|
||||
{
|
||||
}
|
||||
|
||||
void FSourceFileWatcher::OnSourceLoaded(const FString& InPath)
|
||||
{
|
||||
FString Dir = FPaths::GetPath(InPath);
|
||||
FString FileName = FPaths::GetCleanFilename(InPath);
|
||||
|
||||
FScopeLock ScopeLock(&SourceFileWatcherCritical);
|
||||
if (!WatchedDirs.Contains(Dir))
|
||||
{
|
||||
FDirectoryWatcherModule& DirectoryWatcherModule =
|
||||
FModuleManager::Get().LoadModuleChecked<FDirectoryWatcherModule>(TEXT("DirectoryWatcher"));
|
||||
IDirectoryWatcher* DirectoryWatcher = DirectoryWatcherModule.Get();
|
||||
FDelegateHandle DelegateHandle;
|
||||
DirectoryWatcher->RegisterDirectoryChangedCallback_Handle(Dir,
|
||||
IDirectoryWatcher::FDirectoryChanged::CreateRaw(this, &FSourceFileWatcher::OnDirectoryChanged), DelegateHandle,
|
||||
IDirectoryWatcher::IgnoreChangesInSubtree);
|
||||
WatchedDirs.Emplace(Dir, DelegateHandle);
|
||||
UE_LOG(Puerts, Log, TEXT("add watched dir: %s"), *Dir);
|
||||
}
|
||||
if (!WatchedFiles.Contains(Dir))
|
||||
{
|
||||
WatchedFiles.Emplace(Dir, TMap<FString, FMD5Hash>());
|
||||
}
|
||||
if (!WatchedFiles[Dir].Contains(FileName))
|
||||
{
|
||||
UE_LOG(Puerts, Log, TEXT("add watched file: %s"), *InPath);
|
||||
FMD5Hash Hash = FMD5Hash::HashFile(*InPath);
|
||||
WatchedFiles[Dir].Add(FileName, Hash);
|
||||
}
|
||||
}
|
||||
|
||||
void FSourceFileWatcher::OnDirectoryChanged(const TArray<FFileChangeData>& FileChanges)
|
||||
{
|
||||
FScopeLock ScopeLock(&SourceFileWatcherCritical);
|
||||
if (!OnWatchedFileChanged)
|
||||
return;
|
||||
for (auto Change : FileChanges)
|
||||
{
|
||||
if (Change.Action == FFileChangeData::FCA_Modified && Change.Filename.EndsWith(TEXT(".js")))
|
||||
{
|
||||
FPaths::NormalizeFilename(Change.Filename);
|
||||
Change.Filename = FPaths::ConvertRelativePathToFull(Change.Filename);
|
||||
FString Dir = FPaths::GetPath(Change.Filename);
|
||||
FString FileName = FPaths::GetCleanFilename(Change.Filename);
|
||||
FString Splitter = TEXT("/");
|
||||
if (!WatchedFiles.Contains(Dir))
|
||||
{
|
||||
Dir = Dir.Replace(TEXT("/"), TEXT("\\"));
|
||||
Splitter = TEXT("\\");
|
||||
}
|
||||
if (WatchedFiles.Contains(Dir))
|
||||
{
|
||||
if (WatchedFiles[Dir].Contains(FileName))
|
||||
{
|
||||
FString NotifyPath = Dir + Splitter + FileName;
|
||||
FMD5Hash Hash = FMD5Hash::HashFile(*NotifyPath);
|
||||
if (WatchedFiles[Dir][FileName] != Hash)
|
||||
{
|
||||
OnWatchedFileChanged(NotifyPath);
|
||||
WatchedFiles[Dir][FileName] = Hash;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
UE_LOG(Puerts, Error, TEXT("callback with unwatched dir: %s"), *Dir);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FSourceFileWatcher::~FSourceFileWatcher()
|
||||
{
|
||||
FDirectoryWatcherModule& DirectoryWatcherModule =
|
||||
FModuleManager::Get().LoadModuleChecked<FDirectoryWatcherModule>(TEXT("DirectoryWatcher"));
|
||||
IDirectoryWatcher* DirectoryWatcher = DirectoryWatcherModule.Get();
|
||||
|
||||
FScopeLock ScopeLock(&SourceFileWatcherCritical);
|
||||
for (auto KV : WatchedDirs)
|
||||
{
|
||||
DirectoryWatcher->UnregisterDirectoryChangedCallback_Handle(KV.Key, KV.Value);
|
||||
}
|
||||
}
|
||||
} // namespace PUERTS_NAMESPACE
|
||||
#endif
|
||||
@@ -0,0 +1,730 @@
|
||||
/*
|
||||
* 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 "StructWrapper.h"
|
||||
#include "V8Utils.h"
|
||||
#include "ObjectMapper.h"
|
||||
#include "PathEscape.h"
|
||||
|
||||
namespace PUERTS_NAMESPACE
|
||||
{
|
||||
void FStructWrapper::AddExtensionMethods(const std::vector<UFunction*>& InExtensionMethods)
|
||||
{
|
||||
ExtensionMethods.insert(ExtensionMethods.end(), InExtensionMethods.begin(), InExtensionMethods.end());
|
||||
}
|
||||
|
||||
std::shared_ptr<FPropertyTranslator> FStructWrapper::GetPropertyTranslator(PropertyMacro* InProperty)
|
||||
{
|
||||
auto Iter = PropertiesMap.Find(InProperty->GetFName());
|
||||
if (!Iter)
|
||||
{
|
||||
std::shared_ptr<FPropertyTranslator> PropertyTranslator = FPropertyTranslator::Create(InProperty);
|
||||
if (PropertyTranslator)
|
||||
{
|
||||
PropertiesMap.Add(InProperty->GetFName(), PropertyTranslator);
|
||||
Properties.push_back(PropertyTranslator);
|
||||
}
|
||||
return PropertyTranslator;
|
||||
}
|
||||
FPropertyTranslator::CreateOn(InProperty, Iter->get());
|
||||
return *Iter;
|
||||
}
|
||||
|
||||
std::shared_ptr<FFunctionTranslator> FStructWrapper::GetMethodTranslator(UFunction* InFunction, bool IsExtension)
|
||||
{
|
||||
auto Iter = MethodsMap.Find(InFunction->GetFName());
|
||||
if (!Iter)
|
||||
{
|
||||
std::shared_ptr<FFunctionTranslator> FunctionTranslator;
|
||||
if (IsExtension)
|
||||
{
|
||||
FunctionTranslator = std::make_shared<FExtensionMethodTranslator>(InFunction);
|
||||
}
|
||||
else
|
||||
{
|
||||
FunctionTranslator = std::make_shared<FFunctionTranslator>(InFunction, false);
|
||||
}
|
||||
MethodsMap.Add(InFunction->GetFName(), FunctionTranslator);
|
||||
return FunctionTranslator;
|
||||
}
|
||||
Iter->get()->Init(InFunction, false);
|
||||
return *Iter;
|
||||
}
|
||||
|
||||
std::shared_ptr<FFunctionTranslator> FStructWrapper::GetFunctionTranslator(UFunction* InFunction)
|
||||
{
|
||||
auto Iter = FunctionsMap.Find(InFunction->GetFName());
|
||||
if (!Iter)
|
||||
{
|
||||
auto FunctionTranslator = std::make_shared<FFunctionTranslator>(InFunction, false);
|
||||
FunctionsMap.Add(InFunction->GetFName(), FunctionTranslator);
|
||||
return FunctionTranslator;
|
||||
}
|
||||
Iter->get()->Init(InFunction, false);
|
||||
return *Iter;
|
||||
}
|
||||
|
||||
void FStructWrapper::RefreshMethod(UFunction* InFunction)
|
||||
{
|
||||
if (!InFunction->HasAnyFunctionFlags(FUNC_Static))
|
||||
{
|
||||
GetMethodTranslator(InFunction, false);
|
||||
}
|
||||
}
|
||||
|
||||
MSVC_PRAGMA(warning(push))
|
||||
MSVC_PRAGMA(warning(disable : 4191))
|
||||
void FStructWrapper::InitTemplateProperties(
|
||||
v8::Isolate* Isolate, UStruct* InStruct, v8::Local<v8::FunctionTemplate> Template, bool IsReuseTemplate)
|
||||
{
|
||||
auto ClassDefinition = FindClassByType(Struct.Get());
|
||||
TSet<FName> AddedProperties;
|
||||
if (ClassDefinition)
|
||||
{
|
||||
JSPropertyInfo* PropertyInfo = ClassDefinition->Properties;
|
||||
while (PropertyInfo && PropertyInfo->Name && PropertyInfo->Getter)
|
||||
{
|
||||
AddedProperties.Add(PropertyInfo->Name);
|
||||
if (!IsReuseTemplate)
|
||||
{
|
||||
v8::PropertyAttribute PropertyAttribute = v8::DontDelete;
|
||||
if (!PropertyInfo->Setter)
|
||||
PropertyAttribute = (v8::PropertyAttribute)(PropertyAttribute | v8::ReadOnly);
|
||||
auto GetterData = PropertyInfo->GetterData
|
||||
? static_cast<v8::Local<v8::Value>>(v8::External::New(Isolate, PropertyInfo->GetterData))
|
||||
: v8::Local<v8::Value>();
|
||||
|
||||
auto SetterData = PropertyInfo->SetterData
|
||||
? static_cast<v8::Local<v8::Value>>(v8::External::New(Isolate, PropertyInfo->SetterData))
|
||||
: v8::Local<v8::Value>();
|
||||
|
||||
Template->PrototypeTemplate()->SetAccessorProperty(FV8Utils::InternalString(Isolate, PropertyInfo->Name),
|
||||
PropertyInfo->Getter
|
||||
? v8::FunctionTemplate::New(Isolate, (v8::FunctionCallback) PropertyInfo->Getter, GetterData)
|
||||
: v8::Local<v8::FunctionTemplate>(),
|
||||
PropertyInfo->Setter
|
||||
? v8::FunctionTemplate::New(Isolate, (v8::FunctionCallback) PropertyInfo->Setter, SetterData)
|
||||
: v8::Local<v8::FunctionTemplate>(),
|
||||
PropertyAttribute);
|
||||
}
|
||||
++PropertyInfo;
|
||||
}
|
||||
|
||||
if (!IsReuseTemplate)
|
||||
{
|
||||
PropertyInfo = ClassDefinition->Variables;
|
||||
while (PropertyInfo && PropertyInfo->Name && PropertyInfo->Getter)
|
||||
{
|
||||
v8::PropertyAttribute PropertyAttribute = v8::DontDelete;
|
||||
if (!PropertyInfo->Setter)
|
||||
PropertyAttribute = (v8::PropertyAttribute)(PropertyAttribute | v8::ReadOnly);
|
||||
auto GetterData = PropertyInfo->GetterData
|
||||
? static_cast<v8::Local<v8::Value>>(v8::External::New(Isolate, PropertyInfo->GetterData))
|
||||
: v8::Local<v8::Value>();
|
||||
|
||||
auto SetterData = PropertyInfo->SetterData
|
||||
? static_cast<v8::Local<v8::Value>>(v8::External::New(Isolate, PropertyInfo->SetterData))
|
||||
: v8::Local<v8::Value>();
|
||||
|
||||
Template->SetAccessorProperty(FV8Utils::InternalString(Isolate, PropertyInfo->Name),
|
||||
PropertyInfo->Getter
|
||||
? v8::FunctionTemplate::New(Isolate, (v8::FunctionCallback) PropertyInfo->Getter, GetterData)
|
||||
: v8::Local<v8::FunctionTemplate>(),
|
||||
PropertyInfo->Setter
|
||||
? v8::FunctionTemplate::New(Isolate, (v8::FunctionCallback) PropertyInfo->Setter, SetterData)
|
||||
: v8::Local<v8::FunctionTemplate>(),
|
||||
PropertyAttribute);
|
||||
++PropertyInfo;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (TFieldIterator<PropertyMacro> PropertyIt(InStruct, EFieldIteratorFlags::ExcludeSuper); PropertyIt; ++PropertyIt)
|
||||
{
|
||||
PropertyMacro* Property = *PropertyIt;
|
||||
if (AddedProperties.Contains(Property->GetFName()))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
auto PropertyTranslator = GetPropertyTranslator(Property);
|
||||
if (PropertyTranslator)
|
||||
{
|
||||
if (!IsReuseTemplate)
|
||||
PropertyTranslator->SetAccessor(Isolate, Template);
|
||||
}
|
||||
else
|
||||
{
|
||||
// UE_LOG(LogTemp, Warning, TEXT("%s:%s not supported"), *Property->GetOwnerStruct()->GetName(), *Property->GetName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
v8::Local<v8::FunctionTemplate> FStructWrapper::ToFunctionTemplate(v8::Isolate* Isolate, v8::FunctionCallback Construtor)
|
||||
{
|
||||
auto ClassDefinition = FindClassByType(Struct.Get());
|
||||
bool IsReuseTemplate = false;
|
||||
#if PUERTS_REUSE_STRUCTWRAPPER_FUNCTIONTEMPLATE
|
||||
IsReuseTemplate = true;
|
||||
if (CachedFunctionTemplate.IsEmpty())
|
||||
{
|
||||
IsReuseTemplate = false;
|
||||
auto Temp = v8::FunctionTemplate::New(Isolate, Construtor, v8::External::New(Isolate, this));
|
||||
Temp->InstanceTemplate()->SetInternalFieldCount(4);
|
||||
CachedFunctionTemplate.Reset(Isolate, Temp);
|
||||
}
|
||||
auto Result = CachedFunctionTemplate.Get(Isolate);
|
||||
#else
|
||||
auto Result = v8::FunctionTemplate::New(
|
||||
Isolate, Construtor, v8::External::New(Isolate, this)); // 和class的区别就这里传的函数不一样,后续尽量重用
|
||||
Result->InstanceTemplate()->SetInternalFieldCount(4);
|
||||
#endif
|
||||
|
||||
TSet<FName> AddedMethods;
|
||||
TSet<FName> AddedFunctions;
|
||||
|
||||
if (ClassDefinition)
|
||||
{
|
||||
ExternalInitialize = (V8InitializeFuncType) ClassDefinition->Initialize;
|
||||
ExternalFinalize = ClassDefinition->Finalize;
|
||||
JSFunctionInfo* FunctionInfo = ClassDefinition->Methods;
|
||||
while (FunctionInfo && FunctionInfo->Name && FunctionInfo->Callback)
|
||||
{
|
||||
AddedMethods.Add(FunctionInfo->Name);
|
||||
if (!IsReuseTemplate)
|
||||
{
|
||||
#ifndef WITH_QUICKJS
|
||||
auto FastCallInfo = FunctionInfo->ReflectionInfo ? FunctionInfo->ReflectionInfo->FastCallInfo() : nullptr;
|
||||
if (FastCallInfo)
|
||||
{
|
||||
Result->PrototypeTemplate()->Set(FV8Utils::InternalString(Isolate, FunctionInfo->Name),
|
||||
v8::FunctionTemplate::New(Isolate, (v8::FunctionCallback) FunctionInfo->Callback,
|
||||
FunctionInfo->Data ? static_cast<v8::Local<v8::Value>>(v8::External::New(Isolate, FunctionInfo->Data))
|
||||
: v8::Local<v8::Value>(),
|
||||
v8::Local<v8::Signature>(), 0, v8::ConstructorBehavior::kThrow, v8::SideEffectType::kHasSideEffect,
|
||||
FastCallInfo));
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
Result->PrototypeTemplate()->Set(FV8Utils::InternalString(Isolate, FunctionInfo->Name),
|
||||
v8::FunctionTemplate::New(Isolate, (v8::FunctionCallback) FunctionInfo->Callback,
|
||||
FunctionInfo->Data ? static_cast<v8::Local<v8::Value>>(v8::External::New(Isolate, FunctionInfo->Data))
|
||||
: v8::Local<v8::Value>()));
|
||||
}
|
||||
}
|
||||
++FunctionInfo;
|
||||
}
|
||||
FunctionInfo = ClassDefinition->Functions;
|
||||
while (FunctionInfo && FunctionInfo->Name && FunctionInfo->Callback)
|
||||
{
|
||||
AddedFunctions.Add(FunctionInfo->Name);
|
||||
if (!IsReuseTemplate)
|
||||
{
|
||||
#ifndef WITH_QUICKJS
|
||||
auto FastCallInfo = FunctionInfo->ReflectionInfo ? FunctionInfo->ReflectionInfo->FastCallInfo() : nullptr;
|
||||
if (FastCallInfo)
|
||||
{
|
||||
Result->Set(FV8Utils::InternalString(Isolate, FunctionInfo->Name),
|
||||
v8::FunctionTemplate::New(Isolate, (v8::FunctionCallback) FunctionInfo->Callback,
|
||||
FunctionInfo->Data ? static_cast<v8::Local<v8::Value>>(v8::External::New(Isolate, FunctionInfo->Data))
|
||||
: v8::Local<v8::Value>(),
|
||||
v8::Local<v8::Signature>(), 0, v8::ConstructorBehavior::kThrow, v8::SideEffectType::kHasSideEffect,
|
||||
FastCallInfo));
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
Result->Set(FV8Utils::InternalString(Isolate, FunctionInfo->Name),
|
||||
v8::FunctionTemplate::New(Isolate, (v8::FunctionCallback) FunctionInfo->Callback,
|
||||
FunctionInfo->Data ? static_cast<v8::Local<v8::Value>>(v8::External::New(Isolate, FunctionInfo->Data))
|
||||
: v8::Local<v8::Value>()));
|
||||
}
|
||||
}
|
||||
++FunctionInfo;
|
||||
}
|
||||
}
|
||||
|
||||
InitTemplateProperties(Isolate, Struct.Get(), Result, IsReuseTemplate);
|
||||
|
||||
if (const auto Class = Cast<UClass>(Struct.Get()))
|
||||
{
|
||||
for (TFieldIterator<UFunction> FuncIt(Class, EFieldIteratorFlags::ExcludeSuper); FuncIt; ++FuncIt)
|
||||
{
|
||||
UFunction* Function = *FuncIt;
|
||||
|
||||
if ((Function->HasAnyFunctionFlags(FUNC_Static) && AddedFunctions.Contains(Function->GetFName())) ||
|
||||
(!Function->HasAnyFunctionFlags(FUNC_Static) && AddedMethods.Contains(Function->GetFName())))
|
||||
{
|
||||
// UE_LOG(LogTemp, Warning, TEXT("%s added"), *Function->GetName());
|
||||
continue;
|
||||
}
|
||||
|
||||
FString FuncName = Function->GetName();
|
||||
auto Key = FV8Utils::InternalString(Isolate, FuncName);
|
||||
#ifdef PUERTS_WITH_EDITOR_SUFFIX
|
||||
// 这里同时绑定带Suffix和不带Suffix的后缀是为了兼容现有的一些js写的代码(PuertsEditor)
|
||||
v8::Local<v8::String> AdditionalKey{};
|
||||
if (puerts::IsEditorOnlyUFunction(Function))
|
||||
{
|
||||
FString SuffixFuncName = FuncName + EditorOnlyPropertySuffix.GetData();
|
||||
AdditionalKey = FV8Utils::InternalString(Isolate, SuffixFuncName);
|
||||
}
|
||||
#endif
|
||||
// 这里同时绑定带Suffix和不带Suffix的后缀是为了兼容现有的一些js写的代码(PuertsEditor)
|
||||
|
||||
if (Function->HasAnyFunctionFlags(FUNC_Static))
|
||||
{
|
||||
auto FunctionTranslator = GetFunctionTranslator(Function);
|
||||
AddedFunctions.Add(Function->GetFName());
|
||||
if (!IsReuseTemplate)
|
||||
{
|
||||
Result->Set(Key, FunctionTranslator->ToFunctionTemplate(Isolate));
|
||||
#ifdef PUERTS_WITH_EDITOR_SUFFIX
|
||||
if (!AdditionalKey.IsEmpty())
|
||||
{
|
||||
Result->Set(AdditionalKey, FunctionTranslator->ToFunctionTemplate(Isolate));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
auto FunctionTranslator = GetMethodTranslator(Function, false);
|
||||
AddedMethods.Add(Function->GetFName());
|
||||
if (!IsReuseTemplate)
|
||||
{
|
||||
Result->PrototypeTemplate()->Set(Key, FunctionTranslator->ToFunctionTemplate(Isolate));
|
||||
#ifdef PUERTS_WITH_EDITOR_SUFFIX
|
||||
if (!AdditionalKey.IsEmpty())
|
||||
{
|
||||
Result->PrototypeTemplate()->Set(AdditionalKey, FunctionTranslator->ToFunctionTemplate(Isolate));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const FImplementedInterface& Interface : Class->Interfaces)
|
||||
{
|
||||
if (Interface.Class)
|
||||
{
|
||||
for (TFieldIterator<UFunction> ItfFuncIt(Interface.Class, EFieldIteratorFlags::ExcludeSuper); ItfFuncIt;
|
||||
++ItfFuncIt)
|
||||
{
|
||||
UFunction* ItfFunction = *ItfFuncIt;
|
||||
if (!ItfFunction->HasAnyFunctionFlags(FUNC_Static) && !AddedMethods.Contains(ItfFunction->GetFName()))
|
||||
{
|
||||
auto ItfFunctionTranslator = GetMethodTranslator(ItfFunction, false);
|
||||
AddedMethods.Add(ItfFunction->GetFName());
|
||||
if (!IsReuseTemplate)
|
||||
Result->PrototypeTemplate()->Set(FV8Utils::InternalString(Isolate, ItfFunction->GetName()),
|
||||
ItfFunctionTranslator->ToFunctionTemplate(Isolate));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!IsReuseTemplate)
|
||||
{
|
||||
Result->Set(FV8Utils::InternalString(Isolate, "Find"),
|
||||
v8::FunctionTemplate::New(Isolate, Find, v8::External::New(Isolate, this)));
|
||||
Result->Set(FV8Utils::InternalString(Isolate, "Load"),
|
||||
v8::FunctionTemplate::New(Isolate, Load, v8::External::New(Isolate, this)));
|
||||
}
|
||||
}
|
||||
|
||||
for (auto Iter = ExtensionMethods.begin(); Iter != ExtensionMethods.end(); ++Iter)
|
||||
{
|
||||
UFunction* Function = *Iter;
|
||||
|
||||
if (AddedMethods.Contains(Function->GetFName()))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
auto FunctionTranslator = GetMethodTranslator(Function, true);
|
||||
|
||||
AddedMethods.Add(Function->GetFName());
|
||||
if (!IsReuseTemplate)
|
||||
{
|
||||
auto Key = FV8Utils::InternalString(Isolate, Function->GetName());
|
||||
Result->PrototypeTemplate()->Set(Key, FunctionTranslator->ToFunctionTemplate(Isolate));
|
||||
}
|
||||
}
|
||||
|
||||
if (!IsReuseTemplate)
|
||||
Result->Set(FV8Utils::InternalString(Isolate, "StaticClass"),
|
||||
v8::FunctionTemplate::New(Isolate, StaticClass, v8::External::New(Isolate, this)));
|
||||
|
||||
if (!Struct->IsA<UClass>() && !IsReuseTemplate)
|
||||
{
|
||||
Result->Set(FV8Utils::InternalString(Isolate, "StaticStruct"),
|
||||
v8::FunctionTemplate::New(Isolate, StaticClass, v8::External::New(Isolate, this)));
|
||||
}
|
||||
|
||||
#ifndef WITH_QUICKJS
|
||||
if (!IsReuseTemplate)
|
||||
Result->InstanceTemplate()->SetHandler(v8::NamedPropertyHandlerConfiguration(
|
||||
[](v8::Local<v8::Name> Property, const v8::PropertyCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
if (Property->IsSymbol())
|
||||
return;
|
||||
auto InnerIsolate = Info.GetIsolate();
|
||||
auto Context = InnerIsolate->GetCurrentContext();
|
||||
auto This = Info.This();
|
||||
FName RequiredFName(*FV8Utils::ToFString(Info.GetIsolate(), Property));
|
||||
auto FixedPropertyName = FV8Utils::ToV8String(InnerIsolate, RequiredFName);
|
||||
if (This->GetPrototype()->IsObject())
|
||||
{
|
||||
auto Proto = This->GetPrototype().As<v8::Object>();
|
||||
if (Proto->Has(Context, FixedPropertyName).FromMaybe(false))
|
||||
{
|
||||
Info.GetReturnValue().Set(This->Get(Context, FixedPropertyName).ToLocalChecked());
|
||||
auto DescriptorVal = Proto->GetOwnPropertyDescriptor(Context, FixedPropertyName).ToLocalChecked();
|
||||
while (!DescriptorVal->IsObject())
|
||||
{
|
||||
auto Parent = Proto->GetPrototype();
|
||||
if (!Parent->IsObject())
|
||||
break;
|
||||
Proto = Parent.As<v8::Object>();
|
||||
DescriptorVal = Proto->GetOwnPropertyDescriptor(Context, FixedPropertyName).ToLocalChecked();
|
||||
}
|
||||
if (DescriptorVal->IsObject())
|
||||
{
|
||||
auto Descriptor = DescriptorVal.As<v8::Object>();
|
||||
auto Getter = Descriptor->Get(Context, FV8Utils::ToV8String(InnerIsolate, "get")).ToLocalChecked();
|
||||
if (!Getter->IsFunction())
|
||||
{
|
||||
auto Value = Descriptor->Get(Context, FV8Utils::ToV8String(InnerIsolate, "value")).ToLocalChecked();
|
||||
(void) (Proto->Set(Context, Property, Value));
|
||||
}
|
||||
else
|
||||
{
|
||||
Proto->SetAccessorProperty(Property, Getter.As<v8::Function>(),
|
||||
Descriptor->Get(Context, FV8Utils::ToV8String(InnerIsolate, "set"))
|
||||
.ToLocalChecked()
|
||||
.As<v8::Function>());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
[](v8::Local<v8::Name> Property, v8::Local<v8::Value> Value, const v8::PropertyCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
if (Property->IsSymbol())
|
||||
return;
|
||||
auto InnerIsolate = Info.GetIsolate();
|
||||
auto Context = InnerIsolate->GetCurrentContext();
|
||||
auto This = Info.This();
|
||||
FName RequiredFName(*FV8Utils::ToFString(Info.GetIsolate(), Property));
|
||||
auto FixedPropertyName = FV8Utils::ToV8String(InnerIsolate, RequiredFName);
|
||||
if (This->GetPrototype()->IsObject())
|
||||
{
|
||||
auto Proto = This->GetPrototype().As<v8::Object>();
|
||||
if (Proto->Has(Context, FixedPropertyName).FromMaybe(false))
|
||||
{
|
||||
auto _UnUsed = This->Set(Context, FixedPropertyName, Value);
|
||||
Info.GetReturnValue().Set(Value);
|
||||
auto DescriptorVal = Proto->GetOwnPropertyDescriptor(Context, FixedPropertyName).ToLocalChecked();
|
||||
while (!DescriptorVal->IsObject())
|
||||
{
|
||||
auto Parent = Proto->GetPrototype();
|
||||
if (!Parent->IsObject())
|
||||
break;
|
||||
Proto = Parent.As<v8::Object>();
|
||||
DescriptorVal = Proto->GetOwnPropertyDescriptor(Context, FixedPropertyName).ToLocalChecked();
|
||||
}
|
||||
if (DescriptorVal->IsObject())
|
||||
{
|
||||
auto Descriptor = DescriptorVal.As<v8::Object>();
|
||||
// set first, mush set accessor of object
|
||||
Proto->SetAccessorProperty(Property,
|
||||
Descriptor->Get(Context, FV8Utils::ToV8String(InnerIsolate, "get"))
|
||||
.ToLocalChecked()
|
||||
.As<v8::Function>(),
|
||||
Descriptor->Get(Context, FV8Utils::ToV8String(InnerIsolate, "set"))
|
||||
.ToLocalChecked()
|
||||
.As<v8::Function>());
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
nullptr, nullptr, nullptr, v8::Local<v8::Value>(), v8::PropertyHandlerFlags::kNonMasking));
|
||||
#endif
|
||||
|
||||
return Result;
|
||||
}
|
||||
MSVC_PRAGMA(warning(pop))
|
||||
|
||||
void FStructWrapper::StaticClass(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Isolate::Scope IsolateScope(Isolate);
|
||||
v8::HandleScope HandleScope(Isolate);
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
v8::Context::Scope ContextScope(Context);
|
||||
|
||||
FStructWrapper* This = reinterpret_cast<FStructWrapper*>((v8::Local<v8::External>::Cast(Info.Data()))->Value());
|
||||
|
||||
if (!This->Struct.IsValid())
|
||||
{
|
||||
FV8Utils::ThrowException(Isolate, "Associated UStruct had been GC");
|
||||
return;
|
||||
}
|
||||
|
||||
auto Result =
|
||||
FV8Utils::IsolateData<IObjectMapper>(Isolate)->FindOrAdd(Isolate, Context, This->Struct->GetClass(), This->Struct.Get());
|
||||
Info.GetReturnValue().Set(Result);
|
||||
}
|
||||
|
||||
void FStructWrapper::Find(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Isolate::Scope IsolateScope(Isolate);
|
||||
v8::HandleScope HandleScope(Isolate);
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
v8::Context::Scope ContextScope(Context);
|
||||
|
||||
FStructWrapper* This = reinterpret_cast<FStructWrapper*>((v8::Local<v8::External>::Cast(Info.Data()))->Value());
|
||||
|
||||
if (!This->Struct.IsValid())
|
||||
{
|
||||
FV8Utils::ThrowException(Isolate, "Associated UStruct had been GC");
|
||||
return;
|
||||
}
|
||||
|
||||
UClass* Class = Cast<UClass>(This->Struct);
|
||||
|
||||
if (Class && Info.Length() >= 1 && Info[0]->IsString())
|
||||
{
|
||||
UObject* Object = nullptr;
|
||||
if (Info.Length() > 1)
|
||||
{
|
||||
UObject* Outer = FV8Utils::GetUObject(Context, Info[1]);
|
||||
Object = StaticFindObject(Class, Outer, *FV8Utils::ToFString(Isolate, Info[0]), false);
|
||||
}
|
||||
else
|
||||
{
|
||||
#if (ENGINE_MAJOR_VERSION == 5 && ENGINE_MINOR_VERSION >= 1) || ENGINE_MAJOR_VERSION > 5
|
||||
Object = StaticFindFirstObject(Class, *FV8Utils::ToFString(Isolate, Info[0]));
|
||||
#else
|
||||
Object = StaticFindObject(Class, ANY_PACKAGE, *FV8Utils::ToFString(Isolate, Info[0]), false);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (Object)
|
||||
{
|
||||
auto Result = FV8Utils::IsolateData<IObjectMapper>(Isolate)->FindOrAdd(Isolate, Context, Object->GetClass(), Object);
|
||||
Info.GetReturnValue().Set(Result);
|
||||
}
|
||||
else
|
||||
{
|
||||
Info.GetReturnValue().Set(v8::Undefined(Isolate));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FV8Utils::ThrowException(Isolate, "invalid argument");
|
||||
}
|
||||
}
|
||||
|
||||
void FStructWrapper::Load(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Isolate::Scope IsolateScope(Isolate);
|
||||
v8::HandleScope HandleScope(Isolate);
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
v8::Context::Scope ContextScope(Context);
|
||||
|
||||
FStructWrapper* This = reinterpret_cast<FStructWrapper*>((v8::Local<v8::External>::Cast(Info.Data()))->Value());
|
||||
|
||||
if (!This->Struct.IsValid())
|
||||
{
|
||||
FV8Utils::ThrowException(Isolate, "Associated UStruct had been GC");
|
||||
return;
|
||||
}
|
||||
|
||||
UClass* Class = Cast<UClass>(This->Struct);
|
||||
|
||||
if (Class && Info.Length() > 0 && Info[0]->IsString())
|
||||
{
|
||||
bool UnEscape = false;
|
||||
if (Info.Length() > 1)
|
||||
{
|
||||
UnEscape = Info[1]->BooleanValue(Isolate);
|
||||
}
|
||||
auto Path = FV8Utils::ToFString(Isolate, Info[0]);
|
||||
auto Object =
|
||||
StaticLoadObject(Class, nullptr, UnEscape ? *TypeScriptVariableNameToFilename(Path) : *Path, nullptr, LOAD_NoWarn);
|
||||
if (Object)
|
||||
{
|
||||
auto Result = FV8Utils::IsolateData<IObjectMapper>(Isolate)->FindOrAdd(Isolate, Context, Object->GetClass(), Object);
|
||||
Info.GetReturnValue().Set(Result);
|
||||
}
|
||||
else
|
||||
{
|
||||
Info.GetReturnValue().Set(v8::Undefined(Isolate));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FV8Utils::ThrowException(Isolate, "invalid argument");
|
||||
}
|
||||
}
|
||||
|
||||
void FScriptStructWrapper::New(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Isolate::Scope IsolateScope(Isolate);
|
||||
v8::HandleScope HandleScope(Isolate);
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
v8::Context::Scope ContextScope(Context);
|
||||
|
||||
FScriptStructWrapper* This = reinterpret_cast<FScriptStructWrapper*>((v8::Local<v8::External>::Cast(Info.Data()))->Value());
|
||||
if (!This->Struct.IsValid())
|
||||
{
|
||||
FV8Utils::ThrowException(Isolate, "Associated UStruct had been GC");
|
||||
return;
|
||||
}
|
||||
This->New(Isolate, Context, Info);
|
||||
}
|
||||
|
||||
void FScriptStructWrapper::New(
|
||||
v8::Isolate* Isolate, v8::Local<v8::Context>& Context, const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
if (Info.IsConstructCall())
|
||||
{
|
||||
auto Self = Info.This();
|
||||
void* Memory = nullptr;
|
||||
|
||||
{
|
||||
if (ExternalInitialize)
|
||||
{
|
||||
Memory = ExternalInitialize(Info);
|
||||
if (!Memory) // do not bind nullptr
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Memory = Alloc(static_cast<UScriptStruct*>(Struct.Get()));
|
||||
const int Count = Info.Length() < Properties.size() ? Info.Length() : Properties.size();
|
||||
for (int i = 0; i < Count; ++i)
|
||||
{
|
||||
Properties[i]->JsToUEInContainer(Isolate, Context, Info[i], Memory, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
FV8Utils::IsolateData<IObjectMapper>(Isolate)->BindStruct(this, Memory, Self, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
FV8Utils::ThrowException(Isolate, "only call as Construct is supported!");
|
||||
}
|
||||
}
|
||||
|
||||
void* FScriptStructWrapper::Alloc(UScriptStruct* InScriptStruct)
|
||||
{
|
||||
void* ScriptStructMemory = new char[InScriptStruct->GetStructureSize()];
|
||||
InScriptStruct->InitializeStruct(ScriptStructMemory);
|
||||
return ScriptStructMemory;
|
||||
}
|
||||
|
||||
void FScriptStructWrapper::Free(TWeakObjectPtr<UStruct> InStruct, pesapi_finalize InExternalFinalize, void* Ptr)
|
||||
{
|
||||
if (InExternalFinalize)
|
||||
{
|
||||
InExternalFinalize(Ptr, nullptr, nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (InStruct.IsValid())
|
||||
InStruct->DestroyStruct(Ptr);
|
||||
delete[] static_cast<char*>(Ptr);
|
||||
}
|
||||
}
|
||||
|
||||
void FScriptStructWrapper::OnGarbageCollectedWithFree(const v8::WeakCallbackInfo<FScriptStructWrapper>& Data)
|
||||
{
|
||||
FScriptStructWrapper* ScriptStructWrapper = Data.GetParameter();
|
||||
void* ScriptStructMemory = DataTransfer::MakeAddressWithHighPartOfTwo(Data.GetInternalField(0), Data.GetInternalField(1));
|
||||
FV8Utils::IsolateData<IObjectMapper>(Data.GetIsolate())->UnBindStruct(ScriptStructWrapper, ScriptStructMemory);
|
||||
Free(ScriptStructWrapper->Struct, ScriptStructWrapper->ExternalFinalize, ScriptStructMemory);
|
||||
}
|
||||
|
||||
void FScriptStructWrapper::OnGarbageCollected(const v8::WeakCallbackInfo<FScriptStructWrapper>& Data)
|
||||
{
|
||||
void* ScriptStructMemory = DataTransfer::MakeAddressWithHighPartOfTwo(Data.GetInternalField(0), Data.GetInternalField(1));
|
||||
FV8Utils::IsolateData<IObjectMapper>(Data.GetIsolate())->UnBindStruct(Data.GetParameter(), ScriptStructMemory);
|
||||
}
|
||||
|
||||
void FClassWrapper::OnGarbageCollected(const v8::WeakCallbackInfo<UClass>& Data)
|
||||
{
|
||||
FV8Utils::IsolateData<IObjectMapper>(Data.GetIsolate())
|
||||
->UnBind(Data.GetParameter(), reinterpret_cast<UObject*>(DataTransfer::MakeAddressWithHighPartOfTwo(
|
||||
Data.GetInternalField(0), Data.GetInternalField(1))));
|
||||
}
|
||||
|
||||
void FClassWrapper::New(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::Isolate* Isolate = Info.GetIsolate();
|
||||
v8::Isolate::Scope IsolateScope(Isolate);
|
||||
v8::HandleScope HandleScope(Isolate);
|
||||
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
|
||||
v8::Context::Scope ContextScope(Context);
|
||||
|
||||
FClassWrapper* This = reinterpret_cast<FClassWrapper*>((v8::Local<v8::External>::Cast(Info.Data()))->Value());
|
||||
if (!This->Struct.IsValid())
|
||||
{
|
||||
FV8Utils::ThrowException(Isolate, "Associated UStruct had been GC");
|
||||
return;
|
||||
}
|
||||
This->New(Isolate, Context, Info);
|
||||
}
|
||||
|
||||
void FClassWrapper::New(v8::Isolate* Isolate, v8::Local<v8::Context>& Context, const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
if (Info.IsConstructCall())
|
||||
{
|
||||
auto Self = Info.This();
|
||||
|
||||
UObject* Object = nullptr;
|
||||
auto Class = static_cast<UClass*>(Struct.Get());
|
||||
|
||||
{
|
||||
UObject* Outer = GetTransientPackage();
|
||||
FName Name = NAME_None;
|
||||
EObjectFlags ObjectFlags = RF_NoFlags;
|
||||
if (Info.Length() > 0)
|
||||
{
|
||||
Outer = FV8Utils::GetUObject(Context, Info[0]);
|
||||
if (FV8Utils::IsReleasedPtr(Outer))
|
||||
{
|
||||
FV8Utils::ThrowException(Isolate, "passing a invalid object");
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (Info.Length() > 1)
|
||||
{
|
||||
Name = FName(*FV8Utils::ToFString(Isolate, Info[1]));
|
||||
}
|
||||
if (Info.Length() > 2)
|
||||
{
|
||||
ObjectFlags = (EObjectFlags) (Info[2]->Int32Value(Context).ToChecked());
|
||||
}
|
||||
Object = NewObject<UObject>(Outer, Class, Name, ObjectFlags);
|
||||
}
|
||||
|
||||
FV8Utils::IsolateData<IObjectMapper>(Isolate)->Bind(this, Object, Self);
|
||||
}
|
||||
else
|
||||
{
|
||||
FV8Utils::ThrowException(Isolate, "only call as Construct is supported!");
|
||||
}
|
||||
}
|
||||
} // namespace PUERTS_NAMESPACE
|
||||
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "CoreUObject.h"
|
||||
#include "PropertyTranslator.h"
|
||||
#include "FunctionTranslator.h"
|
||||
#include "JSClassRegister.h"
|
||||
#include "NamespaceDef.h"
|
||||
|
||||
#define PUERTS_REUSE_STRUCTWRAPPER_FUNCTIONTEMPLATE 1
|
||||
|
||||
namespace PUERTS_NAMESPACE
|
||||
{
|
||||
class FStructWrapper
|
||||
{
|
||||
public:
|
||||
explicit FStructWrapper(UStruct* InStruct) : ExternalInitialize(nullptr), ExternalFinalize(nullptr), Struct(InStruct)
|
||||
{
|
||||
}
|
||||
|
||||
FORCEINLINE void Init(UStruct* InStruct, bool IsReuseTemplate)
|
||||
{
|
||||
Struct = InStruct;
|
||||
if (!IsReuseTemplate)
|
||||
{
|
||||
ExternalInitialize = nullptr;
|
||||
ExternalFinalize = nullptr;
|
||||
Properties.clear();
|
||||
ExtensionMethods.clear();
|
||||
#if PUERTS_REUSE_STRUCTWRAPPER_FUNCTIONTEMPLATE
|
||||
CachedFunctionTemplate.Reset();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void AddExtensionMethods(const std::vector<UFunction*>& InExtensionMethods);
|
||||
|
||||
#if PUERTS_REUSE_STRUCTWRAPPER_FUNCTIONTEMPLATE
|
||||
v8::UniquePersistent<v8::FunctionTemplate> CachedFunctionTemplate;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
std::vector<std::shared_ptr<FPropertyTranslator>> Properties;
|
||||
|
||||
TMap<FName, std::shared_ptr<FPropertyTranslator>> PropertiesMap;
|
||||
|
||||
std::shared_ptr<FPropertyTranslator> GetPropertyTranslator(PropertyMacro* InProperty);
|
||||
|
||||
TMap<FName, std::shared_ptr<FFunctionTranslator>> FunctionsMap;
|
||||
|
||||
TMap<FName, std::shared_ptr<FFunctionTranslator>> MethodsMap;
|
||||
|
||||
std::shared_ptr<FFunctionTranslator> GetFunctionTranslator(UFunction* InFunction);
|
||||
|
||||
std::shared_ptr<FFunctionTranslator> GetMethodTranslator(UFunction* InFunction, bool IsExtension);
|
||||
|
||||
void RefreshMethod(UFunction* InFunction);
|
||||
|
||||
void InitTemplateProperties(
|
||||
v8::Isolate* Isolate, UStruct* InStruct, v8::Local<v8::FunctionTemplate> Template, bool IsReuseTemplate);
|
||||
|
||||
v8::Local<v8::FunctionTemplate> ToFunctionTemplate(v8::Isolate* Isolate, v8::FunctionCallback Construtor);
|
||||
|
||||
std::vector<UFunction*> ExtensionMethods;
|
||||
|
||||
typedef void* (*V8InitializeFuncType)(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
|
||||
V8InitializeFuncType ExternalInitialize;
|
||||
|
||||
pesapi_finalize ExternalFinalize;
|
||||
|
||||
TWeakObjectPtr<UStruct> Struct;
|
||||
|
||||
#if PUERTS_KEEP_UOBJECT_REFERENCE
|
||||
bool IsNativeTakeJsRef = false;
|
||||
#else
|
||||
bool IsNativeTakeJsRef = true;
|
||||
#endif
|
||||
|
||||
bool IsTypeScriptGeneratedClass = false;
|
||||
|
||||
static void StaticClass(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
|
||||
static void Find(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
|
||||
static void Load(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
|
||||
friend class FJsEnvImpl;
|
||||
};
|
||||
|
||||
class FScriptStructWrapper : public FStructWrapper
|
||||
{
|
||||
public:
|
||||
explicit FScriptStructWrapper(UScriptStruct* InScriptStruct) : FStructWrapper(InScriptStruct)
|
||||
{
|
||||
}
|
||||
|
||||
static void OnGarbageCollectedWithFree(const v8::WeakCallbackInfo<FScriptStructWrapper>& Data);
|
||||
|
||||
static void OnGarbageCollected(const v8::WeakCallbackInfo<FScriptStructWrapper>& Data);
|
||||
|
||||
static void* Alloc(UScriptStruct* InScriptStruct);
|
||||
|
||||
static void Free(TWeakObjectPtr<UStruct> InStruct, pesapi_finalize InExternalFinalize, void* Ptr);
|
||||
|
||||
void Free(void* Ptr)
|
||||
{
|
||||
Free(Struct, ExternalFinalize, Ptr);
|
||||
}
|
||||
|
||||
static void New(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
|
||||
void New(v8::Isolate* Isolate, v8::Local<v8::Context>& Context, const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
};
|
||||
|
||||
class FClassWrapper : public FStructWrapper
|
||||
{
|
||||
public:
|
||||
explicit FClassWrapper(UClass* InClass) : FStructWrapper(InClass)
|
||||
{
|
||||
}
|
||||
|
||||
static void OnGarbageCollected(const v8::WeakCallbackInfo<UClass>& Data);
|
||||
|
||||
static void New(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
|
||||
void New(v8::Isolate* Isolate, v8::Local<v8::Context>& Context, const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
};
|
||||
} // namespace PUERTS_NAMESPACE
|
||||
@@ -0,0 +1,11 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#include "TypeScriptBlueprint.h"
|
||||
#include "TypeScriptGeneratedClass.h"
|
||||
|
||||
#if WITH_EDITOR
|
||||
UClass* UTypeScriptBlueprint::GetBlueprintClass() const
|
||||
{
|
||||
return UTypeScriptGeneratedClass::StaticClass();
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,294 @@
|
||||
/*
|
||||
* 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 "TypeScriptGeneratedClass.h"
|
||||
#include "Runtime/Launch/Resources/Version.h"
|
||||
#include "PropertyMacros.h"
|
||||
#include "JSGeneratedFunction.h"
|
||||
#include "JSLogger.h"
|
||||
|
||||
DEFINE_FUNCTION(UTypeScriptGeneratedClass::execCallJS)
|
||||
{
|
||||
UFunction* Func = Stack.CurrentNativeFunction ? Stack.CurrentNativeFunction : Stack.Node;
|
||||
check(Func);
|
||||
// UE_LOG(LogTemp, Warning, TEXT("overrided function called, %s(%p)"), *Func->GetName(), Func);
|
||||
|
||||
UTypeScriptGeneratedClass* Class = Cast<UTypeScriptGeneratedClass>(Func->GetOuter());
|
||||
if (Class)
|
||||
{
|
||||
#if WITH_EDITOR
|
||||
if (Context)
|
||||
{
|
||||
UTypeScriptGeneratedClass* ClassMayNeedReBind = nullptr;
|
||||
auto TempClass = Context->GetClass();
|
||||
|
||||
while (TempClass && (TempClass != Class) && (!ClassMayNeedReBind || !ClassMayNeedReBind->NeedReBind))
|
||||
{
|
||||
ClassMayNeedReBind = Cast<UTypeScriptGeneratedClass>(TempClass);
|
||||
TempClass = TempClass->GetSuperClass();
|
||||
}
|
||||
if (ClassMayNeedReBind)
|
||||
{
|
||||
NotifyRebind(ClassMayNeedReBind);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
auto PinedDynamicInvoker = Class->DynamicInvoker.Pin();
|
||||
if (PinedDynamicInvoker)
|
||||
{
|
||||
PinedDynamicInvoker->InvokeTsMethod(Context, Func, Stack, RESULT_PARAM);
|
||||
}
|
||||
else
|
||||
{
|
||||
UE_LOG(Puerts, Error, TEXT("call %s::%s fail!, DynamicInvoker invalid"), *Class->GetName(), *Func->GetName());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
UE_LOG(Puerts, Error, TEXT("calling a not ts class method %s::%s"), *Func->GetOuter()->GetName(), *Func->GetName());
|
||||
}
|
||||
}
|
||||
|
||||
DEFINE_FUNCTION(UTypeScriptGeneratedClass::execLazyLoadCallJS)
|
||||
{
|
||||
UFunction* Function = Stack.CurrentNativeFunction ? Stack.CurrentNativeFunction : Stack.Node;
|
||||
check(Function);
|
||||
|
||||
auto Class = Cast<UTypeScriptGeneratedClass>(Function->GetOuterUClassUnchecked());
|
||||
#if !WITH_EDITOR
|
||||
auto PinedDynamicInvoker = Class->DynamicInvoker.Pin();
|
||||
if (PinedDynamicInvoker)
|
||||
{
|
||||
PinedDynamicInvoker->NotifyReBind(Class);
|
||||
}
|
||||
#else
|
||||
NotifyRebind(Context ? Context->GetClass() : Class);
|
||||
#endif
|
||||
Class->RestoreNativeFunc();
|
||||
execCallJS(Context, Stack, RESULT_PARAM);
|
||||
}
|
||||
|
||||
#if WITH_EDITOR
|
||||
void UTypeScriptGeneratedClass::NotifyRebind(UClass* Class)
|
||||
{
|
||||
if (Class->ClassConstructor == &UTypeScriptGeneratedClass::StaticConstructor)
|
||||
{
|
||||
while (Class)
|
||||
{
|
||||
if (UTypeScriptGeneratedClass* TsClass = Cast<UTypeScriptGeneratedClass>(Class))
|
||||
{
|
||||
if (TsClass->NeedReBind && TsClass->DynamicInvoker.IsValid())
|
||||
{
|
||||
TsClass->NeedReBind = false;
|
||||
UTypeScriptGeneratedClass* CachedClass = TsClass;
|
||||
Class = Class->GetSuperClass();
|
||||
while (Class)
|
||||
{
|
||||
if (UTypeScriptGeneratedClass* SuperTsClass = Cast<UTypeScriptGeneratedClass>(Class))
|
||||
{
|
||||
SuperTsClass->NeedReBind = false;
|
||||
}
|
||||
Class = Class->GetSuperClass();
|
||||
}
|
||||
CachedClass->DynamicInvoker.Pin()->NotifyReBind(CachedClass);
|
||||
}
|
||||
return;
|
||||
}
|
||||
Class = Class->GetSuperClass();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UTypeScriptGeneratedClass::LazyLoadRedirect()
|
||||
{
|
||||
for (TFieldIterator<UFunction> FuncIt(this, EFieldIteratorFlags::ExcludeSuper); FuncIt; ++FuncIt)
|
||||
{
|
||||
auto Function = *FuncIt;
|
||||
if (!FunctionToRedirect.Contains(Function->GetFName()))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
Function->FunctionFlags |= FUNC_BlueprintCallable | FUNC_BlueprintEvent | FUNC_Public | FUNC_Native;
|
||||
Function->SetNativeFunc(&UTypeScriptGeneratedClass::execLazyLoadCallJS);
|
||||
AddNativeFunction(*Function->GetName(), &UTypeScriptGeneratedClass::execLazyLoadCallJS);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void UTypeScriptGeneratedClass::StaticConstructor(const FObjectInitializer& ObjectInitializer)
|
||||
{
|
||||
auto Class = ObjectInitializer.GetClass();
|
||||
|
||||
//蓝图继承ts类,既然进了这里,表明链上必然有ts类,由于目前不支持ts继承蓝图,所以顶部节点往下找的第一个UTypeScriptGeneratedClass就是本类
|
||||
while (Class)
|
||||
{
|
||||
if (auto TypeScriptGeneratedClass = Cast<UTypeScriptGeneratedClass>(Class))
|
||||
{
|
||||
TypeScriptGeneratedClass->ObjectInitialize(ObjectInitializer);
|
||||
break;
|
||||
}
|
||||
Class = Class->GetSuperClass();
|
||||
}
|
||||
}
|
||||
|
||||
void UTypeScriptGeneratedClass::RestoreNativeFunc()
|
||||
{
|
||||
for (auto& KV : TempNativeFuncStorage)
|
||||
{
|
||||
if (!FunctionToRedirect.Contains(KV.Key))
|
||||
{
|
||||
auto Function = FindFunctionByName(KV.Key, EIncludeSuperFlag::ExcludeSuper);
|
||||
if (Function)
|
||||
{
|
||||
Function->SetNativeFunc(KV.Value);
|
||||
AddNativeFunction(*Function->GetName(), KV.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
TempNativeFuncStorage.Empty();
|
||||
}
|
||||
|
||||
void UTypeScriptGeneratedClass::ObjectInitialize(const FObjectInitializer& ObjectInitializer)
|
||||
{
|
||||
auto Object = ObjectInitializer.GetObj();
|
||||
if (auto SuperTypeScriptGeneratedClass = Cast<UTypeScriptGeneratedClass>(GetSuperClass()))
|
||||
{
|
||||
SuperTypeScriptGeneratedClass->ObjectInitialize(ObjectInitializer);
|
||||
}
|
||||
else
|
||||
{
|
||||
GetSuperClass()->ClassConstructor(ObjectInitializer);
|
||||
}
|
||||
|
||||
#if !WITH_EDITOR
|
||||
if (Object->HasAnyFlags(RF_ClassDefaultObject | RF_ArchetypeObject))
|
||||
return;
|
||||
#endif
|
||||
|
||||
auto PinedDynamicInvoker = DynamicInvoker.Pin();
|
||||
if (PinedDynamicInvoker)
|
||||
{
|
||||
#ifdef THREAD_SAFE
|
||||
PinedDynamicInvoker->TsConstruct(this, Object);
|
||||
#else
|
||||
if (IsInGameThread())
|
||||
{
|
||||
PinedDynamicInvoker->TsConstruct(this, Object);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
UE_LOG(Puerts, Error, TEXT("call TsConstruct of %s(%p) fail!, DynamicInvoker invalid"), *Object->GetName(), Object);
|
||||
}
|
||||
|
||||
if (UNLIKELY(!RedirectedToTypeScript))
|
||||
{
|
||||
for (TFieldIterator<UFunction> FuncIt(this, EFieldIteratorFlags::ExcludeSuper); FuncIt; ++FuncIt)
|
||||
{
|
||||
auto Function = *FuncIt;
|
||||
if (!Function->IsNative() && Function->HasAnyFunctionFlags(FUNC_Public))
|
||||
{
|
||||
TempNativeFuncStorage.Add(Function->GetFName(), Function->GetNativeFunc());
|
||||
Function->FunctionFlags |= FUNC_Native;
|
||||
Function->SetNativeFunc(&UTypeScriptGeneratedClass::execLazyLoadCallJS);
|
||||
AddNativeFunction(*Function->GetName(), &UTypeScriptGeneratedClass::execLazyLoadCallJS);
|
||||
}
|
||||
}
|
||||
RedirectedToTypeScript = true;
|
||||
}
|
||||
}
|
||||
|
||||
void UTypeScriptGeneratedClass::RedirectToTypeScript(UFunction* InFunction)
|
||||
{
|
||||
if (!FunctionToRedirect.Contains(InFunction->GetFName()))
|
||||
{
|
||||
return;
|
||||
}
|
||||
InFunction->FunctionFlags |= FUNC_BlueprintCallable | FUNC_BlueprintEvent | FUNC_Public;
|
||||
InFunction->SetNativeFunc(&UTypeScriptGeneratedClass::execCallJS);
|
||||
AddNativeFunction(*InFunction->GetName(), &UTypeScriptGeneratedClass::execCallJS);
|
||||
}
|
||||
|
||||
void UTypeScriptGeneratedClass::RedirectToTypeScriptFinish()
|
||||
{
|
||||
for (TFieldIterator<UFunction> FuncIt(this, EFieldIteratorFlags::ExcludeSuper); FuncIt; ++FuncIt)
|
||||
{
|
||||
auto Function = *FuncIt;
|
||||
if (!FunctionToRedirect.Contains(Function->GetFName()))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
Function->FunctionFlags |= FUNC_BlueprintCallable | FUNC_BlueprintEvent | FUNC_Public | FUNC_Native;
|
||||
}
|
||||
}
|
||||
|
||||
void UTypeScriptGeneratedClass::CancelRedirection()
|
||||
{
|
||||
for (TFieldIterator<UFunction> FuncIt(this, EFieldIteratorFlags::ExcludeSuper); FuncIt; ++FuncIt)
|
||||
{
|
||||
auto Function = *FuncIt;
|
||||
if (!FunctionToRedirect.Contains(Function->GetFName()))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
Function->FunctionFlags &= ~FUNC_Native;
|
||||
// Function->SetNativeFunc(ProcessInternal);
|
||||
Function->Bind(); // the same as Function->SetNativeFunc(ProcessInternal) if no native
|
||||
NativeFunctionLookupTable.RemoveAll(
|
||||
[=](const FNativeFunctionLookup& NativeFunctionLookup) { return Function->GetFName() == NativeFunctionLookup.Name; });
|
||||
}
|
||||
}
|
||||
|
||||
bool UTypeScriptGeneratedClass::NotSupportInject()
|
||||
{
|
||||
return (GetName().StartsWith("SKEL_") || GetName().StartsWith("REINST_") || GetName().StartsWith("TRASHCLASS_") ||
|
||||
GetName().StartsWith("PLACEHOLDER-") || GetName().StartsWith("HOTRELOADED_"));
|
||||
}
|
||||
|
||||
void UTypeScriptGeneratedClass::Bind()
|
||||
{
|
||||
if (GetName().StartsWith("REINST_"))
|
||||
{
|
||||
for (TFieldIterator<UFunction> FuncIt(this, EFieldIteratorFlags::ExcludeSuper); FuncIt; ++FuncIt)
|
||||
{
|
||||
auto Function = *FuncIt;
|
||||
Function->FunctionFlags &= ~FUNC_Native;
|
||||
}
|
||||
}
|
||||
|
||||
Super::Bind();
|
||||
|
||||
if (NotSupportInject())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (HasConstructor)
|
||||
{
|
||||
//普通对象会从CDO拷贝,而CDO会从蓝图AR那反序列化(见UBlueprintGeneratedClass::SerializeDefaultObject),这会
|
||||
//导致TS的构造函数对生成的蓝图变量赋值都失效,不太符合程序员直觉,设置CPF_SkipSerialization可以跳过这个过程。
|
||||
//然而在构造对象还有一个PostConstructInit步骤,里头有个从基类的CDO拷贝值的过程(ps:UE对象构造巨复杂,对象巨大)
|
||||
//这个过程如果是CDO的话,目前只找到把属性的flag设置为CPF_Transient | CPF_InstancedReference才能搞定
|
||||
// TODO: 后续尝试下TypeScript生成类不继承UBlueprintGeneratedClass的实现,能实现的话优雅些
|
||||
for (TFieldIterator<PropertyMacro> PropertyIt(this, EFieldIteratorFlags::ExcludeSuper); PropertyIt; ++PropertyIt)
|
||||
{
|
||||
PropertyMacro* Property = *PropertyIt;
|
||||
Property->SetPropertyFlags(CPF_SkipSerialization | CPF_Transient | CPF_InstancedReference);
|
||||
}
|
||||
|
||||
//可避免非CDO的在PostConstructInit从基类拷贝值
|
||||
// ClassFlags |= CLASS_Native;
|
||||
}
|
||||
#if WITH_EDITOR
|
||||
if (DynamicInvoker.IsValid())
|
||||
#endif
|
||||
{
|
||||
ClassConstructor = &StaticConstructor;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,606 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// TODO: 静态库11.8 window调试崩溃
|
||||
|
||||
#if defined(UE_GAME) || defined(UE_EDITOR) || defined(UE_SERVER) || defined(USING_IN_UNREAL_ENGINE)
|
||||
#define USING_UE 1
|
||||
#else
|
||||
#define USING_UE 0
|
||||
#endif
|
||||
|
||||
#if (PLATFORM_WINDOWS || PLATFORM_MAC || PLATFORM_LINUX || defined(WITH_INSPECTOR)) && !defined(WITHOUT_INSPECTOR)
|
||||
|
||||
#include "V8InspectorImpl.h"
|
||||
|
||||
#if USING_UE
|
||||
#include "UECompatible.h"
|
||||
#endif
|
||||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <locale>
|
||||
#include <codecvt>
|
||||
|
||||
PRAGMA_DISABLE_UNDEFINED_IDENTIFIER_WARNINGS
|
||||
#pragma warning(push)
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(disable : 4251)
|
||||
#endif
|
||||
#include "v8.h"
|
||||
#include "v8-inspector.h"
|
||||
#include "libplatform/libplatform.h"
|
||||
#pragma warning(pop)
|
||||
|
||||
#define ASIO_NO_TYPEID // UE需避免使用RTTI功能
|
||||
|
||||
#define ASIO_STANDALONE
|
||||
#define _WEBSOCKETPP_CPP11_TYPE_TRAITS_
|
||||
#include "websocketpp/config/asio_no_tls.hpp"
|
||||
#include "websocketpp/server.hpp"
|
||||
PRAGMA_ENABLE_UNDEFINED_IDENTIFIER_WARNINGS
|
||||
|
||||
#if USING_UE
|
||||
#include "Containers/Ticker.h"
|
||||
#else
|
||||
#include "Log.h"
|
||||
#endif
|
||||
|
||||
#if USING_UE
|
||||
DEFINE_LOG_CATEGORY_STATIC(LogV8Inspector, Log, All);
|
||||
#endif
|
||||
|
||||
namespace PUERTS_NAMESPACE
|
||||
{
|
||||
class V8InspectorChannelImpl : public v8_inspector::V8Inspector::Channel, public V8InspectorChannel
|
||||
{
|
||||
public:
|
||||
V8InspectorChannelImpl(v8::Isolate* InIsolate, v8_inspector::V8Inspector* InV8Inspector, const int32_t InCxtGroupID);
|
||||
|
||||
void DispatchProtocolMessage(const std::string& Message) override;
|
||||
|
||||
void OnMessage(std::function<void(const std::string&)> Handler) override;
|
||||
|
||||
virtual ~V8InspectorChannelImpl() override
|
||||
{
|
||||
OnSendMessage = nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
void SendMessage(v8_inspector::StringBuffer& MessageBuffer);
|
||||
|
||||
void sendResponse(int CallID, std::unique_ptr<v8_inspector::StringBuffer> Message) override;
|
||||
|
||||
void sendNotification(std::unique_ptr<v8_inspector::StringBuffer> Message) override;
|
||||
|
||||
void flushProtocolNotifications() override
|
||||
{
|
||||
}
|
||||
|
||||
std::unique_ptr<v8_inspector::V8InspectorSession> V8InspectorSession;
|
||||
|
||||
std::function<void(const std::string&)> OnSendMessage;
|
||||
|
||||
v8::Isolate* Isolate;
|
||||
};
|
||||
|
||||
V8InspectorChannelImpl::V8InspectorChannelImpl(
|
||||
v8::Isolate* InIsolate, v8_inspector::V8Inspector* InV8Inspector, const int32_t InCxtGroupID)
|
||||
{
|
||||
v8_inspector::StringView DummyState;
|
||||
Isolate = InIsolate;
|
||||
#if V8_MAJOR_VERSION >= 10
|
||||
V8InspectorSession = InV8Inspector->connect(InCxtGroupID, this, DummyState, v8_inspector::V8Inspector::kFullyTrusted);
|
||||
#else
|
||||
V8InspectorSession = InV8Inspector->connect(InCxtGroupID, this, DummyState);
|
||||
#endif
|
||||
}
|
||||
|
||||
void V8InspectorChannelImpl::DispatchProtocolMessage(const std::string& Message)
|
||||
{
|
||||
const auto MessagePtr = reinterpret_cast<const uint8_t*>(Message.c_str());
|
||||
const auto MessageLen = (size_t) Message.length();
|
||||
|
||||
v8_inspector::StringView StringView(MessagePtr, MessageLen);
|
||||
|
||||
#ifdef THREAD_SAFE
|
||||
v8::Locker Locker(Isolate);
|
||||
#endif
|
||||
v8::Isolate::Scope IsolateScope(Isolate);
|
||||
v8::SealHandleScope HandleScope(Isolate);
|
||||
V8InspectorSession->dispatchProtocolMessage(StringView);
|
||||
}
|
||||
|
||||
void V8InspectorChannelImpl::OnMessage(std::function<void(const std::string&)> Handler)
|
||||
{
|
||||
OnSendMessage = Handler;
|
||||
}
|
||||
|
||||
void V8InspectorChannelImpl::SendMessage(v8_inspector::StringBuffer& MessageBuffer)
|
||||
{
|
||||
v8_inspector::StringView MessageView = MessageBuffer.string();
|
||||
|
||||
std::string Message;
|
||||
if (MessageView.is8Bit())
|
||||
{
|
||||
Message = reinterpret_cast<const char*>(MessageView.characters8());
|
||||
}
|
||||
else
|
||||
{
|
||||
#if PLATFORM_WINDOWS
|
||||
#pragma warning(disable : 4996)
|
||||
std::wstring_convert<std::codecvt_utf8_utf16<uint16_t>, uint16_t> Conv;
|
||||
const uint16_t* Start = MessageView.characters16();
|
||||
#else
|
||||
std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> Conv;
|
||||
const char16_t* Start = reinterpret_cast<const char16_t*>(MessageView.characters16());
|
||||
#endif
|
||||
Message = Conv.to_bytes(Start, Start + MessageView.length());
|
||||
}
|
||||
|
||||
if (OnSendMessage)
|
||||
OnSendMessage(Message);
|
||||
}
|
||||
|
||||
void V8InspectorChannelImpl::sendResponse(int /* CallID */, std::unique_ptr<v8_inspector::StringBuffer> Message)
|
||||
{
|
||||
SendMessage(*Message);
|
||||
}
|
||||
|
||||
void V8InspectorChannelImpl::sendNotification(std::unique_ptr<v8_inspector::StringBuffer> Message)
|
||||
{
|
||||
SendMessage(*Message);
|
||||
}
|
||||
|
||||
class V8InspectorClientImpl : public V8Inspector,
|
||||
#if USING_UE
|
||||
#if ENGINE_MAJOR_VERSION >= 5
|
||||
public FTSTickerObjectBase,
|
||||
#else
|
||||
public FTickerObjectBase,
|
||||
#endif
|
||||
#endif
|
||||
public v8_inspector::V8InspectorClient
|
||||
{
|
||||
public:
|
||||
using wspp_server = websocketpp::server<websocketpp::config::asio>;
|
||||
|
||||
using wspp_connection_hdl = websocketpp::connection_hdl;
|
||||
|
||||
using wspp_message_ptr = wspp_server::message_ptr;
|
||||
|
||||
using wspp_exception = websocketpp::exception;
|
||||
|
||||
V8InspectorClientImpl(int32_t InPort, v8::Local<v8::Context> InContext);
|
||||
|
||||
virtual ~V8InspectorClientImpl();
|
||||
|
||||
void Close() override;
|
||||
|
||||
#if USING_UE
|
||||
bool Tick(float DeltaTime) override;
|
||||
#else
|
||||
bool Tick(float DeltaTime);
|
||||
#endif
|
||||
|
||||
bool Tick() override;
|
||||
|
||||
V8InspectorChannel* CreateV8InspectorChannel() override;
|
||||
|
||||
private:
|
||||
void OnHTTP(wspp_connection_hdl Handle);
|
||||
|
||||
void OnOpen(wspp_connection_hdl Handle);
|
||||
|
||||
void OnReceiveMessage(wspp_connection_hdl Handle, wspp_message_ptr Message);
|
||||
|
||||
void OnSendMessage(wspp_connection_hdl Handle, const std::string& Message);
|
||||
|
||||
void OnClose(wspp_connection_hdl Handle);
|
||||
|
||||
void OnFail(wspp_connection_hdl Handle);
|
||||
|
||||
void runMessageLoopOnPause(int ContextGroupId) override;
|
||||
|
||||
void quitMessageLoopOnPause() override;
|
||||
|
||||
void runIfWaitingForDebugger(int ContextGroupId) override
|
||||
{
|
||||
Connected = true;
|
||||
}
|
||||
|
||||
v8::Isolate* Isolate;
|
||||
|
||||
v8::Persistent<v8::Context> Context;
|
||||
|
||||
v8::Persistent<v8::Function> MicroTasksRunner;
|
||||
|
||||
int32_t Port;
|
||||
|
||||
#if defined(V8_HAS_WRAP_API_WITHOUT_STL)
|
||||
v8_inspector::V8Inspector* V8Inspector;
|
||||
#else
|
||||
std::unique_ptr<v8_inspector::V8Inspector> V8Inspector;
|
||||
#endif
|
||||
|
||||
int32_t CtxGroupID;
|
||||
|
||||
std::map<void*, V8InspectorChannelImpl*> V8InspectorChannels;
|
||||
|
||||
wspp_server Server;
|
||||
|
||||
std::string JSONVersion;
|
||||
|
||||
std::string JSONList;
|
||||
|
||||
bool IsAlive;
|
||||
|
||||
bool IsPaused;
|
||||
|
||||
bool Connected;
|
||||
};
|
||||
|
||||
#if USING_UE
|
||||
void ReportException(const websocketpp::exception& Exception, const TCHAR* JobInfo)
|
||||
{
|
||||
#if PLATFORM_WINDOWS
|
||||
int len = MultiByteToWideChar(CP_ACP, 0, Exception.what(), -1, NULL, 0);
|
||||
wchar_t* wstr = new wchar_t[len + 1];
|
||||
memset(wstr, 0, len + 1);
|
||||
MultiByteToWideChar(CP_ACP, 0, Exception.what(), -1, wstr, len);
|
||||
len = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, NULL, 0, NULL, NULL);
|
||||
char* str = new char[len + 1];
|
||||
memset(str, 0, len + 1);
|
||||
WideCharToMultiByte(CP_UTF8, 0, wstr, -1, str, len, NULL, NULL);
|
||||
delete[] wstr;
|
||||
UE_LOG(LogV8Inspector, Warning, TEXT("%s, errno:%d, message:%s"), JobInfo, Exception.code().value(), UTF8_TO_TCHAR(str));
|
||||
delete[] str;
|
||||
#else
|
||||
UE_LOG(LogV8Inspector, Warning, TEXT("%s, errno:%d, message:%s"), JobInfo, Exception.code().value(),
|
||||
ANSI_TO_TCHAR(Exception.what()));
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
void MicroTasksRunnerFunction(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
// throw an error so the v8 will clean pending exception later
|
||||
Info.GetIsolate()->ThrowException(
|
||||
v8::Exception::Error(v8::String::NewFromUtf8(Info.GetIsolate(), "test", v8::NewStringType::kNormal).ToLocalChecked()));
|
||||
}
|
||||
|
||||
V8InspectorClientImpl::V8InspectorClientImpl(int32_t InPort, v8::Local<v8::Context> InContext)
|
||||
#if USING_UE
|
||||
#if ENGINE_MAJOR_VERSION >= 5
|
||||
: FTSTickerObjectBase(0.001f)
|
||||
#else
|
||||
: FTickerObjectBase(0.001f)
|
||||
#endif
|
||||
#endif
|
||||
{
|
||||
Isolate = InContext->GetIsolate();
|
||||
Context.Reset(Isolate, InContext);
|
||||
MicroTasksRunner.Reset(
|
||||
Isolate, v8::FunctionTemplate::New(Isolate, MicroTasksRunnerFunction)->GetFunction(InContext).ToLocalChecked());
|
||||
Port = InPort;
|
||||
IsAlive = false;
|
||||
Connected = false;
|
||||
|
||||
static int32_t CurrentCtxGroupID = 1;
|
||||
CtxGroupID = CurrentCtxGroupID++;
|
||||
const uint8_t CtxNameConst[] = "V8InspectorContext";
|
||||
v8_inspector::StringView CtxName(CtxNameConst, sizeof(CtxNameConst) - 1);
|
||||
#if defined(V8_HAS_WRAP_API_WITHOUT_STL)
|
||||
V8Inspector = V8Inspector_Create_Without_Stl(Isolate, this);
|
||||
#else
|
||||
V8Inspector = v8_inspector::V8Inspector::create(Isolate, this);
|
||||
#endif
|
||||
V8Inspector->contextCreated(v8_inspector::V8ContextInfo(InContext, CtxGroupID, CtxName));
|
||||
|
||||
if (Port < 0)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
Server.set_reuse_addr(true);
|
||||
Server.set_access_channels(websocketpp::log::alevel::none);
|
||||
Server.set_error_channels(websocketpp::log::elevel::none);
|
||||
|
||||
Server.set_http_handler(std::bind(&V8InspectorClientImpl::OnHTTP, this, std::placeholders::_1));
|
||||
Server.set_open_handler(std::bind(&V8InspectorClientImpl::OnOpen, this, std::placeholders::_1));
|
||||
Server.set_message_handler(
|
||||
std::bind(&V8InspectorClientImpl::OnReceiveMessage, this, std::placeholders::_1, std::placeholders::_2));
|
||||
Server.set_close_handler(std::bind(&V8InspectorClientImpl::OnClose, this, std::placeholders::_1));
|
||||
Server.set_fail_handler(std::bind(&V8InspectorClientImpl::OnFail, this, std::placeholders::_1));
|
||||
|
||||
Server.init_asio();
|
||||
Server.listen(Port);
|
||||
Server.start_accept();
|
||||
|
||||
JSONVersion = R"({
|
||||
"Browser": "Puerts/v1.0.0",
|
||||
"Protocol-Version": "1.1"
|
||||
})";
|
||||
|
||||
JSONList = R"([{
|
||||
"description": "Puerts Inspector",
|
||||
"id": "0",
|
||||
"title": "Puerts Inspector",
|
||||
"type": "node",
|
||||
)";
|
||||
JSONList += "\"webSocketDebuggerUrl\"";
|
||||
JSONList += ":";
|
||||
JSONList += "\"ws://127.0.0.1:";
|
||||
JSONList += std::to_string(Port) + "\"\r\n}]";
|
||||
|
||||
IsAlive = true;
|
||||
|
||||
#if USING_UE
|
||||
FString InspectorUrl =
|
||||
FString::Printf(TEXT("devtools://devtools/bundled/inspector.html?v8only=true&ws=127.0.0.1:%d"), Port);
|
||||
UE_LOG(LogV8Inspector, Log,
|
||||
TEXT("Startup Inspector Successfully!\n"
|
||||
"Please Open This URL in Debugger Front-End(e.g. Chrome DevTool):\n \n"
|
||||
"\t%s\n \n"),
|
||||
*InspectorUrl);
|
||||
#endif
|
||||
}
|
||||
catch (const websocketpp::exception& Exception)
|
||||
{
|
||||
IsAlive = false;
|
||||
#if USING_UE
|
||||
ReportException(Exception, TEXT("Failed to Startup Inspector"));
|
||||
#else
|
||||
puerts::PLog(puerts::Error, "V8InspectorClientImpl: %s", Exception.what());
|
||||
puerts::PLog(puerts::Error, "Failed to Startup Inspector.");
|
||||
#endif
|
||||
}
|
||||
|
||||
IsPaused = false;
|
||||
}
|
||||
|
||||
V8InspectorChannel* V8InspectorClientImpl::CreateV8InspectorChannel()
|
||||
{
|
||||
#if defined(V8_HAS_WRAP_API_WITHOUT_STL)
|
||||
return new V8InspectorChannelImpl(Isolate, V8Inspector, CtxGroupID);
|
||||
#else
|
||||
return new V8InspectorChannelImpl(Isolate, V8Inspector.get(), CtxGroupID);
|
||||
#endif
|
||||
}
|
||||
|
||||
V8InspectorClientImpl::~V8InspectorClientImpl()
|
||||
{
|
||||
Close();
|
||||
#if defined(V8_HAS_WRAP_API_WITHOUT_STL)
|
||||
v8_inspector::V8Inspector_Destroy_Without_Stl(V8Inspector);
|
||||
#endif
|
||||
}
|
||||
|
||||
void V8InspectorClientImpl::Close()
|
||||
{
|
||||
if (IsAlive)
|
||||
{
|
||||
#ifdef THREAD_SAFE
|
||||
v8::Locker Locker(Isolate);
|
||||
#endif
|
||||
Server.stop_listening();
|
||||
for (auto Iter = V8InspectorChannels.begin(); Iter != V8InspectorChannels.end(); ++Iter)
|
||||
{
|
||||
delete Iter->second;
|
||||
}
|
||||
V8InspectorChannels.clear();
|
||||
|
||||
v8::Isolate::Scope IsolateScope(Isolate);
|
||||
v8::HandleScope HandleScope(Isolate);
|
||||
V8Inspector->contextDestroyed(Context.Get(Isolate));
|
||||
IsAlive = false;
|
||||
IsPaused = false;
|
||||
}
|
||||
}
|
||||
|
||||
bool V8InspectorClientImpl::Tick(float /* DeltaTime */)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (IsAlive)
|
||||
{
|
||||
#ifdef THREAD_SAFE
|
||||
v8::Locker Locker(Isolate);
|
||||
#endif
|
||||
|
||||
{
|
||||
// v8::Locker lock(Isolate);
|
||||
Server.poll();
|
||||
|
||||
v8::Isolate::Scope IsolateScope(Isolate);
|
||||
v8::HandleScope HandleScope(Isolate);
|
||||
auto LocalContext = Context.Get(Isolate);
|
||||
v8::Context::Scope ContextScope(LocalContext);
|
||||
v8::TryCatch TryCatch(Isolate);
|
||||
|
||||
MicroTasksRunner.Get(Isolate)->Call(LocalContext, LocalContext->Global(), 0, nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (const wspp_exception& Exception)
|
||||
{
|
||||
#if USING_UE
|
||||
ReportException(Exception, TEXT("Tick"));
|
||||
#else
|
||||
puerts::PLog(puerts::Error, "Tick: %s", Exception.what());
|
||||
#endif
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool V8InspectorClientImpl::Tick()
|
||||
{
|
||||
Tick(0);
|
||||
return IsAlive && Connected;
|
||||
}
|
||||
|
||||
void V8InspectorClientImpl::OnHTTP(wspp_connection_hdl Handle)
|
||||
{
|
||||
try
|
||||
{
|
||||
auto Connection = Server.get_con_from_hdl(Handle);
|
||||
auto Resource = Connection->get_resource();
|
||||
|
||||
if (Resource == "/json" || Resource == "/json/list")
|
||||
{
|
||||
#if USING_UE
|
||||
UE_LOG(LogV8Inspector, Display, TEXT("request /json/list"));
|
||||
#else
|
||||
puerts::PLog(puerts::Log, "request /json/list");
|
||||
#endif
|
||||
Connection->set_body(JSONList);
|
||||
Connection->set_status(websocketpp::http::status_code::ok);
|
||||
}
|
||||
else if (Resource == "/json/version")
|
||||
{
|
||||
#if USING_UE
|
||||
UE_LOG(LogV8Inspector, Display, TEXT("request /json/version"));
|
||||
#else
|
||||
puerts::PLog(puerts::Log, "request /json/version");
|
||||
#endif
|
||||
Connection->set_body(JSONVersion);
|
||||
Connection->set_status(websocketpp::http::status_code::ok);
|
||||
}
|
||||
else
|
||||
{
|
||||
#if USING_UE
|
||||
UE_LOG(LogV8Inspector, Display, TEXT("404 Not Found"));
|
||||
#else
|
||||
puerts::PLog(puerts::Log, "404 Not Found");
|
||||
#endif
|
||||
Connection->set_body("404 Not Found");
|
||||
Connection->set_status(websocketpp::http::status_code::not_found);
|
||||
}
|
||||
}
|
||||
catch (const wspp_exception& Exception)
|
||||
{
|
||||
#if USING_UE
|
||||
ReportException(Exception, TEXT("OnHTTP"));
|
||||
#else
|
||||
puerts::PLog(puerts::Error, "OnHTTP: %s", Exception.what());
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void V8InspectorClientImpl::OnOpen(wspp_connection_hdl Handle)
|
||||
{
|
||||
V8InspectorChannelImpl* channel = static_cast<V8InspectorChannelImpl*>(CreateV8InspectorChannel());
|
||||
V8InspectorChannels[Handle.lock().get()] = channel;
|
||||
channel->OnMessage(std::bind(&V8InspectorClientImpl::OnSendMessage, this, Handle, std::placeholders::_1));
|
||||
#if USING_UE
|
||||
UE_LOG(LogV8Inspector, Display, TEXT("Inspector: Connect"));
|
||||
#else
|
||||
puerts::PLog(puerts::Log, "Inspector: Connect");
|
||||
#endif
|
||||
}
|
||||
|
||||
void V8InspectorClientImpl::OnReceiveMessage(wspp_connection_hdl Handle, wspp_message_ptr Message)
|
||||
{
|
||||
//#if USING_UE
|
||||
// UE_LOG(LogV8Inspector, Display, TEXT("<---: %s"), ANSI_TO_TCHAR(Message->get_payload().c_str()));
|
||||
//#else
|
||||
// puerts::PLog(puerts::Log, "<---: %s", Message->get_payload().c_str());
|
||||
//#endif
|
||||
auto channel = V8InspectorChannels[Handle.lock().get()];
|
||||
|
||||
{
|
||||
// v8::Locker Locker(Isolate);
|
||||
v8::Isolate::Scope IsolateScope(Isolate);
|
||||
v8::SealHandleScope scope(Isolate);
|
||||
channel->DispatchProtocolMessage(Message->get_payload());
|
||||
}
|
||||
}
|
||||
|
||||
void V8InspectorClientImpl::OnSendMessage(wspp_connection_hdl Handle, const std::string& Message)
|
||||
{
|
||||
//#if USING_UE
|
||||
// UE_LOG(LogV8Inspector, Display, TEXT("--->: %s"), ANSI_TO_TCHAR(Message.c_str()));
|
||||
//#else
|
||||
// puerts::PLog(puerts::Log, "--->: %s", Message.c_str());
|
||||
//#endif
|
||||
|
||||
try
|
||||
{
|
||||
Server.send(Handle, Message, websocketpp::frame::opcode::TEXT);
|
||||
}
|
||||
catch (const websocketpp::exception& Exception)
|
||||
{
|
||||
#if USING_UE
|
||||
ReportException(Exception, TEXT("OnSendMessage"));
|
||||
#else
|
||||
puerts::PLog(puerts::Error, "OnSendMessage: %s", Exception.what());
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void V8InspectorClientImpl::OnClose(wspp_connection_hdl Handle)
|
||||
{
|
||||
void* HandlePtr = Handle.lock().get();
|
||||
delete V8InspectorChannels[HandlePtr];
|
||||
V8InspectorChannels.erase(HandlePtr);
|
||||
#if USING_UE
|
||||
UE_LOG(LogV8Inspector, Display, TEXT("Inspector: Disconnect"));
|
||||
#endif
|
||||
}
|
||||
|
||||
void V8InspectorClientImpl::OnFail(wspp_connection_hdl Handle)
|
||||
{
|
||||
wspp_server::connection_ptr con = Server.get_con_from_hdl(Handle);
|
||||
std::string message = con->get_ec().message();
|
||||
#if USING_UE
|
||||
UE_LOG(LogV8Inspector, Error, TEXT("Connection OnFail %s"), UTF8_TO_TCHAR(message.c_str()));
|
||||
#else
|
||||
puerts::PLog(puerts::Error, "Connection OnFail %s", message.c_str());
|
||||
#endif
|
||||
}
|
||||
|
||||
void V8InspectorClientImpl::runMessageLoopOnPause(int /* ContextGroupId */)
|
||||
{
|
||||
if (IsPaused)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
IsPaused = true;
|
||||
|
||||
while (IsPaused)
|
||||
{
|
||||
Tick();
|
||||
}
|
||||
}
|
||||
|
||||
void V8InspectorClientImpl::quitMessageLoopOnPause()
|
||||
{
|
||||
IsPaused = false;
|
||||
}
|
||||
|
||||
V8Inspector* CreateV8Inspector(int32_t Port, void* InContextPtr)
|
||||
{
|
||||
v8::Local<v8::Context>* ContextPtr = static_cast<v8::Local<v8::Context>*>(InContextPtr);
|
||||
return new V8InspectorClientImpl(Port, *ContextPtr);
|
||||
}
|
||||
}; // namespace PUERTS_NAMESPACE
|
||||
|
||||
#else
|
||||
|
||||
#include "V8InspectorImpl.h"
|
||||
|
||||
namespace PUERTS_NAMESPACE
|
||||
{
|
||||
V8Inspector* CreateV8Inspector(int32_t Port, void* InContextPtr)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}; // namespace PUERTS_NAMESPACE
|
||||
|
||||
#endif // WITH_EDITOR && (PLATFORM_WINDOWS || PLATFORM_MAC)
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
|
||||
#if !defined(PUERTS_NAMESPACE)
|
||||
#if defined(WITH_QJS_NAMESPACE_SUFFIX)
|
||||
#define PUERTS_NAMESPACE puerts_qjs
|
||||
#else
|
||||
#define PUERTS_NAMESPACE puerts
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef PRAGMA_DISABLE_UNDEFINED_IDENTIFIER_WARNINGS
|
||||
#if defined(_MSC_VER)
|
||||
#define PRAGMA_DISABLE_UNDEFINED_IDENTIFIER_WARNINGS __pragma(warning(push)) __pragma(warning(disable : 4668))
|
||||
#elif defined(__clang__)
|
||||
#define PRAGMA_DISABLE_UNDEFINED_IDENTIFIER_WARNINGS \
|
||||
_Pragma("clang diagnostic push") _Pragma("clang diagnostic ignored \"-Wundef\"")
|
||||
#elif defined(__GNUC__)
|
||||
#define PRAGMA_DISABLE_UNDEFINED_IDENTIFIER_WARNINGS _Pragma("GCC diagnostic push") _Pragma("GCC diagnostic ignored \"-Wundef\"")
|
||||
#endif
|
||||
#endif // PRAGMA_DISABLE_UNDEFINED_IDENTIFIER_WARNINGS
|
||||
|
||||
#ifndef PRAGMA_ENABLE_UNDEFINED_IDENTIFIER_WARNINGS
|
||||
#if defined(_MSC_VER)
|
||||
#define PRAGMA_ENABLE_UNDEFINED_IDENTIFIER_WARNINGS __pragma(warning(pop))
|
||||
#elif defined(__clang__)
|
||||
#define PRAGMA_ENABLE_UNDEFINED_IDENTIFIER_WARNINGS _Pragma("clang diagnostic pop")
|
||||
#elif defined(__GNUC__)
|
||||
#define PRAGMA_ENABLE_UNDEFINED_IDENTIFIER_WARNINGS _Pragma("GCC diagnostic pop")
|
||||
#endif
|
||||
#endif // PRAGMA_ENABLE_UNDEFINED_IDENTIFIER_WARNINGS
|
||||
|
||||
namespace PUERTS_NAMESPACE
|
||||
{
|
||||
class V8InspectorChannel
|
||||
{
|
||||
public:
|
||||
virtual void DispatchProtocolMessage(const std::string& Message) = 0;
|
||||
|
||||
virtual void OnMessage(std::function<void(const std::string&)> Handler) = 0;
|
||||
|
||||
virtual ~V8InspectorChannel()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class V8Inspector
|
||||
{
|
||||
public:
|
||||
virtual void Close() = 0;
|
||||
|
||||
virtual bool Tick() = 0;
|
||||
|
||||
virtual V8InspectorChannel* CreateV8InspectorChannel() = 0;
|
||||
|
||||
virtual ~V8Inspector()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
// 接受端口和v8::Local<v8::Context>指针,返回一个新的V8Inspector指针
|
||||
V8Inspector* CreateV8Inspector(int32_t Port, void* InContextPtr);
|
||||
}; // namespace PUERTS_NAMESPACE
|
||||
@@ -0,0 +1,19 @@
|
||||
#include <V8Utils.h>
|
||||
|
||||
v8::Local<v8::String> puerts::FV8Utils::ToV8String(v8::Isolate* Isolate, const TCHAR* String)
|
||||
{
|
||||
#ifdef WITH_QUICKJS
|
||||
return v8::String::NewFromUtf8(Isolate, TCHAR_TO_UTF8(String), v8::NewStringType::kNormal).ToLocalChecked();
|
||||
#else
|
||||
return v8::String::NewFromTwoByte(Isolate, TCHAR_TO_UTF16(String), v8::NewStringType::kNormal).ToLocalChecked();
|
||||
#endif
|
||||
}
|
||||
|
||||
FString puerts::FV8Utils::ToFString(v8::Isolate* Isolate, v8::Local<v8::Value> Value)
|
||||
{
|
||||
#ifdef WITH_QUICKJS
|
||||
return UTF8_TO_TCHAR(*(v8::String::Utf8Value(Isolate, Value)));
|
||||
#else
|
||||
return UTF16_TO_TCHAR(*(v8::String::Value(Isolate, Value)));
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,458 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#if defined(WITH_WEBSOCKET)
|
||||
|
||||
#include "V8InspectorImpl.h" // for PRAGMA_DISABLE_UNDEFINED_IDENTIFIER_WARNINGS
|
||||
#include "V8Utils.h"
|
||||
|
||||
#ifndef THIRD_PARTY_INCLUDES_START
|
||||
#define THIRD_PARTY_INCLUDES_START
|
||||
#endif
|
||||
|
||||
#ifndef THIRD_PARTY_INCLUDES_END
|
||||
#define THIRD_PARTY_INCLUDES_END
|
||||
#endif
|
||||
|
||||
PRAGMA_DISABLE_UNDEFINED_IDENTIFIER_WARNINGS
|
||||
#pragma warning(push)
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(disable : 4251)
|
||||
#endif
|
||||
#include "v8.h"
|
||||
#pragma warning(pop)
|
||||
|
||||
#define ASIO_NO_TYPEID // UE需避免使用RTTI功能
|
||||
|
||||
#define ASIO_STANDALONE
|
||||
#define _WEBSOCKETPP_CPP11_TYPE_TRAITS_
|
||||
#define UI UI_ST
|
||||
THIRD_PARTY_INCLUDES_START
|
||||
#if defined(WITH_WEBSOCKET_SSL)
|
||||
#include <websocketpp/config/asio.hpp>
|
||||
#else
|
||||
#include "websocketpp/config/asio_no_tls.hpp"
|
||||
#endif
|
||||
#include "websocketpp/client.hpp"
|
||||
THIRD_PARTY_INCLUDES_END
|
||||
#undef UI
|
||||
PRAGMA_ENABLE_UNDEFINED_IDENTIFIER_WARNINGS
|
||||
|
||||
#include <sstream>
|
||||
|
||||
namespace PUERTS_NAMESPACE
|
||||
{
|
||||
#if !defined(USING_IN_UNREAL_ENGINE)
|
||||
class DataTransfer
|
||||
{
|
||||
public:
|
||||
static void* GetArrayBufferData(v8::Local<v8::ArrayBuffer> InArrayBuffer)
|
||||
{
|
||||
size_t DataLength;
|
||||
return GetArrayBufferData(InArrayBuffer, DataLength);
|
||||
}
|
||||
|
||||
static void* GetArrayBufferData(v8::Local<v8::ArrayBuffer> InArrayBuffer, size_t& DataLength)
|
||||
{
|
||||
#if defined(HAS_ARRAYBUFFER_NEW_WITHOUT_STL)
|
||||
return v8::ArrayBuffer_Get_Data(InArrayBuffer, DataLength);
|
||||
#else
|
||||
#if USING_IN_UNREAL_ENGINE
|
||||
DataLength = InArrayBuffer->GetContents().ByteLength();
|
||||
return InArrayBuffer->GetContents().Data();
|
||||
#else
|
||||
auto BS = InArrayBuffer->GetBackingStore();
|
||||
DataLength = BS->ByteLength();
|
||||
return BS->Data();
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
static v8::Local<v8::ArrayBuffer> NewArrayBuffer(v8::Local<v8::Context> Context, void* Data, size_t DataLength)
|
||||
{
|
||||
#if defined(HAS_ARRAYBUFFER_NEW_WITHOUT_STL)
|
||||
return v8::ArrayBuffer_New_Without_Stl(Context->GetIsolate(), Data, DataLength);
|
||||
#else
|
||||
#if USING_IN_UNREAL_ENGINE
|
||||
return v8::ArrayBuffer::New(Context->GetIsolate(), Data, DataLength);
|
||||
#else
|
||||
auto Backing = v8::ArrayBuffer::NewBackingStore(Data, DataLength, v8::BackingStore::EmptyDeleter, nullptr);
|
||||
return v8::ArrayBuffer::New(Context->GetIsolate(), std::move(Backing));
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
class V8WebSocketClientImpl
|
||||
{
|
||||
public:
|
||||
V8WebSocketClientImpl(v8::Isolate* InIsolate, v8::Local<v8::Context> InContext, v8::Local<v8::Object> InSelf);
|
||||
|
||||
#if defined(WITH_WEBSOCKET_SSL)
|
||||
using wspp_client = websocketpp::client<websocketpp::config::asio_tls>;
|
||||
#else
|
||||
using wspp_client = websocketpp::client<websocketpp::config::asio>;
|
||||
#endif
|
||||
|
||||
using wspp_connection_hdl = websocketpp::connection_hdl;
|
||||
|
||||
using wspp_message_ptr = wspp_client::message_ptr;
|
||||
|
||||
using wspp_exception = websocketpp::exception;
|
||||
|
||||
enum HandlerType
|
||||
{
|
||||
ON_OPEN,
|
||||
ON_MESSAGE,
|
||||
ON_CLOSE,
|
||||
ON_FAIL,
|
||||
HANDLE_TYPE_END
|
||||
};
|
||||
|
||||
void Connect(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
|
||||
void Send(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
|
||||
void SetHandles(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
|
||||
void Close(const v8::FunctionCallbackInfo<v8::Value>& Info);
|
||||
|
||||
void Close(websocketpp::close::status::value const code, std::string const& reason);
|
||||
|
||||
void PollOne();
|
||||
|
||||
private:
|
||||
void OnOpen(wspp_connection_hdl Handle);
|
||||
|
||||
void OnMessage(wspp_connection_hdl Handle, wspp_message_ptr Message);
|
||||
|
||||
void OnClose(wspp_connection_hdl Handle);
|
||||
|
||||
void OnFail(wspp_connection_hdl Handle);
|
||||
|
||||
void Cleanup();
|
||||
|
||||
private:
|
||||
v8::Isolate* Isolate;
|
||||
|
||||
v8::Global<v8::Context> GContext;
|
||||
|
||||
v8::Global<v8::Object> GSelf;
|
||||
|
||||
wspp_client Client;
|
||||
|
||||
wspp_connection_hdl Handle;
|
||||
|
||||
bool Connenting = false;
|
||||
|
||||
v8::Global<v8::Function> Handles[HANDLE_TYPE_END];
|
||||
};
|
||||
|
||||
static void OnGarbageCollectedWithFree(const v8::WeakCallbackInfo<V8WebSocketClientImpl>& Data)
|
||||
{
|
||||
// UE_LOG(LogTemp, Warning, TEXT(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> auto gc %p"), Data.GetParameter());
|
||||
Data.GetParameter()->Close(websocketpp::close::status::normal, "");
|
||||
delete Data.GetParameter();
|
||||
}
|
||||
|
||||
V8WebSocketClientImpl::V8WebSocketClientImpl(v8::Isolate* InIsolate, v8::Local<v8::Context> InContext, v8::Local<v8::Object> InSelf)
|
||||
: Isolate(InIsolate), GContext(InIsolate, InContext), GSelf(InIsolate, InSelf)
|
||||
{
|
||||
GSelf.SetWeak<V8WebSocketClientImpl>(this, &OnGarbageCollectedWithFree, v8::WeakCallbackType::kInternalFields);
|
||||
// UE_LOG(LogTemp, Warning, TEXT(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> set weak %p"), this);
|
||||
}
|
||||
|
||||
#if defined(WITH_WEBSOCKET_SSL)
|
||||
websocketpp::lib::shared_ptr<puerts_asio::ssl::context> on_tls_init(websocketpp::connection_hdl)
|
||||
{
|
||||
auto ctx = websocketpp::lib::make_shared<puerts_asio::ssl::context>(websocketpp::lib::puerts_asio::ssl::context::sslv23);
|
||||
ctx->set_verify_mode(puerts_asio::ssl::verify_none);
|
||||
return ctx;
|
||||
}
|
||||
#endif
|
||||
|
||||
void V8WebSocketClientImpl::Connect(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
std::string uri = *(v8::String::Utf8Value(Isolate, Info[0]));
|
||||
|
||||
Client.set_access_channels(websocketpp::log::alevel::none);
|
||||
Client.set_error_channels(websocketpp::log::elevel::none);
|
||||
|
||||
Client.set_open_handler(std::bind(&V8WebSocketClientImpl::OnOpen, this, std::placeholders::_1));
|
||||
Client.set_message_handler(std::bind(&V8WebSocketClientImpl::OnMessage, this, std::placeholders::_1, std::placeholders::_2));
|
||||
Client.set_close_handler(std::bind(&V8WebSocketClientImpl::OnClose, this, std::placeholders::_1));
|
||||
Client.set_fail_handler(std::bind(&V8WebSocketClientImpl::OnFail, this, std::placeholders::_1));
|
||||
#if defined(WITH_WEBSOCKET_SSL)
|
||||
Client.set_tls_init_handler(&on_tls_init);
|
||||
#endif
|
||||
|
||||
Client.init_asio();
|
||||
|
||||
websocketpp::lib::error_code ec;
|
||||
wspp_client::connection_ptr con = Client.get_connection(uri, ec);
|
||||
if (ec)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "could not create connection because: " << ec.message() << std::endl;
|
||||
FV8Utils::ThrowException(Isolate, ss.str().c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
// Note that connect here only requests a connection. No network messages are
|
||||
// exchanged until the event loop starts running in the next line.
|
||||
Client.connect(con);
|
||||
Connenting = true;
|
||||
}
|
||||
|
||||
void V8WebSocketClientImpl::Send(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
if (Handle.expired())
|
||||
{
|
||||
FV8Utils::ThrowException(Isolate, "WebSocket is not open");
|
||||
return;
|
||||
}
|
||||
websocketpp::lib::error_code ec;
|
||||
|
||||
auto Value = Info[0];
|
||||
const void* bin = nullptr;
|
||||
size_t bin_len = 0;
|
||||
if (Value->IsString())
|
||||
{
|
||||
v8::String::Utf8Value str(Isolate, Value);
|
||||
std::string payload(*str, str.length());
|
||||
Client.send(Handle, payload, websocketpp::frame::opcode::TEXT, ec);
|
||||
}
|
||||
else if (Value->IsArrayBufferView())
|
||||
{
|
||||
v8::Local<v8::ArrayBufferView> BuffView = Value.As<v8::ArrayBufferView>();
|
||||
auto Ab = BuffView->Buffer();
|
||||
bin = static_cast<char*>(DataTransfer::GetArrayBufferData(Ab)) + BuffView->ByteOffset();
|
||||
bin_len = BuffView->ByteLength();
|
||||
}
|
||||
else if (Value->IsArrayBuffer())
|
||||
{
|
||||
auto Ab = v8::Local<v8::ArrayBuffer>::Cast(Value);
|
||||
size_t ByteLength;
|
||||
bin = DataTransfer::GetArrayBufferData(Ab, ByteLength);
|
||||
bin_len = ByteLength;
|
||||
}
|
||||
else
|
||||
{
|
||||
FV8Utils::ThrowException(Isolate, "data must be String/ArrayBuffer/ArrayBufferView");
|
||||
return;
|
||||
}
|
||||
|
||||
if (bin)
|
||||
{
|
||||
Client.send(Handle, bin, bin_len, websocketpp::frame::opcode::BINARY, ec);
|
||||
}
|
||||
|
||||
if (ec)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "could not create connection because: " << ec.message() << std::endl;
|
||||
FV8Utils::ThrowException(Isolate, ss.str().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void V8WebSocketClientImpl::SetHandles(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
for (int i = 0; i < HANDLE_TYPE_END; ++i)
|
||||
{
|
||||
if (Info[i]->IsFunction())
|
||||
{
|
||||
Handles[i].Reset(Isolate, Info[i].As<v8::Function>());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void V8WebSocketClientImpl::Cleanup()
|
||||
{
|
||||
if (!Isolate)
|
||||
{
|
||||
return;
|
||||
}
|
||||
Connenting = false;
|
||||
Handle.reset();
|
||||
|
||||
v8::Isolate::Scope IsolateScope(Isolate);
|
||||
for (int i = 0; i < HANDLE_TYPE_END; ++i)
|
||||
{
|
||||
Handles[i].Reset();
|
||||
}
|
||||
|
||||
// GSelf.Reset();
|
||||
GContext.Reset();
|
||||
Isolate = nullptr;
|
||||
}
|
||||
|
||||
void V8WebSocketClientImpl::Close(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
auto InIsolate = Info.GetIsolate();
|
||||
websocketpp::close::status::value code = websocketpp::close::status::normal;
|
||||
std::string reason = "";
|
||||
if (Info[0]->IsInt32())
|
||||
{
|
||||
code = Info[0]->Int32Value(Info.GetIsolate()->GetCurrentContext()).FromJust();
|
||||
}
|
||||
|
||||
if (Info[1]->IsString())
|
||||
{
|
||||
reason = *v8::String::Utf8Value(InIsolate, Info[1]);
|
||||
}
|
||||
|
||||
Close(code, reason);
|
||||
}
|
||||
|
||||
void V8WebSocketClientImpl::Close(websocketpp::close::status::value const code, std::string const& reason)
|
||||
{
|
||||
if (!Handle.expired())
|
||||
{
|
||||
Client.close(Handle, code, reason);
|
||||
}
|
||||
Cleanup();
|
||||
}
|
||||
|
||||
void V8WebSocketClientImpl::PollOne()
|
||||
{
|
||||
if (Connenting || !Handle.expired())
|
||||
{
|
||||
Client.poll_one();
|
||||
}
|
||||
}
|
||||
|
||||
void V8WebSocketClientImpl::OnOpen(wspp_connection_hdl InHandle)
|
||||
{
|
||||
Handle = InHandle;
|
||||
Connenting = false;
|
||||
|
||||
v8::Isolate::Scope IsolateScope(Isolate);
|
||||
v8::HandleScope HandleScope(Isolate);
|
||||
if (!Handles[ON_OPEN].IsEmpty())
|
||||
{
|
||||
v8::Local<v8::Value> args[1];
|
||||
// must not raise exception in js, recommend just push a pending msg and process later.
|
||||
Handles[ON_OPEN].Get(Isolate)->Call(GContext.Get(Isolate), v8::Undefined(Isolate), 0, args);
|
||||
}
|
||||
}
|
||||
|
||||
void V8WebSocketClientImpl::OnMessage(wspp_connection_hdl InHandle, wspp_message_ptr InMessage)
|
||||
{
|
||||
v8::Isolate::Scope IsolateScope(Isolate);
|
||||
v8::HandleScope HandleScope(Isolate);
|
||||
|
||||
if (!Handles[ON_MESSAGE].IsEmpty())
|
||||
{
|
||||
v8::Local<v8::Value> args[1];
|
||||
if (InMessage->get_opcode() == websocketpp::frame::opcode::TEXT)
|
||||
{
|
||||
args[0] = v8::String::NewFromUtf8(
|
||||
Isolate, InMessage->get_payload().c_str(), v8::NewStringType::kNormal, InMessage->get_payload().size())
|
||||
.ToLocalChecked();
|
||||
}
|
||||
else if (InMessage->get_opcode() == websocketpp::frame::opcode::BINARY)
|
||||
{
|
||||
args[0] = DataTransfer::NewArrayBuffer(
|
||||
GContext.Get(Isolate), (void*) InMessage->get_payload().c_str(), InMessage->get_payload().size());
|
||||
}
|
||||
else
|
||||
{
|
||||
args[0] = v8::Undefined(Isolate);
|
||||
}
|
||||
// must not raise exception in js, recommend just push a pending msg and process later.
|
||||
Handles[ON_MESSAGE].Get(Isolate)->Call(GContext.Get(Isolate), v8::Undefined(Isolate), 1, args);
|
||||
}
|
||||
}
|
||||
|
||||
void V8WebSocketClientImpl::OnClose(wspp_connection_hdl InHandle)
|
||||
{
|
||||
v8::Isolate::Scope IsolateScope(Isolate);
|
||||
v8::HandleScope HandleScope(Isolate);
|
||||
|
||||
if (!Handles[ON_CLOSE].IsEmpty())
|
||||
{
|
||||
wspp_client::connection_ptr con = Client.get_con_from_hdl(InHandle);
|
||||
v8::Local<v8::Value> args[2] = {v8::Integer::New(Isolate, con->get_remote_close_code()),
|
||||
v8::String::NewFromUtf8(
|
||||
Isolate, con->get_remote_close_reason().c_str(), v8::NewStringType::kNormal, con->get_remote_close_reason().size())
|
||||
.ToLocalChecked()};
|
||||
// must not raise exception in js, recommend just push a pending msg and process later.
|
||||
Handles[ON_CLOSE].Get(Isolate)->Call(GContext.Get(Isolate), v8::Undefined(Isolate), 2, args);
|
||||
}
|
||||
Cleanup();
|
||||
}
|
||||
|
||||
void V8WebSocketClientImpl::OnFail(wspp_connection_hdl InHandle)
|
||||
{
|
||||
v8::Isolate::Scope IsolateScope(Isolate);
|
||||
v8::HandleScope HandleScope(Isolate);
|
||||
|
||||
if (!Handles[ON_FAIL].IsEmpty())
|
||||
{
|
||||
wspp_client::connection_ptr con = Client.get_con_from_hdl(InHandle);
|
||||
v8::Local<v8::Value> args[1] = {v8::String::NewFromUtf8(
|
||||
Isolate, con->get_ec().message().c_str(), v8::NewStringType::kNormal, con->get_ec().message().size())
|
||||
.ToLocalChecked()};
|
||||
// must not raise exception in js, recommend just push a pending msg and process later.
|
||||
Handles[ON_FAIL].Get(Isolate)->Call(GContext.Get(Isolate), v8::Undefined(Isolate), 1, args);
|
||||
}
|
||||
Close(websocketpp::close::status::abnormal_close, "");
|
||||
}
|
||||
|
||||
} // namespace PUERTS_NAMESPACE
|
||||
|
||||
void InitWebsocketPPWrap(v8::Local<v8::Context> Context)
|
||||
{
|
||||
auto Isolate = Context->GetIsolate();
|
||||
auto WSTemplate = v8::FunctionTemplate::New(Context->GetIsolate(),
|
||||
[](const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
auto ws =
|
||||
new PUERTS_NAMESPACE::V8WebSocketClientImpl(Info.GetIsolate(), Info.GetIsolate()->GetCurrentContext(), Info.This());
|
||||
Info.This()->SetAlignedPointerInInternalField(0, ws);
|
||||
ws->Connect(Info);
|
||||
});
|
||||
WSTemplate->InstanceTemplate()->SetInternalFieldCount(1);
|
||||
|
||||
WSTemplate->PrototypeTemplate()->Set(v8::String::NewFromUtf8(Isolate, "send").ToLocalChecked(),
|
||||
v8::FunctionTemplate::New(Isolate,
|
||||
[](const v8::FunctionCallbackInfo<v8::Value>& Info) {
|
||||
static_cast<PUERTS_NAMESPACE::V8WebSocketClientImpl*>(Info.Holder()->GetAlignedPointerFromInternalField(0))
|
||||
->Send(Info);
|
||||
}));
|
||||
|
||||
WSTemplate->PrototypeTemplate()->Set(v8::String::NewFromUtf8(Isolate, "setHandles").ToLocalChecked(),
|
||||
v8::FunctionTemplate::New(Isolate,
|
||||
[](const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
static_cast<PUERTS_NAMESPACE::V8WebSocketClientImpl*>(Info.Holder()->GetAlignedPointerFromInternalField(0))
|
||||
->SetHandles(Info);
|
||||
}));
|
||||
|
||||
WSTemplate->PrototypeTemplate()->Set(v8::String::NewFromUtf8(Isolate, "close").ToLocalChecked(),
|
||||
v8::FunctionTemplate::New(Isolate,
|
||||
[](const v8::FunctionCallbackInfo<v8::Value>& Info) {
|
||||
static_cast<PUERTS_NAMESPACE::V8WebSocketClientImpl*>(Info.Holder()->GetAlignedPointerFromInternalField(0))
|
||||
->Close(Info);
|
||||
}));
|
||||
|
||||
WSTemplate->PrototypeTemplate()->Set(v8::String::NewFromUtf8(Isolate, "poll").ToLocalChecked(),
|
||||
v8::FunctionTemplate::New(Isolate,
|
||||
[](const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
v8::TryCatch TryCatch(Info.GetIsolate());
|
||||
static_cast<PUERTS_NAMESPACE::V8WebSocketClientImpl*>(Info.Holder()->GetAlignedPointerFromInternalField(0))
|
||||
->PollOne();
|
||||
}));
|
||||
|
||||
Context->Global()->Set(Context, v8::String::NewFromUtf8(Isolate, "WebSocketPP").ToLocalChecked(),
|
||||
WSTemplate->GetFunction(Context).ToLocalChecked());
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "ArrayBuffer.generated.h"
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FArrayBuffer
|
||||
{
|
||||
public:
|
||||
GENERATED_USTRUCT_BODY()
|
||||
|
||||
public:
|
||||
void* Data;
|
||||
|
||||
size_t Length;
|
||||
|
||||
bool bCopy = false;
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FArrayBufferValue
|
||||
{
|
||||
public:
|
||||
GENERATED_USTRUCT_BODY()
|
||||
|
||||
public:
|
||||
TArray<uint8> Data;
|
||||
};
|
||||
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "PuertsNamespaceDef.h"
|
||||
#include "StaticCall.hpp"
|
||||
#include "ScriptBackend.hpp"
|
||||
#include "Object.hpp"
|
||||
@@ -0,0 +1,370 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if USING_IN_UNREAL_ENGINE
|
||||
#include "CoreMinimal.h"
|
||||
#include "UObject/Package.h"
|
||||
#include "UObject/Class.h"
|
||||
#else
|
||||
#include "JSClassRegister.h"
|
||||
#endif
|
||||
|
||||
#include "NamespaceDef.h"
|
||||
|
||||
PRAGMA_DISABLE_UNDEFINED_IDENTIFIER_WARNINGS
|
||||
#pragma warning(push, 0)
|
||||
#include "v8.h"
|
||||
#pragma warning(pop)
|
||||
PRAGMA_ENABLE_UNDEFINED_IDENTIFIER_WARNINGS
|
||||
|
||||
#if !defined(MAPPER_ISOLATE_DATA_POS)
|
||||
#define MAPPER_ISOLATE_DATA_POS 0
|
||||
#endif
|
||||
|
||||
#ifndef PESAPI_PRIVATE_DATA_POS_IN_ISOLATE
|
||||
#define PESAPI_PRIVATE_DATA_POS_IN_ISOLATE (MAPPER_ISOLATE_DATA_POS + 1)
|
||||
#endif
|
||||
|
||||
#define RELEASED_UOBJECT ((UObject*) 12)
|
||||
#define RELEASED_UOBJECT_MEMBER ((void*) 12)
|
||||
|
||||
namespace PUERTS_NAMESPACE
|
||||
{
|
||||
template <typename T, typename FT, typename = void>
|
||||
struct TOuterLinker
|
||||
{
|
||||
V8_INLINE static void Link(v8::Local<v8::Context> Context, v8::Local<v8::Value> Outer, v8::Local<v8::Value> Inner)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
V8_INLINE void LinkOuterImpl(v8::Local<v8::Context> Context, v8::Local<v8::Value> Outer, v8::Local<v8::Value> Inner)
|
||||
{
|
||||
#ifdef WITH_OUTER_LINK
|
||||
Inner.As<v8::Object>()->Set(Context, 0, Outer);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if USING_IN_UNREAL_ENGINE
|
||||
FORCEINLINE UScriptStruct* GetScriptStructInCoreUObject(const TCHAR* Name)
|
||||
{
|
||||
static UPackage* CoreUObjectPkg = FindObjectChecked<UPackage>(nullptr, TEXT("/Script/CoreUObject"));
|
||||
return FindObjectChecked<UScriptStruct>(CoreUObjectPkg, Name);
|
||||
}
|
||||
|
||||
template <class T, typename Enable = void>
|
||||
struct TScriptStructTraits
|
||||
{
|
||||
};
|
||||
|
||||
template <>
|
||||
struct TScriptStructTraits<FVector>
|
||||
{
|
||||
static UScriptStruct* Get()
|
||||
{
|
||||
return TBaseStructure<FVector>::Get();
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct TScriptStructTraits<FVector2D>
|
||||
{
|
||||
static UScriptStruct* Get()
|
||||
{
|
||||
return TBaseStructure<FVector2D>::Get();
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct TScriptStructTraits<FVector4>
|
||||
{
|
||||
static UScriptStruct* Get()
|
||||
{
|
||||
return TBaseStructure<FVector4>::Get();
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct TScriptStructTraits<FRotator>
|
||||
{
|
||||
static UScriptStruct* Get()
|
||||
{
|
||||
return TBaseStructure<FRotator>::Get();
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct TScriptStructTraits<FQuat>
|
||||
{
|
||||
static UScriptStruct* Get()
|
||||
{
|
||||
return TBaseStructure<FQuat>::Get();
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct TScriptStructTraits<FTransform>
|
||||
{
|
||||
static UScriptStruct* Get()
|
||||
{
|
||||
return TBaseStructure<FTransform>::Get();
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct TScriptStructTraits<FLinearColor>
|
||||
{
|
||||
static UScriptStruct* Get()
|
||||
{
|
||||
return TBaseStructure<FLinearColor>::Get();
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct TScriptStructTraits<FColor>
|
||||
{
|
||||
static UScriptStruct* Get()
|
||||
{
|
||||
return TBaseStructure<FColor>::Get();
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct TScriptStructTraits<FGuid>
|
||||
{
|
||||
static UScriptStruct* Get()
|
||||
{
|
||||
return TBaseStructure<FGuid>::Get();
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct TScriptStructTraits<FBox2D>
|
||||
{
|
||||
static UScriptStruct* Get()
|
||||
{
|
||||
return TBaseStructure<FBox2D>::Get();
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct TScriptStructTraits<FIntPoint>
|
||||
{
|
||||
static UScriptStruct* Get()
|
||||
{
|
||||
return GetScriptStructInCoreUObject(TEXT("IntPoint"));
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct TScriptStructTraits<FIntVector>
|
||||
{
|
||||
static UScriptStruct* Get()
|
||||
{
|
||||
return GetScriptStructInCoreUObject(TEXT("IntVector"));
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct TScriptStructTraits<FPlane>
|
||||
{
|
||||
static UScriptStruct* Get()
|
||||
{
|
||||
return GetScriptStructInCoreUObject(TEXT("Plane"));
|
||||
}
|
||||
};
|
||||
|
||||
template <class...>
|
||||
using ToVoid = void;
|
||||
|
||||
template <typename T, typename = void>
|
||||
struct HasStaticStructHelper : std::false_type
|
||||
{
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct HasStaticStructHelper<T, ToVoid<decltype(&T::StaticStruct)>> : std::true_type
|
||||
{
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct TScriptStructTraits<T, typename std::enable_if<HasStaticStructHelper<T>::value>::type>
|
||||
{
|
||||
static UScriptStruct* Get()
|
||||
{
|
||||
return T::StaticStruct();
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename FT>
|
||||
struct TOuterLinker<T, FT, ToVoid<decltype(&TScriptStructTraits<FT>::Get)>>
|
||||
{
|
||||
V8_INLINE static void Link(v8::Local<v8::Context> Context, v8::Local<v8::Value> Outer, v8::Local<v8::Value> Inner)
|
||||
{
|
||||
LinkOuterImpl(Context, Outer, Inner);
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
class JSENV_API DataTransfer
|
||||
{
|
||||
public:
|
||||
FORCEINLINE static void* MakeAddressWithHighPartOfTwo(void* Address1, void* Address2)
|
||||
{
|
||||
UPTRINT High = reinterpret_cast<UPTRINT>(Address1) & (((UPTRINT) -1) << (sizeof(UPTRINT) / 2)); //清除低位
|
||||
UPTRINT Low = (reinterpret_cast<UPTRINT>(Address2) >> (sizeof(UPTRINT) / 2)) &
|
||||
~(((UPTRINT) -1) << (sizeof(UPTRINT) / 2)); //右移,然后清除高位
|
||||
return reinterpret_cast<void*>(High | Low);
|
||||
}
|
||||
|
||||
FORCEINLINE static void SplitAddressToHighPartOfTwo(const void* Address, UPTRINT& High, UPTRINT& Low)
|
||||
{
|
||||
High = reinterpret_cast<UPTRINT>(Address) & (((UPTRINT) -1) << (sizeof(UPTRINT) / 2)); //清除低位
|
||||
Low = reinterpret_cast<UPTRINT>(Address) << (sizeof(UPTRINT) / 2);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
FORCEINLINE static T* GetPointerFast(v8::Local<v8::Object> Object, int Index)
|
||||
{
|
||||
int P1 = Index << 1;
|
||||
int P2 = P1 + 1;
|
||||
if (V8_LIKELY(Object->InternalFieldCount() > P2))
|
||||
{
|
||||
return static_cast<T*>(MakeAddressWithHighPartOfTwo(
|
||||
Object->GetAlignedPointerFromInternalField(P1), Object->GetAlignedPointerFromInternalField(P2)));
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
FORCEINLINE static T* GetPointerFast(v8::Local<v8::Object> Object)
|
||||
{
|
||||
if (V8_LIKELY(Object->InternalFieldCount() > 1))
|
||||
{
|
||||
return static_cast<T*>(MakeAddressWithHighPartOfTwo(
|
||||
Object->GetAlignedPointerFromInternalField(0), Object->GetAlignedPointerFromInternalField(1)));
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//替代 Object->SetAlignedPointerInInternalField(Index, Ptr);
|
||||
FORCEINLINE static void SetPointer(v8::Isolate* Isolate, v8::Local<v8::Object> Object, const void* Ptr, int Index)
|
||||
{
|
||||
// Object->SetInternalField(Index, v8::External::New(Isolate, Ptr));
|
||||
// Object->SetAlignedPointerInInternalField(Index, Ptr);
|
||||
UPTRINT High;
|
||||
UPTRINT Low;
|
||||
SplitAddressToHighPartOfTwo(Ptr, High, Low);
|
||||
Object->SetAlignedPointerInInternalField(Index * 2, reinterpret_cast<void*>(High));
|
||||
Object->SetAlignedPointerInInternalField(Index * 2 + 1, reinterpret_cast<void*>(Low));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
FORCEINLINE static T* IsolateData(v8::Isolate* Isolate)
|
||||
{
|
||||
return static_cast<T*>(Isolate->GetData(MAPPER_ISOLATE_DATA_POS));
|
||||
}
|
||||
|
||||
FORCEINLINE static void* GetIsolatePrivateData(v8::Isolate* Isolate)
|
||||
{
|
||||
return Isolate->GetData(PESAPI_PRIVATE_DATA_POS_IN_ISOLATE);
|
||||
}
|
||||
|
||||
FORCEINLINE static void SetIsolatePrivateData(v8::Isolate* Isolate, void* PrivateData)
|
||||
{
|
||||
Isolate->SetData(PESAPI_PRIVATE_DATA_POS_IN_ISOLATE, PrivateData);
|
||||
}
|
||||
|
||||
static v8::Local<v8::Value> FindOrAddCData(
|
||||
v8::Isolate* Isolate, v8::Local<v8::Context> Context, const void* TypeId, const void* Ptr, bool PassByPointer);
|
||||
|
||||
static bool IsInstanceOf(v8::Isolate* Isolate, const void* TypeId, v8::Local<v8::Object> JsObject);
|
||||
|
||||
static v8::Local<v8::Value> UnRef(v8::Isolate* Isolate, const v8::Local<v8::Value>& Value);
|
||||
|
||||
static void UpdateRef(v8::Isolate* Isolate, v8::Local<v8::Value> Outer, const v8::Local<v8::Value>& Value);
|
||||
|
||||
static std::weak_ptr<int> GetJsEnvLifeCycleTracker(v8::Isolate* Isolate);
|
||||
|
||||
#if USING_IN_UNREAL_ENGINE
|
||||
template <typename T>
|
||||
static v8::Local<v8::Value> FindOrAddObject(v8::Isolate* Isolate, v8::Local<v8::Context>& Context, T* UEObject)
|
||||
{
|
||||
return FindOrAddObject(Isolate, Context, UEObject == nullptr ? T::StaticClass() : UEObject->GetClass(), UEObject);
|
||||
}
|
||||
|
||||
static v8::Local<v8::Value> FindOrAddObject(
|
||||
v8::Isolate* Isolate, v8::Local<v8::Context>& Context, UClass* Class, UObject* UEObject);
|
||||
|
||||
template <typename T>
|
||||
static v8::Local<v8::Value> FindOrAddStruct(v8::Isolate* Isolate, v8::Local<v8::Context> Context, void* Ptr, bool PassByPointer)
|
||||
{
|
||||
return FindOrAddStruct(Isolate, Context, TScriptStructTraits<T>::Get(), Ptr, PassByPointer);
|
||||
}
|
||||
|
||||
static v8::Local<v8::Value> FindOrAddStruct(
|
||||
v8::Isolate* Isolate, v8::Local<v8::Context> Context, UScriptStruct* ScriptStruct, void* Ptr, bool PassByPointer);
|
||||
|
||||
template <typename T>
|
||||
static bool IsInstanceOf(v8::Isolate* Isolate, v8::Local<v8::Object> JsObject)
|
||||
{
|
||||
return IsInstanceOf(Isolate, TScriptStructTraits<T>::Get(), JsObject);
|
||||
}
|
||||
|
||||
static bool IsInstanceOf(v8::Isolate* Isolate, UStruct* Struct, v8::Local<v8::Object> JsObject);
|
||||
|
||||
static FString ToFString(v8::Isolate* Isolate, v8::Local<v8::Value> Value);
|
||||
|
||||
static void ThrowException(v8::Isolate* Isolate, const char* Message);
|
||||
#endif
|
||||
|
||||
template <typename T1, typename T2>
|
||||
FORCEINLINE static void LinkOuter(v8::Local<v8::Context> Context, v8::Local<v8::Value> Outer, v8::Local<v8::Value> Inner)
|
||||
{
|
||||
TOuterLinker<T1, T2>::Link(Context, Outer, Inner);
|
||||
}
|
||||
|
||||
FORCEINLINE static v8::Local<v8::ArrayBuffer> NewArrayBuffer(v8::Local<v8::Context> Context, void* Data, size_t DataLength)
|
||||
{
|
||||
#if defined(HAS_ARRAYBUFFER_NEW_WITHOUT_STL)
|
||||
return v8::ArrayBuffer_New_Without_Stl(Context->GetIsolate(), Data, DataLength);
|
||||
#else
|
||||
#if USING_IN_UNREAL_ENGINE
|
||||
return v8::ArrayBuffer::New(Context->GetIsolate(), Data, DataLength);
|
||||
#else
|
||||
auto Backing = v8::ArrayBuffer::NewBackingStore(Data, DataLength, v8::BackingStore::EmptyDeleter, nullptr);
|
||||
return v8::ArrayBuffer::New(Context->GetIsolate(), std::move(Backing));
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
FORCEINLINE static void* GetArrayBufferData(v8::Local<v8::ArrayBuffer> InArrayBuffer)
|
||||
{
|
||||
size_t DataLength;
|
||||
return GetArrayBufferData(InArrayBuffer, DataLength);
|
||||
}
|
||||
|
||||
FORCEINLINE static void* GetArrayBufferData(v8::Local<v8::ArrayBuffer> InArrayBuffer, size_t& DataLength)
|
||||
{
|
||||
#if defined(HAS_ARRAYBUFFER_NEW_WITHOUT_STL)
|
||||
return v8::ArrayBuffer_Get_Data(InArrayBuffer, DataLength);
|
||||
#else
|
||||
#if USING_IN_UNREAL_ENGINE
|
||||
DataLength = InArrayBuffer->GetContents().ByteLength();
|
||||
return InArrayBuffer->GetContents().Data();
|
||||
#else
|
||||
auto BS = InArrayBuffer->GetBackingStore();
|
||||
DataLength = BS->ByteLength();
|
||||
return BS->Data();
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
};
|
||||
} // namespace PUERTS_NAMESPACE
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "NamespaceDef.h"
|
||||
|
||||
#include "CoreUObject.h"
|
||||
|
||||
PRAGMA_DISABLE_UNDEFINED_IDENTIFIER_WARNINGS
|
||||
#pragma warning(push, 0)
|
||||
#include "v8.h"
|
||||
#pragma warning(pop)
|
||||
PRAGMA_ENABLE_UNDEFINED_IDENTIFIER_WARNINGS
|
||||
|
||||
class UDynamicDelegateProxy;
|
||||
class UJSGeneratedFunction;
|
||||
namespace PUERTS_NAMESPACE
|
||||
{
|
||||
class IDynamicInvoker
|
||||
{
|
||||
public:
|
||||
virtual void InvokeDelegateCallback(UDynamicDelegateProxy* Proxy, void* Params) = 0;
|
||||
|
||||
#if !defined(ENGINE_INDEPENDENT_JSENV)
|
||||
virtual void JsConstruct(UClass* Class, UObject* Object, const v8::UniquePersistent<v8::Function>& Constructor,
|
||||
const v8::UniquePersistent<v8::Object>& Prototype) = 0;
|
||||
|
||||
virtual void InvokeJsMethod(UObject* ContextObject, UJSGeneratedFunction* Function, FFrame& Stack, void* RESULT_PARAM) = 0;
|
||||
|
||||
virtual void InvokeMixinMethod(UObject* ContextObject, UJSGeneratedFunction* Function, FFrame& Stack, void* RESULT_PARAM) = 0;
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace PUERTS_NAMESPACE
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user