Add async init and tint coloring based on type to debug commands
This commit is contained in:
@@ -212,6 +212,11 @@ namespace FlaxEditor.Windows
|
|||||||
Name = command,
|
Name = command,
|
||||||
Owner = this,
|
Owner = this,
|
||||||
});
|
});
|
||||||
|
var flags = DebugCommands.GetCommandFlags(command);
|
||||||
|
if (flags.HasFlag(DebugCommands.CommandFlags.Exec))
|
||||||
|
lastItem.TintColor = new Color(0.85f, 0.85f, 1.0f, 1.0f);
|
||||||
|
else if (flags.HasFlag(DebugCommands.CommandFlags.Read) && !flags.HasFlag(DebugCommands.CommandFlags.Write))
|
||||||
|
lastItem.TintColor = new Color(0.85f, 0.85f, 0.85f, 1.0f);
|
||||||
lastItem.Focused += item =>
|
lastItem.Focused += item =>
|
||||||
{
|
{
|
||||||
// Set command
|
// Set command
|
||||||
@@ -259,6 +264,15 @@ namespace FlaxEditor.Windows
|
|||||||
RootWindow.Window.LostFocus -= OnRootWindowLostFocus;
|
RootWindow.Window.LostFocus -= OnRootWindowLostFocus;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void OnGotFocus()
|
||||||
|
{
|
||||||
|
// Precache debug commands to reduce time-to-interactive
|
||||||
|
DebugCommands.InitAsync();
|
||||||
|
|
||||||
|
base.OnGotFocus();
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override void OnTextChanged()
|
protected override void OnTextChanged()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
#include "Engine/Core/Collections/Array.h"
|
#include "Engine/Core/Collections/Array.h"
|
||||||
#include "Engine/Engine/EngineService.h"
|
#include "Engine/Engine/EngineService.h"
|
||||||
#include "Engine/Threading/Threading.h"
|
#include "Engine/Threading/Threading.h"
|
||||||
|
#include "Engine/Threading/Task.h"
|
||||||
#include "Engine/Profiler/ProfilerCPU.h"
|
#include "Engine/Profiler/ProfilerCPU.h"
|
||||||
#include "Engine/Scripting/BinaryModule.h"
|
#include "Engine/Scripting/BinaryModule.h"
|
||||||
#include "Engine/Scripting/Scripting.h"
|
#include "Engine/Scripting/Scripting.h"
|
||||||
@@ -103,6 +104,7 @@ namespace
|
|||||||
{
|
{
|
||||||
CriticalSection Locker;
|
CriticalSection Locker;
|
||||||
bool Inited = false;
|
bool Inited = false;
|
||||||
|
Task* AsyncTask = nullptr;
|
||||||
Array<CommandData> Commands;
|
Array<CommandData> Commands;
|
||||||
|
|
||||||
void FindDebugCommands(BinaryModule* module)
|
void FindDebugCommands(BinaryModule* module)
|
||||||
@@ -208,15 +210,45 @@ namespace
|
|||||||
|
|
||||||
void InitCommands()
|
void InitCommands()
|
||||||
{
|
{
|
||||||
|
ASSERT_LOW_LAYER(!Inited);
|
||||||
PROFILE_CPU();
|
PROFILE_CPU();
|
||||||
Inited = true;
|
|
||||||
|
// Cache existing modules
|
||||||
const auto& modules = BinaryModule::GetModules();
|
const auto& modules = BinaryModule::GetModules();
|
||||||
for (BinaryModule* module : modules)
|
for (BinaryModule* module : modules)
|
||||||
{
|
{
|
||||||
FindDebugCommands(module);
|
FindDebugCommands(module);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Link for modules load/reload actions
|
||||||
Scripting::BinaryModuleLoaded.Bind(&FindDebugCommands);
|
Scripting::BinaryModuleLoaded.Bind(&FindDebugCommands);
|
||||||
Scripting::ScriptsReloading.Bind(&OnScriptsReloading);
|
Scripting::ScriptsReloading.Bind(&OnScriptsReloading);
|
||||||
|
|
||||||
|
// Mark as done
|
||||||
|
Locker.Lock();
|
||||||
|
Inited = true;
|
||||||
|
AsyncTask = nullptr;
|
||||||
|
Locker.Unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnsureInited()
|
||||||
|
{
|
||||||
|
// Check current state
|
||||||
|
Locker.Lock();
|
||||||
|
bool inited = Inited;
|
||||||
|
Locker.Unlock();
|
||||||
|
if (inited)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Wait for any async task
|
||||||
|
if (AsyncTask)
|
||||||
|
AsyncTask->Wait();
|
||||||
|
|
||||||
|
// Do sync init if still not inited
|
||||||
|
Locker.Lock();
|
||||||
|
if (!Inited)
|
||||||
|
InitCommands();
|
||||||
|
Locker.Unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -231,6 +263,8 @@ public:
|
|||||||
void Dispose() override
|
void Dispose() override
|
||||||
{
|
{
|
||||||
// Cleanup
|
// Cleanup
|
||||||
|
if (AsyncTask)
|
||||||
|
AsyncTask->Wait();
|
||||||
ScopeLock lock(Locker);
|
ScopeLock lock(Locker);
|
||||||
Scripting::BinaryModuleLoaded.Unbind(&FindDebugCommands);
|
Scripting::BinaryModuleLoaded.Unbind(&FindDebugCommands);
|
||||||
Scripting::ScriptsReloading.Unbind(&OnScriptsReloading);
|
Scripting::ScriptsReloading.Unbind(&OnScriptsReloading);
|
||||||
@@ -264,9 +298,8 @@ void DebugCommands::Execute(StringView command)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Ensure that commands cache has been created
|
// Ensure that commands cache has been created
|
||||||
|
EnsureInited();
|
||||||
ScopeLock lock(Locker);
|
ScopeLock lock(Locker);
|
||||||
if (!Inited)
|
|
||||||
InitCommands();
|
|
||||||
|
|
||||||
// Find command to run
|
// Find command to run
|
||||||
for (const CommandData& cmd : Commands)
|
for (const CommandData& cmd : Commands)
|
||||||
@@ -290,9 +323,8 @@ void DebugCommands::Search(StringView searchText, Array<StringView>& matches, bo
|
|||||||
String searchTextCopy = searchText;
|
String searchTextCopy = searchText;
|
||||||
searchText = searchTextCopy;
|
searchText = searchTextCopy;
|
||||||
|
|
||||||
|
EnsureInited();
|
||||||
ScopeLock lock(Locker);
|
ScopeLock lock(Locker);
|
||||||
if (!Inited)
|
|
||||||
InitCommands();
|
|
||||||
|
|
||||||
if (startsWith)
|
if (startsWith)
|
||||||
{
|
{
|
||||||
@@ -316,13 +348,45 @@ void DebugCommands::Search(StringView searchText, Array<StringView>& matches, bo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DebugCommands::Iterate(const StringView& searchText, int32& index)
|
void DebugCommands::InitAsync()
|
||||||
{
|
{
|
||||||
ScopeLock lock(Locker);
|
ScopeLock lock(Locker);
|
||||||
|
if (Inited)
|
||||||
|
return;
|
||||||
|
AsyncTask = Task::StartNew(InitCommands);
|
||||||
|
}
|
||||||
|
|
||||||
|
DebugCommands::CommandFlags DebugCommands::GetCommandFlags(StringView command)
|
||||||
|
{
|
||||||
|
CommandFlags result = CommandFlags::None;
|
||||||
|
// TODO: fix missing string handle on 1st command execution (command gets invalid after InitCommands due to dotnet GC or dotnet interop handles flush)
|
||||||
|
String commandCopy = command;
|
||||||
|
command = commandCopy;
|
||||||
|
EnsureInited();
|
||||||
|
for (auto& e : Commands)
|
||||||
|
{
|
||||||
|
if (e.Name == command)
|
||||||
|
{
|
||||||
|
if (e.Method)
|
||||||
|
result |= CommandFlags::Exec;
|
||||||
|
else if (e.Field)
|
||||||
|
result |= CommandFlags::ReadWrite;
|
||||||
|
if (e.MethodGet)
|
||||||
|
result |= CommandFlags::Read;
|
||||||
|
if (e.MethodSet)
|
||||||
|
result |= CommandFlags::Write;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DebugCommands::Iterate(const StringView& searchText, int32& index)
|
||||||
|
{
|
||||||
|
EnsureInited();
|
||||||
if (index >= 0)
|
if (index >= 0)
|
||||||
{
|
{
|
||||||
if (!Inited)
|
ScopeLock lock(Locker);
|
||||||
InitCommands();
|
|
||||||
while (index < Commands.Count())
|
while (index < Commands.Count())
|
||||||
{
|
{
|
||||||
auto& command = Commands.Get()[index];
|
auto& command = Commands.Get()[index];
|
||||||
|
|||||||
@@ -11,6 +11,21 @@ API_CLASS(static) class FLAXENGINE_API DebugCommands
|
|||||||
{
|
{
|
||||||
DECLARE_SCRIPTING_TYPE_MINIMAL(DebugCommands);
|
DECLARE_SCRIPTING_TYPE_MINIMAL(DebugCommands);
|
||||||
|
|
||||||
|
// Types of debug command flags.
|
||||||
|
API_ENUM(Attributes="Flags") enum class CommandFlags
|
||||||
|
{
|
||||||
|
// Incorrect or missing command.
|
||||||
|
None = 0,
|
||||||
|
// Executable method.
|
||||||
|
Exec = 1,
|
||||||
|
// Can get value.
|
||||||
|
Read = 2,
|
||||||
|
// Can set value.
|
||||||
|
Write = 4,
|
||||||
|
// Can get and set value.
|
||||||
|
ReadWrite = Read | Write,
|
||||||
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Executes the command.
|
/// Executes the command.
|
||||||
@@ -26,7 +41,20 @@ public:
|
|||||||
/// <param name="startsWith">True if filter commands that start with a specific search text, otherwise will return commands that contain a specific query.</param>
|
/// <param name="startsWith">True if filter commands that start with a specific search text, otherwise will return commands that contain a specific query.</param>
|
||||||
API_FUNCTION() static void Search(StringView searchText, API_PARAM(Out) Array<StringView, HeapAllocation>& matches, bool startsWith = false);
|
API_FUNCTION() static void Search(StringView searchText, API_PARAM(Out) Array<StringView, HeapAllocation>& matches, bool startsWith = false);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Starts asynchronous debug commands caching. Cna be used to minimize time-to-interactive when using console interface or when using scripted actions.
|
||||||
|
/// </summary>
|
||||||
|
API_FUNCTION() static void InitAsync();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns flags of the command.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="command">The full name of the command.</param>
|
||||||
|
API_FUNCTION() static CommandFlags GetCommandFlags(StringView command);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static bool Iterate(const StringView& searchText, int32& index);
|
static bool Iterate(const StringView& searchText, int32& index);
|
||||||
static StringView GetCommandName(int32 index);
|
static StringView GetCommandName(int32 index);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
DECLARE_ENUM_OPERATORS(DebugCommands::CommandFlags);
|
||||||
|
|||||||
Reference in New Issue
Block a user