interop tests

This commit is contained in:
2025-12-09 21:57:25 +02:00
parent 5af8610c0c
commit 43e1acacce
6 changed files with 760 additions and 0 deletions

View File

@@ -0,0 +1,32 @@
{
"ID": "2a86c77242441f5ac25b4a8bbf4029a8",
"TypeName": "FlaxEngine.SceneAsset",
"EngineBuild": 6804,
"Data": [
{
"ID": "2a86c77242441f5ac25b4a8bbf4029a8",
"TypeName": "FlaxEngine.Scene",
"LightmapSettings": {
"IndirectLightingIntensity": 1.0,
"GlobalObjectsScale": 1.0,
"ChartsPadding": 3,
"AtlasSize": 1024,
"BounceCount": 1,
"CompressLightmaps": true,
"UseGeometryWithNoMaterials": true,
"Quality": 10
}
},
{
"ID": "5b51518c45ce815817a6f1978fec4699",
"TypeName": "Game.MyScript",
"ParentID": "2a86c77242441f5ac25b4a8bbf4029a8"
},
{
"ID": "efa3263d4596af098d5babb8fd6ea6fb",
"TypeName": "Game.MyScriptTwo",
"ParentID": "2a86c77242441f5ac25b4a8bbf4029a8",
"V": {}
}
]
}

View File

