diff --git a/Source/Editor/Editor.cs b/Source/Editor/Editor.cs index b384b6515..393bf564e 100644 --- a/Source/Editor/Editor.cs +++ b/Source/Editor/Editor.cs @@ -1343,108 +1343,6 @@ namespace FlaxEditor public float AutoRebuildNavMeshTimeoutMs; } - [StructLayout(LayoutKind.Sequential)] - [NativeMarshalling(typeof(VisualScriptLocalMarshaller))] - internal struct VisualScriptLocal - { - public string Value; - public string ValueTypeName; - public uint NodeId; - public int BoxId; - } - - [CustomMarshaller(typeof(VisualScriptLocal), MarshalMode.Default, typeof(VisualScriptLocalMarshaller))] - internal static class VisualScriptLocalMarshaller - { - [StructLayout(LayoutKind.Sequential)] - internal struct VisualScriptLocalNative - { - public IntPtr Value; - public IntPtr ValueTypeName; - public uint NodeId; - public int BoxId; - } - - internal static VisualScriptLocal ConvertToManaged(VisualScriptLocalNative unmanaged) => ToManaged(unmanaged); - internal static VisualScriptLocalNative ConvertToUnmanaged(VisualScriptLocal managed) => ToNative(managed); - - internal static VisualScriptLocal ToManaged(VisualScriptLocalNative managed) - { - return new VisualScriptLocal() - { - Value = ManagedString.ToManaged(managed.Value), - ValueTypeName = ManagedString.ToManaged(managed.ValueTypeName), - NodeId = managed.NodeId, - BoxId = managed.BoxId, - }; - } - - internal static VisualScriptLocalNative ToNative(VisualScriptLocal managed) - { - return new VisualScriptLocalNative() - { - Value = ManagedString.ToNative(managed.Value), - ValueTypeName = ManagedString.ToNative(managed.ValueTypeName), - NodeId = managed.NodeId, - BoxId = managed.BoxId, - }; - } - - internal static void Free(VisualScriptLocalNative unmanaged) - { - ManagedString.Free(unmanaged.Value); - ManagedString.Free(unmanaged.ValueTypeName); - } - } - - [StructLayout(LayoutKind.Sequential)] - [NativeMarshalling(typeof(VisualScriptStackFrameMarshaller))] - internal struct VisualScriptStackFrame - { - public VisualScript Script; - public uint NodeId; - public int BoxId; - } - - [CustomMarshaller(typeof(VisualScriptStackFrame), MarshalMode.Default, typeof(VisualScriptStackFrameMarshaller))] - internal static class VisualScriptStackFrameMarshaller - { - [StructLayout(LayoutKind.Sequential)] - internal struct VisualScriptStackFrameNative - { - public IntPtr Script; - public uint NodeId; - public int BoxId; - } - - internal static VisualScriptStackFrame ConvertToManaged(VisualScriptStackFrameNative unmanaged) => ToManaged(unmanaged); - internal static VisualScriptStackFrameNative ConvertToUnmanaged(VisualScriptStackFrame managed) => ToNative(managed); - - internal static VisualScriptStackFrame ToManaged(VisualScriptStackFrameNative managed) - { - return new VisualScriptStackFrame() - { - Script = VisualScriptMarshaller.ConvertToManaged(managed.Script), - NodeId = managed.NodeId, - BoxId = managed.BoxId, - }; - } - - internal static VisualScriptStackFrameNative ToNative(VisualScriptStackFrame managed) - { - return new VisualScriptStackFrameNative() - { - Script = VisualScriptMarshaller.ConvertToUnmanaged(managed.Script), - NodeId = managed.NodeId, - BoxId = managed.BoxId, - }; - } - - internal static void Free(VisualScriptStackFrameNative unmanaged) - { - } - } - internal void BuildCommand(string arg) { if (TryBuildCommand(arg)) @@ -1723,21 +1621,6 @@ namespace FlaxEditor [LibraryImport("FlaxEngine", EntryPoint = "EditorInternal_RunVisualScriptBreakpointLoopTick", StringMarshalling = StringMarshalling.Custom, StringMarshallingCustomType = typeof(StringMarshaller))] internal static partial void Internal_RunVisualScriptBreakpointLoopTick(float deltaTime); - [LibraryImport("FlaxEngine", EntryPoint = "EditorInternal_GetVisualScriptLocals", StringMarshalling = StringMarshalling.Custom, StringMarshallingCustomType = typeof(StringMarshaller))] - [return: MarshalUsing(typeof(FlaxEngine.Interop.ArrayMarshaller<,>), CountElementName = "localsCount")] - internal static partial VisualScriptLocal[] Internal_GetVisualScriptLocals(out int localsCount); - - [LibraryImport("FlaxEngine", EntryPoint = "EditorInternal_GetVisualScriptStackFrames", StringMarshalling = StringMarshalling.Custom, StringMarshallingCustomType = typeof(StringMarshaller))] - [return: MarshalUsing(typeof(FlaxEngine.Interop.ArrayMarshaller<,>), CountElementName = "stackFrameCount")] - internal static partial VisualScriptStackFrame[] Internal_GetVisualScriptStackFrames(out int stackFrameCount); - - [LibraryImport("FlaxEngine", EntryPoint = "EditorInternal_GetVisualScriptPreviousScopeFrame", StringMarshalling = StringMarshalling.Custom, StringMarshallingCustomType = typeof(StringMarshaller))] - internal static partial VisualScriptStackFrame Internal_GetVisualScriptPreviousScopeFrame(); - - [LibraryImport("FlaxEngine", EntryPoint = "EditorInternal_EvaluateVisualScriptLocal", StringMarshalling = StringMarshalling.Custom, StringMarshallingCustomType = typeof(StringMarshaller))] - [return: MarshalAs(UnmanagedType.U1)] - internal static partial bool Internal_EvaluateVisualScriptLocal(IntPtr script, ref VisualScriptLocal local); - [LibraryImport("FlaxEngine", EntryPoint = "EditorInternal_DeserializeSceneObject", StringMarshalling = StringMarshalling.Custom, StringMarshallingCustomType = typeof(StringMarshaller))] internal static partial void Internal_DeserializeSceneObject(IntPtr sceneObject, string json); diff --git a/Source/Editor/Managed/ManagedEditor.Internal.cpp b/Source/Editor/Managed/ManagedEditor.Internal.cpp index 8855ba58a..ae8b71ee2 100644 --- a/Source/Editor/Managed/ManagedEditor.Internal.cpp +++ b/Source/Editor/Managed/ManagedEditor.Internal.cpp @@ -526,133 +526,6 @@ DEFINE_INTERNAL_CALL(void) EditorInternal_RunVisualScriptBreakpointLoopTick(floa Engine::OnDraw(); } -struct VisualScriptLocalManaged -{ - MString* Value; - MString* ValueTypeName; - uint32 NodeId; - int32 BoxId; -}; - -DEFINE_INTERNAL_CALL(MArray*) EditorInternal_GetVisualScriptLocals(int* localsCount) -{ - MArray* result = nullptr; - *localsCount = 0; - const auto stack = VisualScripting::GetThreadStackTop(); - if (stack && stack->Scope) - { - const int32 count = stack->Scope->Parameters.Length() + stack->Scope->ReturnedValues.Count(); - const MClass* mclass = ((NativeBinaryModule*)GetBinaryModuleFlaxEngine())->Assembly->GetClass("FlaxEditor.Editor+VisualScriptLocal"); - ASSERT(mclass); - result = MCore::Array::New(mclass, count); - VisualScriptLocalManaged local; - local.NodeId = MAX_uint32; - if (stack->Scope->Parameters.Length() != 0) - { - auto s = stack; - while (s->PreviousFrame && s->PreviousFrame->Scope == stack->Scope) - s = s->PreviousFrame; - if (s) - local.NodeId = s->Node->ID; - } - VisualScriptLocalManaged* resultPtr = MCore::Array::GetAddress(result); - for (int32 i = 0; i < stack->Scope->Parameters.Length(); i++) - { - auto& v = stack->Scope->Parameters[i]; - local.BoxId = i + 1; - local.Value = MUtils::ToString(v.ToString()); - local.ValueTypeName = MUtils::ToString(v.Type.GetTypeName()); - resultPtr[i] = local; - } - for (int32 i = 0; i < stack->Scope->ReturnedValues.Count(); i++) - { - auto& v = stack->Scope->ReturnedValues[i]; - local.NodeId = v.NodeId; - local.BoxId = v.BoxId; - local.Value = MUtils::ToString(v.Value.ToString()); - local.ValueTypeName = MUtils::ToString(v.Value.Type.GetTypeName()); - resultPtr[stack->Scope->Parameters.Length() + i] = local; - } - *localsCount = count; - } - return result; -} - -struct VisualScriptStackFrameManaged -{ - MObject* Script; - uint32 NodeId; - int32 BoxId; -}; - -DEFINE_INTERNAL_CALL(MArray*) EditorInternal_GetVisualScriptStackFrames(int* stackFramesCount) -{ - MArray* result = nullptr; - *stackFramesCount = 0; - const auto stack = VisualScripting::GetThreadStackTop(); - if (stack) - { - int32 count = 0; - auto s = stack; - while (s) - { - s = s->PreviousFrame; - count++; - } - const MClass* mclass = ((NativeBinaryModule*)GetBinaryModuleFlaxEngine())->Assembly->GetClass("FlaxEditor.Editor+VisualScriptStackFrame"); - ASSERT(mclass); - result = MCore::Array::New(mclass, count); - VisualScriptStackFrameManaged* resultPtr = MCore::Array::GetAddress(result); - s = stack; - count = 0; - while (s) - { - VisualScriptStackFrameManaged frame; - frame.Script = s->Script->GetOrCreateManagedInstance(); - frame.NodeId = s->Node->ID; - frame.BoxId = s->Box ? s->Box->ID : MAX_uint32; - resultPtr[count] = frame; - s = s->PreviousFrame; - count++; - } - *stackFramesCount = count; - } - return result; -} - -DEFINE_INTERNAL_CALL(VisualScriptStackFrameManaged) EditorInternal_GetVisualScriptPreviousScopeFrame() -{ - VisualScriptStackFrameManaged frame; - Platform::MemoryClear(&frame, sizeof(frame)); - const auto stack = VisualScripting::GetThreadStackTop(); - if (stack) - { - auto s = stack; - while (s->PreviousFrame && s->PreviousFrame->Scope == stack->Scope) - s = s->PreviousFrame; - if (s && s->PreviousFrame) - { - s = s->PreviousFrame; - frame.Script = s->Script->GetOrCreateManagedInstance(); - frame.NodeId = s->Node->ID; - frame.BoxId = s->Box ? s->Box->ID : MAX_uint32; - } - } - return frame; -} - -DEFINE_INTERNAL_CALL(bool) EditorInternal_EvaluateVisualScriptLocal(VisualScript* script, VisualScriptLocalManaged* local) -{ - Variant v; - if (VisualScripting::Evaluate(script, VisualScripting::GetThreadStackTop()->Instance, local->NodeId, local->BoxId, v)) - { - local->Value = MUtils::ToString(v.ToString()); - local->ValueTypeName = MUtils::ToString(v.Type.GetTypeName()); - return true; - } - return false; -} - DEFINE_INTERNAL_CALL(void) EditorInternal_DeserializeSceneObject(SceneObject* sceneObject, MString* jsonObj) { PROFILE_CPU_NAMED("DeserializeSceneObject"); diff --git a/Source/Editor/Managed/ManagedEditor.cpp b/Source/Editor/Managed/ManagedEditor.cpp index bed742885..f7e0c1498 100644 --- a/Source/Editor/Managed/ManagedEditor.cpp +++ b/Source/Editor/Managed/ManagedEditor.cpp @@ -489,6 +489,95 @@ void ManagedEditor::RequestStartPlayOnEditMode() Internal_RequestStartPlayOnEditMode->Invoke(GetManagedInstance(), nullptr, nullptr); } +Array ManagedEditor::GetVisualScriptStackFrames() +{ + Array result; + const auto stack = VisualScripting::GetThreadStackTop(); + auto s = stack; + while (s) + { + VisualScriptStackFrame& frame = result.AddOne(); + frame.Script = s->Script; + frame.NodeId = s->Node->ID; + frame.BoxId = s->Box ? s->Box->ID : MAX_uint32; + s = s->PreviousFrame; + } + return result; +} + +ManagedEditor::VisualScriptStackFrame ManagedEditor::GetVisualScriptPreviousScopeFrame() +{ + VisualScriptStackFrame frame; + Platform::MemoryClear(&frame, sizeof(frame)); + const auto stack = VisualScripting::GetThreadStackTop(); + if (stack) + { + auto s = stack; + while (s->PreviousFrame && s->PreviousFrame->Scope == stack->Scope) + s = s->PreviousFrame; + if (s && s->PreviousFrame) + { + s = s->PreviousFrame; + frame.Script = s->Script; + frame.NodeId = s->Node->ID; + frame.BoxId = s->Box ? s->Box->ID : MAX_uint32; + } + } + return frame; +} + +Array ManagedEditor::GetVisualScriptLocals() +{ + Array result; + const auto stack = VisualScripting::GetThreadStackTop(); + if (stack && stack->Scope) + { + const int32 count = stack->Scope->Parameters.Length() + stack->Scope->ReturnedValues.Count(); + result.Resize(count); + VisualScriptLocal local; + local.NodeId = MAX_uint32; + if (stack->Scope->Parameters.Length() != 0) + { + auto s = stack; + while (s->PreviousFrame && s->PreviousFrame->Scope == stack->Scope) + s = s->PreviousFrame; + if (s) + local.NodeId = s->Node->ID; + } + for (int32 i = 0; i < stack->Scope->Parameters.Length(); i++) + { + auto& v = stack->Scope->Parameters[i]; + local.BoxId = i + 1; + local.Value = v.ToString(); + local.ValueTypeName = v.Type.GetTypeName(); + result[i] = local; + } + for (int32 i = 0; i < stack->Scope->ReturnedValues.Count(); i++) + { + auto& v = stack->Scope->ReturnedValues[i]; + local.NodeId = v.NodeId; + local.BoxId = v.BoxId; + local.Value = v.Value.ToString(); + local.ValueTypeName = v.Value.Type.GetTypeName(); + result[stack->Scope->Parameters.Length() + i] = local; + } + } + return result; +} + +bool ManagedEditor::EvaluateVisualScriptLocal(VisualScript* script, VisualScriptLocal& local) +{ + Variant v; + const auto stack = VisualScripting::GetThreadStackTop(); + if (stack && VisualScripting::Evaluate(script, stack->Instance, local.NodeId, local.BoxId, v)) + { + local.Value = v.ToString(); + local.ValueTypeName = v.Type.GetTypeName(); + return true; + } + return false; +} + void ManagedEditor::OnEditorAssemblyLoaded(MAssembly* assembly) { ASSERT(!HasManagedInstance()); diff --git a/Source/Editor/Managed/ManagedEditor.h b/Source/Editor/Managed/ManagedEditor.h index 93d1723a3..8c9571cfd 100644 --- a/Source/Editor/Managed/ManagedEditor.h +++ b/Source/Editor/Managed/ManagedEditor.h @@ -210,6 +210,31 @@ public: API_FUNCTION() static bool TryRestoreImportOptions(API_PARAM(Ref) AudioTool::Options& options, String assetPath); #endif +public: + API_STRUCT(Internal, NoDefault) struct VisualScriptStackFrame + { + DECLARE_SCRIPTING_TYPE_MINIMAL(VisualScriptStackFrame); + + API_FIELD() class VisualScript* Script; + API_FIELD() uint32 NodeId; + API_FIELD() int32 BoxId; + }; + + API_STRUCT(Internal, NoDefault) struct VisualScriptLocal + { + DECLARE_SCRIPTING_TYPE_MINIMAL(VisualScriptLocal); + + API_FIELD() String Value; + API_FIELD() String ValueTypeName; + API_FIELD() uint32 NodeId; + API_FIELD() int32 BoxId; + }; + + API_FUNCTION(Internal) static Array GetVisualScriptStackFrames(); + API_FUNCTION(Internal) static VisualScriptStackFrame GetVisualScriptPreviousScopeFrame(); + API_FUNCTION(Internal) static Array GetVisualScriptLocals(); + API_FUNCTION(Internal) static bool EvaluateVisualScriptLocal(VisualScript* script, API_PARAM(Ref) VisualScriptLocal& local); + private: void OnEditorAssemblyLoaded(MAssembly* assembly); diff --git a/Source/Editor/Surface/VisualScriptSurface.cs b/Source/Editor/Surface/VisualScriptSurface.cs index 2f8d4cda8..18a4695aa 100644 --- a/Source/Editor/Surface/VisualScriptSurface.cs +++ b/Source/Editor/Surface/VisualScriptSurface.cs @@ -123,7 +123,7 @@ namespace FlaxEditor.Surface BoxId = box.ID, }; var script = ((Windows.Assets.VisualScriptWindow)box.Surface.Owner).Asset; - if (Editor.Internal_EvaluateVisualScriptLocal(Object.GetUnmanagedPtr(script), ref local)) + if (Editor.EvaluateVisualScriptLocal(script, ref local)) { text = $"{local.Value ?? string.Empty} ({local.ValueTypeName})"; return true; diff --git a/Source/Editor/Windows/Assets/VisualScriptWindow.cs b/Source/Editor/Windows/Assets/VisualScriptWindow.cs index 79157f850..802269677 100644 --- a/Source/Editor/Windows/Assets/VisualScriptWindow.cs +++ b/Source/Editor/Windows/Assets/VisualScriptWindow.cs @@ -797,11 +797,12 @@ namespace FlaxEditor.Windows.Assets } // Check if any breakpoint was hit - for (int i = 0; i < Surface.Breakpoints.Count; i++) + var breakpoints = Surface.Breakpoints; + for (int i = 0; i < breakpoints.Count; i++) { - if (Surface.Breakpoints[i].ID == flowInfo.NodeId) + if (breakpoints[i].ID == flowInfo.NodeId) { - OnDebugBreakpointHit(ref flowInfo, Surface.Breakpoints[i]); + OnDebugBreakpointHit(ref flowInfo, breakpoints[i]); break; } } @@ -820,7 +821,7 @@ namespace FlaxEditor.Windows.Assets var state = (BreakpointHangState)Editor.Instance.Simulation.BreakpointHangTag; if (state.Locals == null) { - state.Locals = Editor.Internal_GetVisualScriptLocals(out var _); + state.Locals = Editor.GetVisualScriptLocals(); Editor.Instance.Simulation.BreakpointHangTag = state; } return state; @@ -831,7 +832,7 @@ namespace FlaxEditor.Windows.Assets var state = (BreakpointHangState)Editor.Instance.Simulation.BreakpointHangTag; if (state.StackFrames == null) { - state.StackFrames = Editor.Internal_GetVisualScriptStackFrames(out var _); + state.StackFrames = Editor.GetVisualScriptStackFrames(); Editor.Instance.Simulation.BreakpointHangTag = state; } return state; @@ -976,7 +977,7 @@ namespace FlaxEditor.Windows.Assets return; // Break on any of the output connects from the previous scope node - var frame = Editor.Internal_GetVisualScriptPreviousScopeFrame(); + var frame = Editor.GetVisualScriptPreviousScopeFrame(); if (frame.Script != null) { if (_debugStepOutNodesIds == null)