// Copyright (c) Wojciech Figat. All rights reserved. #include "Engine/Platform/Platform.h" #include "Engine/Animations/Graph/AnimGraph.h" #include "Engine/Scripting/Scripting.h" #include "Engine/Scripting/ScriptingType.h" #include "Engine/Scripting/BinaryModule.h" #include "Engine/Scripting/ManagedCLR/MAssembly.h" #include "Engine/Scripting/ManagedCLR/MException.h" #include "Engine/Scripting/ManagedCLR/MUtils.h" #include "Engine/Scripting/ManagedCLR/MCore.h" #include "Engine/Scripting/Internal/InternalCalls.h" #include "Engine/Core/ObjectsRemovalService.h" #include "Engine/Profiler/Profiler.h" #include "FlaxEngine.Gen.h" #if TRACY_ENABLE && !PROFILE_CPU_USE_TRANSIENT_DATA #include "Engine/Core/Collections/ChunkedArray.h" #endif #include "Engine/Threading/Threading.h" #if !COMPILE_WITHOUT_CSHARP DEFINE_INTERNAL_CALL(void) PlatformInternal_MemoryCopy(void* dst, const void* src, uint64 size) { Platform::MemoryCopy(dst, src, size); } DEFINE_INTERNAL_CALL(void) PlatformInternal_MemoryClear(void* dst, uint64 size) { Platform::MemoryClear(dst, size); } DEFINE_INTERNAL_CALL(int32) PlatformInternal_MemoryCompare(const void* buf1, const void* buf2, uint64 size) { return Platform::MemoryCompare(buf1, buf2, size); } DEFINE_INTERNAL_CALL(void) DebugLogHandlerInternal_LogWrite(LogType level, MString* msgObj) { #if LOG_ENABLE StringView msg; MUtils::ToString(msgObj, msg); Log::Logger::Write(level, msg); #endif } DEFINE_INTERNAL_CALL(void) DebugLogHandlerInternal_Log(LogType level, MString* msgObj, ScriptingObject* obj, MString* stackTrace) { #if LOG_ENABLE if (msgObj == nullptr) return; // Get info StringView msg; MUtils::ToString(msgObj, msg); //const String objName = obj ? obj->ToString() : String::Empty; // Send event // TODO: maybe option for build to threat warnings and errors as fatal errors? //const String logMessage = String::Format(TEXT("Debug:{1} {2}"), objName, *msg); Log::Logger::Write(level, msg); #endif } DEFINE_INTERNAL_CALL(void) DebugLogHandlerInternal_LogException(MObject* exception, ScriptingObject* obj) { #if USE_CSHARP if (exception == nullptr) return; // Get info MException ex(exception); const String objName = obj ? obj->ToString() : String::Empty; // Print exception including inner exceptions // TODO: maybe option for build to threat warnings and errors as fatal errors? ex.Log(LogType::Warning, objName.GetText()); #endif } #endif #if USE_CSHARP namespace { #if COMPILE_WITH_PROFILER Array> ManagedEventsGPU; #if TRACY_ENABLE && !PROFILE_CPU_USE_TRANSIENT_DATA CriticalSection ManagedSourceLocationsLocker; struct Location { String Name; StringAnsi NameAnsi; tracy::SourceLocationData SrcLocation; }; ChunkedArray ManagedSourceLocations; ThreadLocal ManagedEventsCount; #endif #endif } DEFINE_INTERNAL_CALL(void) ProfilerInternal_BeginEvent(MString* nameObj) { #if COMPILE_WITH_PROFILER StringView name; MUtils::ToString(nameObj, name); ProfilerCPU::BeginEvent(*name); #if TRACY_ENABLE #if PROFILE_CPU_USE_TRANSIENT_DATA tracy::ScopedZone::Begin(__LINE__, __FILE__, strlen( __FILE__ ), __FUNCTION__, strlen( __FUNCTION__ ), name.Get(), name.Length() ); #else ScopeLock lock(ManagedSourceLocationsLocker); tracy::SourceLocationData* srcLoc = nullptr; for (auto e = ManagedSourceLocations.Begin(); e.IsNotEnd(); ++e) { if (name == e->Name) { srcLoc = &e->SrcLocation; break; } } if (!srcLoc) { auto& e = ManagedSourceLocations.AddOne(); e.Name = name; e.NameAnsi = name.Get(); srcLoc = &e.SrcLocation; srcLoc->name = e.NameAnsi.Get(); srcLoc->function = nullptr; srcLoc->file = nullptr; srcLoc->line = 0; srcLoc->color = 0; } //static constexpr tracy::SourceLocationData tracySrcLoc{ nullptr, __FUNCTION__, __FILE__, (uint32_t)__LINE__, 0 }; const bool tracyActive = tracy::ScopedZone::Begin(srcLoc); if (tracyActive) ManagedEventsCount.Get()++; #endif #endif #endif } DEFINE_INTERNAL_CALL(void) ProfilerInternal_EndEvent() { #if COMPILE_WITH_PROFILER #if TRACY_ENABLE uint32& tracyActive = ManagedEventsCount.Get(); if (tracyActive > 0) { tracyActive--; tracy::ScopedZone::End(); } #endif ProfilerCPU::EndEvent(); #endif } DEFINE_INTERNAL_CALL(void) ProfilerInternal_BeginEventGPU(MString* nameObj) { #if COMPILE_WITH_PROFILER const StringView nameChars = MCore::String::GetChars(nameObj); const auto index = ProfilerGPU::BeginEvent(nameChars.Get()); ManagedEventsGPU.Push(index); #endif } DEFINE_INTERNAL_CALL(void) ProfilerInternal_EndEventGPU() { #if COMPILE_WITH_PROFILER const auto index = ManagedEventsGPU.Pop(); ProfilerGPU::EndEvent(index); #endif } DEFINE_INTERNAL_CALL(bool) ScriptingInternal_HasGameModulesLoaded() { return Scripting::HasGameModulesLoaded(); } DEFINE_INTERNAL_CALL(bool) ScriptingInternal_IsTypeFromGameScripts(MType* type) { return Scripting::IsTypeFromGameScripts(MUtils::GetClass(type)); } DEFINE_INTERNAL_CALL(void) ScriptingInternal_FlushRemovedObjects() { ObjectsRemovalService::Flush(); } #endif class ScriptingInternal { public: static void InitRuntime() { } }; IMPLEMENT_SCRIPTING_TYPE_NO_SPAWN(Scripting, FlaxEngine, "FlaxEngine.Scripting", nullptr, nullptr);