@@ -3,6 +3,8 @@ using FlaxEngine;
using Console = Game.Console;
using System.Linq;
using System.Threading;
using FlaxEngine.Json;
#if FLAX_EDITOR
using FlaxEditor;
@@ -137,6 +139,9 @@ public class ConsoleEditorPlugin : EditorPlugin
private void OnPlayModeBegin()
{
if (!Level.Scenes.Any(x => x.ID == JsonSerializer.ParseID("194e05f445ece24ec5448d886e1334df"))) // MainScene
return;
//FlaxEditor.Editor.Instance.PlayModeBegin -= Instance_PlayModeBegin;
LoadConfig();
//GameMode.Connect();

553
Source/Game/MyScript.cpp Normal file
View File

@@ -0,0 +1,553 @@
#include "MyScript.h"
#include "Engine/Level/Actor.h"
#include "Engine/Core/Log.h"
#include "Engine/Renderer/RenderList.h"
#include "Engine/Scripting/ManagedCLR/MUtils.h"
#include "Engine/Scripting/ManagedCLR/MCore.h"
#include "Engine/Scripting/ManagedCLR/MClass.h"
#include "Engine/Scripting/ManagedCLR/MEvent.h"
#include "Engine/Scripting/ManagedCLR/MMethod.h"
#include "Engine/Level/Scene/Scene.h"
#include "Engine/Core/Collections/Sorting.h"
#define NEW_VERSION 1
#if BUILD_DEBUG
#define LONGER 1
#define CHUNK_TIMES 10
#else
#define LONGER 10
#define CHUNK_TIMES 1000
#endif
#define TIMES (10000*LONGER)
#define TIMES2 (1000*LONGER)
#define TIMES3 (100*LONGER)
#define TIMES4 (10*LONGER)
#define TIMES5 (1*LONGER)
MyScript2::MyScript2(const SpawnParams& params)
: Script(params)
{
// _tickUpdate = true;
}
MyScript::MyScript(const SpawnParams& params)
: Script(params)
{
// _tickUpdate = true;
}
#define BENCHMARK_CALL_ARGS0(REPEAT, FUNC) \
{ \
LOG(Info, #FUNC); \
const auto times = REPEAT; \
const auto chunkTimes = CHUNK_TIMES; \
const auto freq = Platform::GetClockFrequency(); \
results.Clear(); \
auto start2 = Platform::GetTimeCycles(); \
for (int i = 0; i < times; ++i) \
{ \
auto start = Platform::GetTimeCycles(); \
for (int j = 0; j < chunkTimes; ++j) \
scriptTwo->FUNC(); \
auto end = Platform::GetTimeCycles(); \
auto elapsed = end - start; \
results.Add(elapsed); \
} \
auto end2 = Platform::GetTimeCycles(); \
auto elapsed2 = end2 - start2; \
Sorting::MergeSort(results); \
const auto resultsIndex = 0; \
LOG(Info, " - VirtualCall: {:.1f}ns ({:.0f}ms total {} times)", (results[resultsIndex] * (1.0 / static_cast<double>(freq)) * 1000000000 / chunkTimes), (elapsed2 * (1.0 / static_cast<double>(freq)) * 1000), times*chunkTimes); \
}
#define BENCHMARK_CALL_ARGS1(REPEAT, FUNC, PARAM1) \
{ \
LOG(Info, #FUNC); \
const auto times = REPEAT; \
const auto chunkTimes = CHUNK_TIMES; \
const auto freq = Platform::GetClockFrequency(); \
results.Clear(); \
auto start2 = Platform::GetTimeCycles(); \
for (int i = 0; i < times; ++i) \
{ \
auto start = Platform::GetTimeCycles(); \
for (int j = 0; j < chunkTimes; ++j) \
scriptTwo->FUNC(PARAM1); \
auto end = Platform::GetTimeCycles(); \
auto elapsed = end - start; \
results.Add(elapsed); \
} \
auto end2 = Platform::GetTimeCycles(); \
auto elapsed2 = end2 - start2; \
Sorting::MergeSort(results); \
const auto resultsIndex = 0; \
LOG(Info, " - VirtualCall: {:.1f}ns ({:.0f}ms total {} times)", (results[resultsIndex] * (1.0 / static_cast<double>(freq)) * 1000000000 / chunkTimes), (elapsed2 * (1.0 / static_cast<double>(freq)) * 1000), times*chunkTimes); \
}
#define BENCHMARK_CALL_ARGS1_REF(REPEAT, FUNC, PARAM1) \
{ \
LOG(Info, #FUNC); \
const auto times = REPEAT; \
const auto chunkTimes = CHUNK_TIMES; \
const auto freq = Platform::GetClockFrequency(); \
results.Clear(); \
auto start2 = Platform::GetTimeCycles(); \
for (int i = 0; i < times; ++i) \
{ \
auto start = Platform::GetTimeCycles(); \
for (int j = 0; j < chunkTimes; ++j) \
{ \
auto _param1_orig_value = PARAM1; \
scriptTwo->FUNC(_param1_orig_value); \
} \
auto end = Platform::GetTimeCycles(); \
auto elapsed = end - start; \
results.Add(elapsed); \
} \
auto end2 = Platform::GetTimeCycles(); \
auto elapsed2 = end2 - start2; \
Sorting::MergeSort(results); \
const auto resultsIndex = 0; \
LOG(Info, " - VirtualCall: {:.1f}ns ({:.0f}ms total {} times)", (results[resultsIndex] * (1.0 / static_cast<double>(freq)) * 1000000000 / chunkTimes), (elapsed2 * (1.0 / static_cast<double>(freq)) * 1000), times*chunkTimes); \
}
#define BENCHMARK_CALL_ARGS5(REPEAT, FUNC, PARAM1, PARAM2, PARAM3, PARAM4, PARAM5) \
{ \
LOG(Info, #FUNC); \
const auto times = REPEAT; \
const auto chunkTimes = CHUNK_TIMES; \
const auto freq = Platform::GetClockFrequency(); \
results.Clear(); \
auto start2 = Platform::GetTimeCycles(); \
for (int i = 0; i < times; ++i) \
{ \
auto start = Platform::GetTimeCycles(); \
for (int j = 0; j < chunkTimes; ++j) \
scriptTwo->FUNC(PARAM1, PARAM2, PARAM3, PARAM4, PARAM5); \
auto end = Platform::GetTimeCycles(); \
auto elapsed = end - start; \
results.Add(elapsed); \
} \
auto end2 = Platform::GetTimeCycles(); \
auto elapsed2 = end2 - start2; \
Sorting::MergeSort(results); \
const auto resultsIndex = 0; \
LOG(Info, " - VirtualCall: {:.1f}ns ({:.0f}ms total {} times)", (results[resultsIndex] * (1.0 / static_cast<double>(freq)) * 1000000000 / chunkTimes), (elapsed2 * (1.0 / static_cast<double>(freq)) * 1000), times*chunkTimes); \
}
#define BENCHMARK_THUNK_BEGIN_ARGS0(REPEAT, FUNC) \
{ \
const auto times = REPEAT; \
const auto chunkTimes = CHUNK_TIMES; \
typedef void (*Thunk)(void* instance, MObject** exception); \
const auto thunk = (Thunk)scriptTwo->GetClass()->GetMethod(#FUNC, 0)->GetThunk(); \
const auto instance = scriptTwo->GetOrCreateManagedInstance(); \
MObject* exception = nullptr;
#define BENCHMARK_THUNK_CALL_ARGS0() \
const auto freq = Platform::GetClockFrequency(); \
results.Clear(); \
auto start2 = Platform::GetTimeCycles(); \
for (int i = 0; i < times; ++i) \
{ \
auto start = Platform::GetTimeCycles(); \
for (int j = 0; j < chunkTimes; ++j) \
thunk(instance, &exception); \
auto end = Platform::GetTimeCycles(); \
auto elapsed = end - start; \
results.Add(elapsed); \
} \
auto end2 = Platform::GetTimeCycles(); \
auto elapsed2 = end2 - start2; \
Sorting::MergeSort(results); \
const auto resultsIndex = 0; \
LOG(Info, " - InvokeThunkOnly: {:.1f}ns ({:.0f}ms total {} times)", (results[resultsIndex] * (1.0 / static_cast<double>(freq)) * 1000000000 / chunkTimes), (elapsed2 * (1.0 / static_cast<double>(freq)) * 1000), times*chunkTimes);
#define BENCHMARK_THUNK_BEGIN_ARGS1(REPEAT, FUNC) \
{ \
const auto times = REPEAT; \
const auto chunkTimes = CHUNK_TIMES; \
typedef void (*Thunk)(void* instance, void*, MObject** exception); \
const auto thunk = (Thunk)scriptTwo->GetClass()->GetMethod(#FUNC, 1)->GetThunk(); \
const auto instance = scriptTwo->GetOrCreateManagedInstance(); \
MObject* exception = nullptr; \
void* params[1];
#define BENCHMARK_THUNK_CALL_ARGS1() \
const auto freq = Platform::GetClockFrequency(); \
results.Clear(); \
auto start2 = Platform::GetTimeCycles(); \
for (int i = 0; i < times; ++i) \
{ \
auto start = Platform::GetTimeCycles(); \
for (int j = 0; j < chunkTimes; ++j) \
thunk(instance, params[0], &exception); \
auto end = Platform::GetTimeCycles(); \
auto elapsed = end - start; \
results.Add(elapsed); \
} \
auto end2 = Platform::GetTimeCycles(); \
auto elapsed2 = end2 - start2; \
Sorting::MergeSort(results); \
const auto resultsIndex = 0; \
LOG(Info, " - InvokeThunkOnly: {:.1f}ns ({:.0f}ms total {} times)", (results[resultsIndex] * (1.0 / static_cast<double>(freq)) * 1000000000 / chunkTimes), (elapsed2 * (1.0 / static_cast<double>(freq)) * 1000), times*chunkTimes);
#define BENCHMARK_THUNK_CALL_ARGS1_REF(FUN) \
const auto freq = Platform::GetClockFrequency(); \
results.Clear(); \
auto start2 = Platform::GetTimeCycles(); \
for (int i = 0; i < times; ++i) \
{ \
auto start = Platform::GetTimeCycles(); \
for (int j = 0; j < chunkTimes; ++j) \
{ \
thunk(instance, params[0], &exception); \
FUN \
} \
auto end = Platform::GetTimeCycles(); \
auto elapsed = end - start; \
results.Add(elapsed); \
} \
auto end2 = Platform::GetTimeCycles(); \
auto elapsed2 = end2 - start2; \
Sorting::MergeSort(results); \
const auto resultsIndex = 0; \
LOG(Info, " - InvokeThunkOnly: {:.1f}ns ({:.0f}ms total {} times)", (results[resultsIndex] * (1.0 / static_cast<double>(freq)) * 1000000000 / chunkTimes), (elapsed2 * (1.0 / static_cast<double>(freq)) * 1000), times*chunkTimes);
#define BENCHMARK_THUNK_BEGIN_ARGS5(REPEAT, FUNC) \
{ \
const auto times = REPEAT; \
const auto chunkTimes = CHUNK_TIMES; \
typedef void (*Thunk)(void* instance, void*, void*, void*, void*, void*, MObject** exception); \
const auto thunk = (Thunk)scriptTwo->GetClass()->GetMethod(#FUNC, 5)->GetThunk(); \
const auto instance = scriptTwo->GetOrCreateManagedInstance(); \
MObject* exception = nullptr; \
void* params[5];
#define BENCHMARK_THUNK_CALL_ARGS5() \
const auto freq = Platform::GetClockFrequency(); \
results.Clear(); \
auto start2 = Platform::GetTimeCycles(); \
for (int i = 0; i < times; ++i) \
{ \
auto start = Platform::GetTimeCycles(); \
for (int j = 0; j < chunkTimes; ++j) \
thunk(instance, params[0], params[1], params[2], params[3], params[4], &exception); \
auto end = Platform::GetTimeCycles(); \
auto elapsed = end - start; \
results.Add(elapsed); \
} \
auto end2 = Platform::GetTimeCycles(); \
auto elapsed2 = end2 - start2; \
Sorting::MergeSort(results); \
const auto resultsIndex = 0; \
LOG(Info, " - InvokeThunkOnly: {:.1f}ns ({:.0f}ms total {} times)", (results[resultsIndex] * (1.0 / static_cast<double>(freq)) * 1000000000 / chunkTimes), (elapsed2 * (1.0 / static_cast<double>(freq)) * 1000), times*chunkTimes);
#define BENCHMARK_THUNK_END() \
}
void MyScript::OnStart()
{
LOG(Info, "C++ OnStart");
MyScript2* scriptTwo = (MyScript2*)GetActor()->GetScript(1);
if (scriptTwo == nullptr)
return;
bool otherTests = true;
bool arrayTests = true;
bool asRefTests = true;
Array<uint64> results(TIMES);
auto CyclesToSeconds = 1.0 / static_cast<double>(Platform::GetClockFrequency());
LOG(Info, "CyclesToSeconds: {}, freq: {}", CyclesToSeconds, Platform::GetClockFrequency());
String shortString = TEXT("Testing string parameter marshalling");
StringAnsi shortStringAnsi = "Testing string parameter marshalling";
Actor* actor = GetActor();
SceneReference sceneRef; sceneRef.ID = actor->GetScene()->GetID();
BehaviorUpdateContext behaviorUpdateContext = {};
RenderContext renderContext = MainRenderTask::Instance;
renderContext.List = RenderList::GetFromPool();
Array<int> simpleArray; for (int i=0; i<10; i++) simpleArray.Add(i);
Array<Actor*> actorArray; for (int i=0; i<10; i++) actorArray.Add(actor);
TestStruct testStruct; testStruct.Object = actor; testStruct.SceneRef = sceneRef;
Array<TestStruct> complexArray; for (int i=0; i<10; i++) complexArray.Add(testStruct);
if (otherTests)
{
BENCHMARK_CALL_ARGS0(TIMES2, SimpleCall);
BENCHMARK_THUNK_BEGIN_ARGS0(TIMES2, SimpleCall);
BENCHMARK_THUNK_CALL_ARGS0();
BENCHMARK_THUNK_END();
}
if (otherTests)
{
BENCHMARK_CALL_ARGS5(TIMES4, SimpleParams, 1, 2, '3', 4, 5);
BENCHMARK_THUNK_BEGIN_ARGS5(TIMES3, SimpleParams);
params[0] = MUtils::Box<int>(1, MCore::TypeCache::Int32);
params[1] = MUtils::Box<float>(2, MCore::TypeCache::Single);
params[2] = MUtils::Box<char>('3', MCore::TypeCache::SByte);
params[3] = MUtils::Box<double>(4, MCore::TypeCache::Double);
params[4] = MUtils::Box<long>(5, MCore::TypeCache::Int64);
BENCHMARK_THUNK_CALL_ARGS5();
#if NEW_VERSION
auto __param0_handle = *(MGCHandle*)&params[0];
MCore::GCHandle::Free(__param0_handle);
auto __param1_handle = *(MGCHandle*)&params[1];
MCore::GCHandle::Free(__param1_handle);
auto __param2_handle = *(MGCHandle*)&params[2];
MCore::GCHandle::Free(__param2_handle);
auto __param3_handle = *(MGCHandle*)&params[3];
MCore::GCHandle::Free(__param3_handle);
auto __param4_handle = *(MGCHandle*)&params[4];
MCore::GCHandle::Free(__param4_handle);
#endif
BENCHMARK_THUNK_END();
}
if (otherTests)
{
BENCHMARK_CALL_ARGS1(TIMES3, StringParamAnsi, shortStringAnsi);
BENCHMARK_THUNK_BEGIN_ARGS1(TIMES2, StringParamAnsi);
params[0] = MUtils::Box<StringAnsi>(shortStringAnsi, MCore::TypeCache::String);
BENCHMARK_THUNK_CALL_ARGS1();
#if NEW_VERSION
auto __param0_handle = *(MGCHandle*)&params[0];
MCore::GCHandle::Free(__param0_handle);
#endif
BENCHMARK_THUNK_END();
}
if (otherTests)
{
BENCHMARK_CALL_ARGS1(TIMES3, StringParam, shortString);
BENCHMARK_THUNK_BEGIN_ARGS1(TIMES2, StringParam);
params[0] = MUtils::Box<String>(shortString, MCore::TypeCache::String);
BENCHMARK_THUNK_CALL_ARGS1();
#if NEW_VERSION
auto __param0_handle = *(MGCHandle*)&params[0];
MCore::GCHandle::Free(__param0_handle);
#endif
BENCHMARK_THUNK_END();
}
if (otherTests)
{
BENCHMARK_CALL_ARGS1(TIMES3, StringParamRef, shortString);
BENCHMARK_THUNK_BEGIN_ARGS1(TIMES2, StringParamRef);
params[0] = MUtils::Box<String>(shortString, MCore::TypeCache::String);
BENCHMARK_THUNK_CALL_ARGS1();
#if NEW_VERSION
auto __param0_handle = *(MGCHandle*)&params[0];
MCore::GCHandle::Free(__param0_handle);
#endif
BENCHMARK_THUNK_END();
}
if (otherTests)
{
BENCHMARK_CALL_ARGS1(TIMES3, StringParamRefConst, shortString);
BENCHMARK_THUNK_BEGIN_ARGS1(TIMES2, StringParamRefConst);
params[0] = MUtils::Box<String>(shortString, MCore::TypeCache::String);
BENCHMARK_THUNK_CALL_ARGS1();
#if NEW_VERSION
auto __param0_handle = *(MGCHandle*)&params[0];
MCore::GCHandle::Free(__param0_handle);
#endif
BENCHMARK_THUNK_END();
}
if (asRefTests)
{
String str = shortString;
BENCHMARK_CALL_ARGS1_REF(TIMES3, StringParamAsRef, str);
LOG(Info, " - InvokeThunkOnly: not valid");
/* str = shortString;
BENCHMARK_THUNK_BEGIN_ARGS1(TIMES3, StringParamAsRef);
#if NEW_VERSION
auto __param_orig_str = MUtils::Box<String>(str, MCore::TypeCache::String);
auto __param_str = __param_orig_str;
params[0] = &__param_str;
#else
auto __param_str = MUtils::Box<String>(str, MCore::TypeCache::String);
params[0] = &__param_str;
#endif
BENCHMARK_THUNK_CALL_ARGS1_REF({ params[0] = &__param_str; });
str = MUtils::Unbox<String>(*(MObject**)params[0]);
ASSERT(str == shortString);
#if NEW_VERSION
MUtils::FreeManaged<String>((MObject*)__param_str);
if (__param_orig_str != __param_str)
MUtils::FreeManaged<String>((MObject*)__param_orig_str);
#endif
BENCHMARK_THUNK_END();*/
}
if (otherTests)
{
BENCHMARK_CALL_ARGS1(TIMES2, ActorParam, actor);
BENCHMARK_THUNK_BEGIN_ARGS1(TIMES2, ActorParam);
params[0] = ScriptingObject::ToManaged((ScriptingObject*)actor);
BENCHMARK_THUNK_CALL_ARGS1();
BENCHMARK_THUNK_END();
}
if (otherTests)
{
BENCHMARK_CALL_ARGS1(TIMES3, ComplexParam, behaviorUpdateContext);
BENCHMARK_THUNK_BEGIN_ARGS1(TIMES2, ComplexParam);
params[0] = MUtils::Box<BehaviorUpdateContext>(behaviorUpdateContext, BehaviorUpdateContext::TypeInitializer.GetClass());
BENCHMARK_THUNK_CALL_ARGS1();
#if NEW_VERSION
MUtils::FreeManaged<BehaviorUpdateContext>((MObject*)params[0]);
#endif
BENCHMARK_THUNK_END();
}
if (otherTests)
{
BENCHMARK_CALL_ARGS1(TIMES4, Complex2Param, renderContext);
BENCHMARK_THUNK_BEGIN_ARGS1(TIMES3, Complex2Param);
params[0] = MUtils::Box<RenderContext>(renderContext, RenderContext::TypeInitializer.GetClass());
BENCHMARK_THUNK_CALL_ARGS1();
#if NEW_VERSION
MUtils::FreeManaged<RenderContext>((MObject*)params[0]);
#endif
BENCHMARK_THUNK_END();
}
if (otherTests)
{
BENCHMARK_CALL_ARGS1(TIMES4, Complex2ParamConst, renderContext);
BENCHMARK_THUNK_BEGIN_ARGS1(TIMES3, Complex2ParamConst);
params[0] = MUtils::Box<RenderContext>(renderContext, RenderContext::TypeInitializer.GetClass());
BENCHMARK_THUNK_CALL_ARGS1();
#if NEW_VERSION
MUtils::FreeManaged<RenderContext>((MObject*)params[0]);
#endif
BENCHMARK_THUNK_END();
}
if (asRefTests)
{
RenderContext context = renderContext;
BENCHMARK_CALL_ARGS1_REF(TIMES4, Complex2ParamAsRef, context);
LOG(Info, " - InvokeThunkOnly: not valid");
/* context = renderContext;
BENCHMARK_THUNK_BEGIN_ARGS1(TIMES3, Complex2ParamAsRef);
#if NEW_VERSION
auto __param_orig_context = MUtils::Box<RenderContext>(context, RenderContext::TypeInitializer.GetClass());
auto __param_context = __param_orig_context;
params[0] = &__param_context;
#else
auto __param_context = MUtils::Box<RenderContext>(context, RenderContext::TypeInitializer.GetClass());
params[0] = &__param_context;
#endif
BENCHMARK_THUNK_CALL_ARGS1_REF({ if (__param_orig_context != __param_context) MUtils::FreeManaged<RenderContext>((MObject*)__param_orig_context); params[0] = &__param_context; });
context = MUtils::Unbox<RenderContext>(*(MObject**)params[0]);
ASSERT(context.Buffers == renderContext.Buffers);
ASSERT(context.Task == renderContext.Task);
#if NEW_VERSION
MUtils::FreeManaged<RenderContext>((MObject*)__param_context);
if (__param_orig_context != __param_context)
MUtils::FreeManaged<RenderContext>((MObject*)__param_orig_context);
#endif
BENCHMARK_THUNK_END();*/
}
if (arrayTests)
{
BENCHMARK_CALL_ARGS1(TIMES4, SimpleArrayParam, simpleArray);
BENCHMARK_THUNK_BEGIN_ARGS1(TIMES3, SimpleArrayParam);
params[0] = MUtils::ToArray(simpleArray, MCore::TypeCache::Int32);
BENCHMARK_THUNK_CALL_ARGS1();
#if NEW_VERSION
//TODO
#endif
BENCHMARK_THUNK_END();
}
if (arrayTests && asRefTests)
{
Array<int> arr = simpleArray;
BENCHMARK_CALL_ARGS1_REF(TIMES4, SimpleArrayParamAsRef, simpleArray);
LOG(Info, " - InvokeThunkOnly: not valid");
/* arr = simpleArray;
BENCHMARK_THUNK_BEGIN_ARGS1(TIMES3, SimpleArrayParamAsRef);
#if NEW_VERSION
auto __param_orig_arr = MUtils::ToArray(arr, MCore::TypeCache::Int32);
auto __param_arr = __param_orig_arr;
params[0] = &__param_arr;
#else
auto __param_arr = MUtils::ToArray(arr, MCore::TypeCache::Int32);
params[0] = &__param_arr;
#endif
BENCHMARK_THUNK_CALL_ARGS1();
arr = MUtils::Unbox<Array<int>>(*(MObject**)params[0]);
ASSERT(arr.Count() == simpleArray.Count());
for (int i=0; i<arr.Count(); i++) ASSERT(arr[i] == simpleArray[i]);
#if NEW_VERSION
//TODO
#endif
BENCHMARK_THUNK_END();*/
}
if (arrayTests)
{
BENCHMARK_CALL_ARGS1(TIMES4, ActorArrayParam, actorArray);
BENCHMARK_THUNK_BEGIN_ARGS1(TIMES3, ActorArrayParam);
params[0] = MUtils::ToArray(actorArray, Actor::TypeInitializer.GetClass());
BENCHMARK_THUNK_CALL_ARGS1();
#if NEW_VERSION
//MUtils::FreeManaged<RenderContext>((MObject*)params[0]);
#endif
BENCHMARK_THUNK_END();
}
if (arrayTests)
{
BENCHMARK_CALL_ARGS1(TIMES4, ComplexArrayParam, complexArray);
BENCHMARK_THUNK_BEGIN_ARGS1(TIMES3, ComplexArrayParam);
params[0] = MUtils::ToArray(complexArray, TestStruct::TypeInitializer.GetClass());
BENCHMARK_THUNK_CALL_ARGS1();
#if NEW_VERSION
//MUtils::FreeManaged<RenderContext>((MObject*)params[0]);
#endif
BENCHMARK_THUNK_END();
}
if (arrayTests && asRefTests)
{
Array<TestStruct> arr = complexArray;
BENCHMARK_CALL_ARGS1_REF(TIMES4, ComplexArrayParamAsRef, arr);
LOG(Info, " - InvokeThunkOnly: not valid");
/* arr = complexArray;
BENCHMARK_THUNK_BEGIN_ARGS1(TIMES4, ComplexArrayParamAsRef);
#if NEW_VERSION
auto __param_orig_arr = MUtils::ToArray(arr, TestStruct::TypeInitializer.GetClass());
auto __param_arr = __param_orig_arr;
params[0] = &__param_arr;
#else
auto __param_arr = MUtils::ToArray(arr, TestStruct::TypeInitializer.GetClass());
params[0] = &__param_arr;
#endif
BENCHMARK_THUNK_CALL_ARGS1();
arr = MUtils::Unbox<Array<TestStruct>>(*(MObject**)params[0]);
ASSERT(arr.Count() == complexArray.Count());
for (int i = 0; i < arr.Count(); i++) ASSERT(arr[i] == complexArray[i]);
#if NEW_VERSION
//MUtils::FreeManaged<RenderContext>((MObject*)params[0]);
#endif
BENCHMARK_THUNK_END();*/
}
}
void MyScript::OnEnable()
{
//LOG(Info, "C++ OnEnable");
}
void MyScript::OnDisable()
{
LOG(Info, "running garbage collector");
MCore::GC::Collect(MCore::GC::MaxGeneration(), MGCCollectionMode::Aggressive, true, true);
MCore::GC::WaitForPendingFinalizers();
}
void MyScript::OnUpdate()
{
}

108
Source/Game/MyScript.h Normal file
View File

@@ -0,0 +1,108 @@
#pragma once
#include "Engine/Scripting/Script.h"
#include <Engine/Animations/Curve.h>
#include <Engine/AI/Behavior.h>
#include "Engine/Graphics/PostProcessEffect.h"
#include "Engine/Graphics/RenderTask.h"
#include "Engine/Graphics/Graphics.h"
#include "Engine/Scripting/SoftTypeReference.h"
#include "Engine/Content/SceneReference.h"
API_ENUM() enum TestTypeEnum
{
None,
Value1,
Value22,
};
/*template<typename T>
API_STRUCT() struct GAME_API MyThinger
{
public:
T fieldo;
};*/
API_STRUCT(NoDefault) struct TestStruct : public ISerializable
{
API_AUTO_SERIALIZATION();
DECLARE_SCRIPTING_TYPE_MINIMAL(TestStruct);
// Var
API_FIELD() Float3 Vector = Float3::One;
// Ref
API_FIELD() ScriptingObject* Object = nullptr;
// Soft Type Ref
API_FIELD() SoftTypeReference<ScriptingObject> SoftTypeRef;
// Scene Ref
API_FIELD() SceneReference SceneRef;
friend bool operator==(const TestStruct& lhs, const TestStruct& rhs)
{
return lhs.Vector == rhs.Vector &&
lhs.Object == rhs.Object &&
lhs.SoftTypeRef == rhs.SoftTypeRef &&
lhs.SceneRef == rhs.SceneRef;
}
};
API_CLASS() class GAME_API MyScript2 : public Script
{
API_AUTO_SERIALIZATION();
DECLARE_SCRIPTING_TYPE(MyScript2);
API_FUNCTION() virtual void SimpleCall() {};
API_FUNCTION() virtual void SimpleParams(int a, float b, char c, double d, long e) {};
API_FUNCTION() virtual void StringParamAnsi(StringAnsi str) {};
API_FUNCTION() virtual void StringParam(String str) {};
API_FUNCTION() virtual void StringParamRef(String& str) {};
API_FUNCTION() virtual void StringParamRefConst(const String& str) {};
API_FUNCTION() virtual void StringParamAsRef(API_PARAM(Ref) String& str) {};
API_FUNCTION() virtual void ActorParam(Actor* actor) {};
API_FUNCTION() virtual void ComplexParam(BehaviorUpdateContext context) {};
API_FUNCTION() virtual void Complex2Param(RenderContext& context) {};
API_FUNCTION() virtual void Complex2ParamConst(const RenderContext& context) {};
API_FUNCTION() virtual void Complex2ParamAsRef(API_PARAM(Ref) RenderContext& context) {};
API_FUNCTION() virtual void SimpleArrayParam(Array<int> arr) {};
API_FUNCTION() virtual void SimpleArrayParamRef(Array<int>& arr) {};
API_FUNCTION() virtual void SimpleArrayParamRefConst(const Array<int>& arr) {};
API_FUNCTION() virtual void SimpleArrayParamAsRef(API_PARAM(Ref) Array<int>& arr) {};
API_FUNCTION() virtual void ActorArrayParam(Array<Actor*> arr) {};
API_FUNCTION() virtual void ActorArrayParamRef(Array<Actor*>& arr) {};
API_FUNCTION() virtual void ActorArrayParamRefConst(const Array<Actor*>& arr) {};
//API_FUNCTION() virtual void ActorArrayParamAsRef(API_PARAM(Ref) Array<Actor*>& arr) {};
API_FUNCTION() virtual void ComplexArrayParam(Array<TestStruct> arr) {};
API_FUNCTION() virtual void ComplexArrayParamRef(Array<TestStruct>& arr) {};
API_FUNCTION() virtual void ComplexArrayParamRefConst(const Array<TestStruct>& arr) {};
API_FUNCTION() virtual void ComplexArrayParamAsRef(API_PARAM(Ref) Array<TestStruct>& arr) {};
//API_EVENT() Delegate<int32, Float3, const String&, String&, TestStruct&, const Array<TestStruct>&, Array<TestStruct>&> TestEvent;
};
API_CLASS() class GAME_API MyScript : public Script
{
API_AUTO_SERIALIZATION();
DECLARE_SCRIPTING_TYPE(MyScript);
/*API_STRUCT() struct GAME_API InnerStructer
{
public:
float floaty;
};*/
//API_FIELD() MyThinger<int> thingey;
// [Script]
void OnStart() override;
void OnEnable() override;
void OnDisable() override;
void OnUpdate() override;
//API_FUNCTION() void Test1(API_PARAM(REF) Array<TestTypeEnum>& eenums) {};
//API_FUNCTION() BezierCurve<Transform>.Keyframe Test2(BezierCurve<Transform> kef) {};
};

View File

@@ -0,0 +1,59 @@
using System;
using System.Collections.Generic;
using FlaxEngine;
namespace Game;
/// <summary>
/// MyScriptTwo Script.
/// </summary>
public class MyScriptTwo : MyScript2
{
private int counter = 0;
/// <inheritdoc/>
public override void OnStart()
{
Debug.Log("C# OnStart");
}
/// <inheritdoc/>
public override void OnEnable()
{
//counter++;
}
/// <inheritdoc/>
public override void OnDisable()
{
}
/// <inheritdoc/>
public override void OnUpdate()
{
}
public override void SimpleCall() {}
public override void SimpleParams(int a, float b, sbyte c, double d, long e) {}
public override void StringParamAnsi(string str) {}
public override void StringParam(string str) {}
public override void StringParamRef(string str) {}
public override void StringParamRefConst(string str) {}
public override void StringParamAsRef(ref string str) {}
public override void ActorParam(Actor actor) {}
public override void ComplexParam(BehaviorUpdateContext context) {}
public override void Complex2Param(RenderContext context) {}
public override void Complex2ParamConst(RenderContext context) {}
public override void Complex2ParamAsRef(ref RenderContext context) {}
public override void SimpleArrayParam(int[] arr) {}
public override void SimpleArrayParamRef(int[] arr) {}
public override void SimpleArrayParamRefConst(int[] arr) {}
public override void SimpleArrayParamAsRef(ref int[] arr) {}
public override void ActorArrayParam(Actor[] arr) {}
public override void ActorArrayParamRef(Actor[] arr) {}
public override void ActorArrayParamRefConst(Actor[] arr) {}
//public override void ActorArrayParamAsRef(ref Actor[] arr) {}
public override void ComplexArrayParam(TestStruct[] arr) {}
public override void ComplexArrayParamRef(TestStruct[] arr) {}
public override void ComplexArrayParamRefConst(TestStruct[] arr) {}
public override void ComplexArrayParamAsRef(ref TestStruct[] arr) {}
}

View File

@@ -24,13 +24,16 @@ public class GameTarget : GameProjectTarget
OutputType = TargetOutputType.Executable;
}
Modules.Add("Game");
Modules.Add("Graphics");
}
public override void SetupTargetEnvironment(BuildOptions options)
{
base.SetupTargetEnvironment(options);
#pragma warning disable CS0618 // X is obsolete
options.LinkEnv.UseFastPDBLinking = true;
#pragma warning restore CS0618 // X is obsolete
}
public override string GetOutputFilePath(BuildOptions options, TargetOutputType? outputType = null)