GetLocationsByLspFunc(string path, int
return AsyncUtils.ObserveUntilTimeout(t => lspFunction(parameters, t), TimeoutSpan);
}
+ ///
+ /// Retrieves semantic tokens for the document at the given .
+ ///
+ /// Note that the returned semantic tokens may be empty if the document has not been fully analyzed yet.
+ ///
+ /// The path to the document.
+ /// The semantic tokens for the document at the given path.
+ public async UniTask GetSemanticTokensAsync(string path)
+ {
+ SemanticTokensParams parameters = new()
+ {
+ TextDocument = new TextDocumentIdentifier(path)
+ };
+ return await Client.RequestSemanticTokensFull(parameters);
+ }
+
///
/// Shuts down the language server and exits its process.
///
diff --git a/Assets/SEE/Tools/LSP/LSPIssue.cs b/Assets/SEE/Tools/LSP/LSPIssue.cs
new file mode 100644
index 0000000000..abec60f12e
--- /dev/null
+++ b/Assets/SEE/Tools/LSP/LSPIssue.cs
@@ -0,0 +1,107 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Cysharp.Threading.Tasks;
+using OmniSharp.Extensions.LanguageServer.Protocol.Models;
+using SEE.UI.Window.CodeWindow;
+using Range = SEE.DataModel.DG.Range;
+
+namespace SEE.Tools.LSP
+{
+ ///
+ /// A code issue diagnosed by a language server.
+ ///
+ /// The path of the file where the issue was diagnosed.
+ /// The diagnostic that represents the issue.
+ public record LSPIssue(string Path, Diagnostic Diagnostic) : IDisplayableIssue
+ {
+ ///
+ /// Implements .
+ ///
+ public UniTask ToDisplayStringAsync()
+ {
+ string message = "";
+ if (Diagnostic.Code.HasValue)
+ {
+ message += $"{Diagnostic.Code.Value.String ?? Diagnostic.Code.Value.Long.ToString()}: ";
+ }
+ message += $"{Diagnostic.Message}";
+ return UniTask.FromResult(message);
+ }
+
+ ///
+ /// Implements .
+ ///
+ public string Source => Diagnostic.Source ?? "LSP";
+
+ ///
+ /// Implements .
+ ///
+ public IList RichTags
+ {
+ get
+ {
+ List tags = Diagnostic.Tags?.ToList() ?? new();
+ if (tags.Count > 0)
+ {
+ return tags.Select(DiagnosticTagToRichTag).ToList();
+ }
+ else
+ {
+ // If there are no explicit tags, we create a tag based on the severity.
+ return new List
+ {
+ DiagnosticSeverityToTag(Diagnostic.Severity ?? DiagnosticSeverity.Warning)
+ };
+ }
+ }
+ }
+
+ ///
+ /// Converts a diagnostic tag to a TextMeshPro rich text tag, intended to be used within code windows.
+ ///
+ /// The diagnostic tag to convert.
+ /// The TextMeshPro rich text tag that corresponds to the given .
+ private static string DiagnosticTagToRichTag(DiagnosticTag tag) =>
+ tag switch
+ {
+ DiagnosticTag.Unnecessary => "",
+ DiagnosticTag.Deprecated => "",
+ _ => throw new ArgumentOutOfRangeException(nameof(tag), tag, "Unknown diagnostic tag")
+ };
+
+ ///
+ /// Converts a diagnostic severity to a TextMeshPro rich text tag, intended to be used within code windows.
+ ///
+ /// The diagnostic severity to convert.
+ /// The TextMeshPro rich text tag that corresponds to the given .
+ private static string DiagnosticSeverityToTag(DiagnosticSeverity severity) =>
+ severity switch
+ {
+ DiagnosticSeverity.Error => "",
+ DiagnosticSeverity.Warning => "",
+ DiagnosticSeverity.Information => "",
+ DiagnosticSeverity.Hint => "",
+ _ => throw new ArgumentOutOfRangeException(nameof(severity), severity, "Unknown diagnostic severity")
+ };
+
+ ///
+ /// Implements .
+ ///
+ public IEnumerable<(string Path, Range Range)> Occurrences
+ {
+ get
+ {
+ List<(string Path, Range Range)> occurrences = new()
+ {
+ (Path, Range.FromLspRange(Diagnostic.Range))
+ };
+ if (Diagnostic.RelatedInformation != null)
+ {
+ occurrences.AddRange(Diagnostic.RelatedInformation.Select(x => (x.Location.Uri.GetFileSystemPath(), Range.FromLspRange(x.Location.Range))));
+ }
+ return occurrences;
+ }
+ }
+ }
+}
diff --git a/Assets/SEE/Tools/LSP/LSPIssue.cs.meta b/Assets/SEE/Tools/LSP/LSPIssue.cs.meta
new file mode 100644
index 0000000000..5f566e2bb2
--- /dev/null
+++ b/Assets/SEE/Tools/LSP/LSPIssue.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 0f8ef404e0e848dbacec41015bca6a4e
+timeCreated: 1720786567
\ No newline at end of file
diff --git a/Assets/SEE/Tools/LSP/LSPLanguage.cs b/Assets/SEE/Tools/LSP/LSPLanguage.cs
index f38bdb7e53..53e79be483 100644
--- a/Assets/SEE/Tools/LSP/LSPLanguage.cs
+++ b/Assets/SEE/Tools/LSP/LSPLanguage.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
+using SEE.Scanner;
namespace SEE.Tools.LSP
{
@@ -8,18 +9,8 @@ namespace SEE.Tools.LSP
/// A programming language supported by a language server.
///
///
- public record LSPLanguage
+ public class LSPLanguage: TokenLanguage
{
- ///
- /// The name of the language.
- ///
- public string Name { get; }
-
- ///
- /// The file extensions associated with this language.
- ///
- public ISet Extensions { get; }
-
///
/// A mapping from file extensions to LSP language IDs.
///
@@ -33,16 +24,13 @@ public record LSPLanguage
/// The name of the language.
/// The file extensions associated with this language.
/// A mapping from file extensions to LSP language IDs.
- private LSPLanguage(string name, ISet extensions, IDictionary languageIds = null)
+ private LSPLanguage(string name, ISet extensions, IDictionary languageIds = null): base(name, extensions)
{
if (name.Contains('/'))
{
throw new ArgumentException("Language name must not contain slashes!");
}
- Name = name;
- Extensions = extensions;
LanguageIds = languageIds ?? new Dictionary();
- All.Add(this);
}
///
@@ -63,7 +51,7 @@ private LSPLanguage(string name, ISet extensions, string languageId) : t
/// The language with the given .
public static LSPLanguage GetByName(string name)
{
- return All.First(language => language.Name == name);
+ return AllLspLanguages.First(language => language.Name == name);
}
public override string ToString()
@@ -71,10 +59,6 @@ public override string ToString()
return Name;
}
- // NOTE: All servers below have been tested first. Before adding a language server to this list,
- // please make sure that it actually works in SEE, since we have some special requirements
- // (e.g., we require a documentSymbol provider that returns hierarchic `DocumentSymbol` objects).
- public static readonly IList All = new List();
public static readonly LSPLanguage C = new("C", new HashSet { "c", "h" }, "c");
public static readonly LSPLanguage CPP = new("C++", new HashSet
{
@@ -111,5 +95,10 @@ public override string ToString()
}, "typescript");
public static readonly LSPLanguage XML = new("XML", new HashSet { "xml", "gxl" }, "xml");
public static readonly LSPLanguage Zig = new("Zig", new HashSet { "zig" }, "zig");
+
+ ///
+ /// A list of all supported LSP languages.
+ ///
+ public static readonly IList AllLspLanguages = AllTokenLanguages.OfType().ToList();
}
}
diff --git a/Assets/SEE/Tools/LSP/LSPServer.cs b/Assets/SEE/Tools/LSP/LSPServer.cs
index 7928b5f81e..9081b8a500 100644
--- a/Assets/SEE/Tools/LSP/LSPServer.cs
+++ b/Assets/SEE/Tools/LSP/LSPServer.cs
@@ -1,6 +1,7 @@
using System.Collections.Generic;
using System.Linq;
using SEE.Utils;
+using static SEE.Tools.LSP.LSPLanguage;
namespace SEE.Tools.LSP
{
@@ -75,7 +76,7 @@ private LSPServer(string name, string websiteURL, IList languages,
/// The language ID for the given file .
public string LanguageIdFor(string extension)
{
- LSPLanguage language = Languages.FirstOrDefault(language => language.Extensions.Contains(extension));
+ LSPLanguage language = Languages.FirstOrDefault(language => language.FileExtensions.Contains(extension));
return language?.LanguageIds.GetValueOrDefault(extension, language.LanguageIds.GetValueOrDefault(string.Empty));
}
@@ -86,69 +87,73 @@ public override string ToString()
public static readonly IList All = new List();
+ // NOTE: All servers below have been tested first. Before adding a language server to this list,
+ // please make sure that it actually works in SEE, since we have some special requirements
+ // (e.g., we require a documentSymbol provider that returns hierarchic `DocumentSymbol` objects).
+
public static readonly LSPServer Clangd = new("clangd",
"https://clangd.llvm.org/",
- new List { LSPLanguage.C, LSPLanguage.CPP },
+ new List { C, CPP },
"clangd", "--background-index");
public static readonly LSPServer Gopls = new("gopls",
"https://github.com/golang/tools/tree/master/gopls",
- new List { LSPLanguage.Go },
+ new List { Go },
"gopls");
public static readonly LSPServer HaskellLanguageServer = new("Haskell Language Server",
"https://haskell-language-server.readthedocs.io/en/latest/",
- new List { LSPLanguage.Haskell },
+ new List { Haskell },
"haskell-language-server", "--lsp");
public static readonly LSPServer EclipseJdtls = new("Eclipse JDT Language Server",
"https://github.com/eclipse-jdtls/eclipse.jdt.ls",
- new List { LSPLanguage.Java },
+ new List { Java },
"jdtls");
public static readonly LSPServer TypescriptLanguageServer = new("Typescript Language Server",
"https://github.com/typescript-language-server/typescript-language-server",
- new List { LSPLanguage.TypeScript, LSPLanguage.JavaScript },
+ new List { TypeScript, JavaScript },
"typescript-language-server", "--stdio");
public static readonly LSPServer VscodeJson = new("VSCode JSON Language Server",
"https://www.npmjs.com/package/vscode-json-languageserver",
- new List { LSPLanguage.JSON },
+ new List { JSON },
"vscode-json-languageserver", "--stdio");
public static readonly LSPServer Texlab = new("Texlab",
"https://github.com/latex-lsp/texlab",
- new List { LSPLanguage.LaTeX },
+ new List { LaTeX },
"texlab");
public static readonly LSPServer LuaLanguageServer = new("Lua Language Server",
"https://github.com/LuaLS/lua-language-server",
- new List { LSPLanguage.Lua },
+ new List { Lua },
"lua-language-server");
public static readonly LSPServer Marksman = new("Marksman",
"https://github.com/artempyanykh/marksman",
- new List { LSPLanguage.Markdown },
+ new List { Markdown },
"marksman", "server");
public static readonly LSPServer MatlabLanguageServer = new("Matlab Language Server",
"https://github.com/mathworks/MATLAB-language-server",
- new List { LSPLanguage.MATLAB },
+ new List { MATLAB },
"matlab-language-server", "--stdio");
public static readonly LSPServer PhpActor = new("Phpactor",
"https://github.com/phpactor/phpactor",
- new List { LSPLanguage.PHP },
+ new List { PHP },
"phpactor", "language-server");
public static readonly LSPServer Intelephense = new("Intelephense",
"https://github.com/bmewburn/vscode-intelephense",
- new List { LSPLanguage.PHP },
+ new List { PHP },
"intelephense", "--stdio");
public static readonly LSPServer Omnisharp = new("Omnisharp",
"https://github.com/OmniSharp/omnisharp-roslyn",
- new List { LSPLanguage.CSharp },
+ new List { CSharp },
"omnisharp", "-z DotNet:enablePackageRestore=false -e utf-8 -lsp",
initOptions: new Dictionary
{
@@ -164,33 +169,33 @@ public override string ToString()
public static readonly LSPServer DartAnalysisServer = new("Dart analysis server",
"https://github.com/dart-lang/sdk/blob/master/pkg/analysis_server/tool/lsp_spec/README.md",
- new List { LSPLanguage.Dart },
+ new List { Dart },
"dart", "language-server");
public static readonly LSPServer KotlinLanguageServer = new("Kotlin Language Server",
"https://github.com/fwcd/kotlin-language-server",
- new List { LSPLanguage.Kotlin },
+ new List { Kotlin },
"kotlin-language-server");
public static readonly LSPServer Pyright = new("Pyright",
"https://github.com/microsoft/pyright",
- new List { LSPLanguage.Python },
+ new List { Python },
"pyright-langserver",
"--stdio");
public static readonly LSPServer Jedi = new("Jedi Language Server",
"https://github.com/pappasam/jedi-language-server",
- new List { LSPLanguage.Python },
+ new List { Python },
"jedi-language-server");
public static readonly LSPServer RubyLsp = new("Ruby LSP",
"https://github.com/Shopify/ruby-lsp",
- new List { LSPLanguage.Ruby },
+ new List { Ruby },
"srb", "typecheck --lsp --disable-watchman .");
public static readonly LSPServer RustAnalyzer = new("Rust Analyzer",
"https://github.com/rust-lang/rust-analyzer",
- new List { LSPLanguage.Rust },
+ new List { Rust },
"rust-analyzer",
initOptions: new Dictionary
{
@@ -204,12 +209,12 @@ public override string ToString()
public static readonly LSPServer Lemminx = new("Lemminx",
"https://github.com/eclipse/lemminx",
- new List { LSPLanguage.XML },
+ new List { XML },
"lemminx");
public static readonly LSPServer ZLS = new("ZLS",
"https://github.com/zigtools/zls",
- new List { LSPLanguage.Zig },
+ new List { Zig },
"zls");
///
diff --git a/Assets/SEE/UI/DebugAdapterProtocol/DebugAdapterProtocolSession.cs b/Assets/SEE/UI/DebugAdapterProtocol/DebugAdapterProtocolSession.cs
index d11acae1cb..dd4249a142 100644
--- a/Assets/SEE/UI/DebugAdapterProtocol/DebugAdapterProtocolSession.cs
+++ b/Assets/SEE/UI/DebugAdapterProtocol/DebugAdapterProtocolSession.cs
@@ -336,11 +336,11 @@ private void OnDestroy()
{
Destroyer.Destroy(controls);
}
- if (adapterProcess != null && !adapterProcess.HasExited)
+ if (adapterProcess is { HasExited: false })
{
adapterProcess.Kill();
}
- if (adapterHost != null && adapterHost.IsRunning)
+ if (adapterHost is { IsRunning: true })
{
adapterHost.Stop();
}
@@ -349,12 +349,12 @@ private void OnDestroy()
///
/// Creates the process for the debug adapter.
///
- /// Whether the creation was sucessful.
+ /// Whether the creation was successful.
private bool CreateAdapterProcess()
{
adapterProcess = new Process
{
- StartInfo = new ProcessStartInfo()
+ StartInfo = new ProcessStartInfo
{
FileName = Adapter.AdapterFileName,
Arguments = Adapter.AdapterArguments,
@@ -371,8 +371,8 @@ private bool CreateAdapterProcess()
},
EnableRaisingEvents = true
};
- adapterProcess.Exited += (_, args) => ConsoleWindow.AddMessage($"Process: Exited! ({(!adapterProcess.HasExited ? adapterProcess.ProcessName : null)})");
- adapterProcess.Disposed += (_, args) => ConsoleWindow.AddMessage($"Process: Exited! ({(!adapterProcess.HasExited ? adapterProcess.ProcessName : null)})");
+ adapterProcess.Exited += (_, _) => ConsoleWindow.AddMessage($"Process: Exited! ({(!adapterProcess.HasExited ? adapterProcess.ProcessName : null)})");
+ adapterProcess.Disposed += (_, _) => ConsoleWindow.AddMessage($"Process: Exited! ({(!adapterProcess.HasExited ? adapterProcess.ProcessName : null)})");
adapterProcess.OutputDataReceived += (_, args) => ConsoleWindow.AddMessage($"Process: OutputDataReceived! ({adapterProcess.ProcessName})\n\t{args.Data}");
adapterProcess.ErrorDataReceived += (_, args) =>
{
@@ -410,7 +410,7 @@ private bool CreateAdapterProcess()
private bool CreateAdapterHost()
{
adapterHost = new DebugProtocolHost(adapterProcess.StandardInput.BaseStream, adapterProcess.StandardOutput.BaseStream);
- adapterHost.DispatcherError += (sender, args) =>
+ adapterHost.DispatcherError += (_, args) =>
{
string message = $"DispatcherError - {args.Exception}";
ConsoleWindow.AddMessage(message + "\n", "Adapter", "Error");
@@ -451,7 +451,7 @@ private void UpdateStackFrames()
return;
}
- stackFrames = adapterHost.SendRequestSync(new StackTraceRequest() { ThreadId = MainThread.Id }).StackFrames;
+ stackFrames = adapterHost.SendRequestSync(new StackTraceRequest { ThreadId = MainThread.Id }).StackFrames;
}
@@ -474,7 +474,7 @@ private void UpdateVariables()
foreach (StackFrame stackFrame in stackFrames)
{
- List stackScopes = adapterHost.SendRequestSync(new ScopesRequest() { FrameId = stackFrame.Id }).Scopes;
+ List stackScopes = adapterHost.SendRequestSync(new ScopesRequest { FrameId = stackFrame.Id }).Scopes;
Dictionary> stackVariables = stackScopes.ToDictionary(scope => scope, scope => RetrieveNestedVariables(scope.VariablesReference));
threadVariables.Add(stackFrame, stackVariables);
}
@@ -499,7 +499,7 @@ private List RetrieveNestedVariables(int variablesReference)
{
return new();
}
- return adapterHost.SendRequestSync(new VariablesRequest() { VariablesReference = variablesReference }).Variables;
+ return adapterHost.SendRequestSync(new VariablesRequest { VariablesReference = variablesReference }).Variables;
}
///
@@ -512,7 +512,7 @@ private string RetrieveVariableValue(Variable variable)
{
if (IsRunning && variable.EvaluateName != null)
{
- EvaluateResponse value = adapterHost.SendRequestSync(new EvaluateRequest()
+ EvaluateResponse value = adapterHost.SendRequestSync(new EvaluateRequest
{
Expression = variable.EvaluateName,
FrameId = IsRunning ? null : StackFrame.Id
diff --git a/Assets/SEE/UI/DebugAdapterProtocol/DebugAdapterProtocolSessionCodePosition.cs b/Assets/SEE/UI/DebugAdapterProtocol/DebugAdapterProtocolSessionCodePosition.cs
index afaabbb88a..0e1fa44116 100644
--- a/Assets/SEE/UI/DebugAdapterProtocol/DebugAdapterProtocolSessionCodePosition.cs
+++ b/Assets/SEE/UI/DebugAdapterProtocol/DebugAdapterProtocolSessionCodePosition.cs
@@ -6,6 +6,7 @@
using SEE.Utils;
using System.IO;
using System.Linq;
+using Cysharp.Threading.Tasks;
using StackFrame = Microsoft.VisualStudio.Shared.VSCodeDebugProtocol.Messages.StackFrame;
namespace SEE.UI.DebugAdapterProtocol
@@ -87,7 +88,7 @@ private void ShowCodePosition(bool makeActive = false, bool scroll = false, floa
{
codeWindow = Canvas.AddComponent();
codeWindow.Title = Path.GetFileName(lastCodePath);
- codeWindow.EnterFromFile(lastCodePath);
+ codeWindow.EnterFromFileAsync(lastCodePath).Forget();
manager.AddWindow(codeWindow);
codeWindow.OnComponentInitialized += Mark;
codeWindow.OnComponentInitialized += MakeActive;
diff --git a/Assets/SEE/UI/DebugAdapterProtocol/DebugAdapterProtocolSessionEvents.cs b/Assets/SEE/UI/DebugAdapterProtocol/DebugAdapterProtocolSessionEvents.cs
index 4760de1f89..c45d0113d2 100644
--- a/Assets/SEE/UI/DebugAdapterProtocol/DebugAdapterProtocolSessionEvents.cs
+++ b/Assets/SEE/UI/DebugAdapterProtocol/DebugAdapterProtocolSessionEvents.cs
@@ -25,16 +25,16 @@ private void OnBreakpointsChanged(string path, int line)
{
actions.Enqueue(() =>
{
- adapterHost.SendRequest(new SetBreakpointsRequest()
+ adapterHost.SendRequest(new SetBreakpointsRequest
{
- Source = new Source() { Path = path, Name = path },
+ Source = new Source { Path = path, Name = path },
Breakpoints = DebugBreakpointManager.Breakpoints[path].Values.ToList(),
}, _ => { });
});
}
///
- /// Handles the begining of hovering a word.
+ /// Handles the beginning of hovering a word.
///
/// The code window containing the hovered word.
/// The info of the hovered word.
@@ -66,11 +66,11 @@ private void UpdateHoverTooltip()
return;
}
- string expression = ((TMP_WordInfo)hoveredWord).GetWord();
+ string expression = hoveredWord.Value.GetWord();
try
{
- EvaluateResponse result = adapterHost.SendRequestSync(new EvaluateRequest()
+ EvaluateResponse result = adapterHost.SendRequestSync(new EvaluateRequest
{
Expression = expression,
Context = capabilities.SupportsEvaluateForHovers == true ? EvaluateArguments.ContextValue.Hover : null,
@@ -133,14 +133,14 @@ private void OnInitializedEvent(InitializedEvent initializedEvent)
adapterHost.SendRequest(Adapter.GetLaunchRequest(), _ => IsRunning = true);
foreach ((string path, Dictionary breakpoints) in DebugBreakpointManager.Breakpoints)
{
- adapterHost.SendRequest(new SetBreakpointsRequest()
+ adapterHost.SendRequest(new SetBreakpointsRequest
{
- Source = new Source() { Path = path, Name = path },
+ Source = new Source { Path = path, Name = path },
Breakpoints = breakpoints.Values.ToList(),
}, _ => { });
}
- adapterHost.SendRequest(new SetFunctionBreakpointsRequest() { Breakpoints = new() }, _ => { });
- adapterHost.SendRequest(new SetExceptionBreakpointsRequest() { Filters = new() }, _ => { });
+ adapterHost.SendRequest(new SetFunctionBreakpointsRequest { Breakpoints = new() }, _ => { });
+ adapterHost.SendRequest(new SetExceptionBreakpointsRequest { Filters = new() }, _ => { });
if (capabilities.SupportsConfigurationDoneRequest == true)
{
adapterHost.SendRequest(new ConfigurationDoneRequest(), _ => { });
@@ -227,7 +227,7 @@ private void OnStoppedEvent(StoppedEvent stoppedEvent)
return;
}
- ExceptionInfoResponse exceptionInfo = adapterHost.SendRequestSync(new ExceptionInfoRequest()
+ ExceptionInfoResponse exceptionInfo = adapterHost.SendRequestSync(new ExceptionInfoRequest
{
ThreadId = MainThread.Id,
});
@@ -358,7 +358,7 @@ private void OnConsoleInput(string text)
///
/// Queues a continue request.
///
- void OnContinue()
+ private void OnContinue()
{
actions.Enqueue(() =>
{
@@ -373,7 +373,7 @@ void OnContinue()
///
/// Queues a pause request.
///
- void OnPause()
+ private void OnPause()
{
actions.Enqueue(() =>
{
@@ -388,7 +388,7 @@ void OnPause()
///
/// Queues a reverse continue request.
///
- void OnReverseContinue()
+ private void OnReverseContinue()
{
actions.Enqueue(() =>
{
@@ -403,7 +403,7 @@ void OnReverseContinue()
///
/// Queues a next request.
///
- void OnNext()
+ private void OnNext()
{
actions.Enqueue(() =>
{
@@ -418,7 +418,7 @@ void OnNext()
///
/// Queues a step back request.
///
- void OnStepBack()
+ private void OnStepBack()
{
actions.Enqueue(() =>
{
@@ -433,7 +433,7 @@ void OnStepBack()
///
/// Queues a step in request.
///
- void OnStepIn()
+ private void OnStepIn()
{
actions.Enqueue(() =>
{
@@ -448,7 +448,7 @@ void OnStepIn()
///
/// Queues a step out request.
///
- void OnStepOut()
+ private void OnStepOut()
{
actions.Enqueue(() =>
{
@@ -463,7 +463,7 @@ void OnStepOut()
///
/// Queues a restart request.
///
- void OnRestart()
+ private void OnRestart()
{
actions.Enqueue(() =>
{
@@ -474,7 +474,7 @@ void OnRestart()
///
/// Queues a terminate request.
///
- void OnStop()
+ private void OnStop()
{
actions.Enqueue(() =>
{
@@ -487,6 +487,7 @@ void OnStop()
Disconnect();
}
});
+ return;
// Tries to stop the debuggee gracefully.
void Terminate()
diff --git a/Assets/SEE/UI/HelpSystem/HelpSystemBuilder.cs b/Assets/SEE/UI/HelpSystem/HelpSystemBuilder.cs
index 74800a05d2..9d1b7f7025 100644
--- a/Assets/SEE/UI/HelpSystem/HelpSystemBuilder.cs
+++ b/Assets/SEE/UI/HelpSystem/HelpSystemBuilder.cs
@@ -18,6 +18,7 @@
using System.Collections.Generic;
using System.IO;
using SEE.UI.Menu;
+using SEE.Utils;
using TMPro;
using UnityEngine;
using UnityEngine.Video;
@@ -107,25 +108,20 @@ private static GameObject HelpSystemObject()
}
///
- /// The path to the default-icon for an HelpSystemEntry in the nested menu.
+ /// The path to the default-icon for a in the nested menu.
///
- private const string entryIcon = "Materials/ModernUIPack/Eye";
+ private const char entryIcon = Icons.Eye;
///
- /// The path to the default-icon for an RefEntry in the nested menu.
+ /// The path to the default-icon for a RefEntry in the nested menu.
///
- private const string refIcon = "Materials/ModernUIPack/Plus";
+ private const char refIcon = '+';
///
/// The LinkedListEntries of the currently selected HelpSystemEntry.
///
public static LinkedList CurrentEntries;
- ///
- /// The space where the entry is inside.
- ///
- public static GameObject EntrySpace;
-
///
/// The headline gameObject of the helpSystemEntry or rather the headline which is inside of the dynamicPanel.
///
@@ -150,20 +146,19 @@ public static MenuEntry CreateNewHelpSystemEntry
LinkedList keywords,
HelpSystemEntry entry = null)
{
- return new MenuEntry(selectAction: () => { Execute(entry, title, keywords, videoPath); },
- unselectAction: null,
- title: title,
- description: description,
- entryColor: entryColor,
- icon: Resources.Load(entryIcon));
+ return new MenuEntry(SelectAction: () => Execute(entry, title, keywords, videoPath),
+ Title: title,
+ Description: description,
+ EntryColor: entryColor,
+ Icon: entryIcon);
}
///
/// Creates a new Ref-Entry for the HelpSystemMenu. That means, this entry contains a list of further entries,
- /// which are opened as the lower hierachy-layer onclick. These entries are only responsible for the structure of the HelpSystemMenu,
+ /// which are opened as the lower hierarchy-layer onclick. These entries are only responsible for the structure of the HelpSystemMenu,
/// they are not executing an HelpSystemEntry.
///
- /// The inner Entries, which are displayed onclick as the lower hierachy-layer.
+ /// The inner Entries, which are displayed onclick as the lower hierarchy-layer.
/// The title of the RefEntry.
/// The description of the RefEntry, displayed as a tooltip.
/// The color of the Ref-Entry.
@@ -174,18 +169,18 @@ public static NestedMenuEntry CreateNewRefEntry(List inner
title: title,
description: description,
entryColor: entryColor,
- icon: Resources.Load(refIcon));
+ icon: refIcon);
}
///
/// Creates the Main-Menu of the HelpSystemMenu.
- /// More specific, it creates the highest Hierachy-Layer,
+ /// More specific, it creates the highest Hierarchy-Layer,
/// where new Layers can be attached to with the functions above.
///
/// The title of the HelpSystem-MainMenu.
/// The description of the HelpSystem-MainMenu.
/// The icon of the HelpSystem-MainMenu.
- /// The MenuEntries which are displayed inside of the MainMenu for more hierachy-layers.
+ /// The MenuEntries which are displayed inside of the MainMenu for more hierarchy-layers.
/// The Main-Menu as a NestedMenu.
public static NestedListMenu CreateMainMenu(string title, string description, string icon, List mainMenuEntries)
{
@@ -208,7 +203,7 @@ public static NestedListMenu CreateMainMenu(string title, string description, st
/// The title of the HelpSystemEntry.
/// The path of the video which should be displayed.
/// All instructions which should be displayed and spoken aloud.
- public static void Execute(HelpSystemEntry helpSystem, string entryTitle, LinkedList instructions, string videoPath)
+ private static void Execute(HelpSystemEntry helpSystem, string entryTitle, LinkedList instructions, string videoPath)
{
helpSystem.EntryShown = true;
helpSystem.ShowEntry();
diff --git a/Assets/SEE/UI/HelpSystem/HelpSystemEntry.cs b/Assets/SEE/UI/HelpSystem/HelpSystemEntry.cs
index 6802db22e4..ebc3efd8de 100644
--- a/Assets/SEE/UI/HelpSystem/HelpSystemEntry.cs
+++ b/Assets/SEE/UI/HelpSystem/HelpSystemEntry.cs
@@ -245,7 +245,6 @@ public void ShowEntry()
{
helpSystemSpace = PrefabInstantiator.InstantiatePrefab(helpSystemEntrySpacePrefab, Canvas.transform, false);
helpSystemEntry = PrefabInstantiator.InstantiatePrefab(helpSystemEntryPrefab, helpSystemSpace.transform, false);
- HelpSystemBuilder.EntrySpace = helpSystemSpace;
helpSystemSpace.transform.localScale = new Vector3(1.7f, 1.7f);
RectTransform dynamicPanel = helpSystemSpace.transform.GetChild(2).GetComponent();
dynamicPanel.sizeDelta = new Vector2(550, 425);
diff --git a/Assets/SEE/UI/Menu/Desktop/SimpleListMenuDesktop.cs b/Assets/SEE/UI/Menu/Desktop/SimpleListMenuDesktop.cs
index 97fb47f99b..17dcad2146 100644
--- a/Assets/SEE/UI/Menu/Desktop/SimpleListMenuDesktop.cs
+++ b/Assets/SEE/UI/Menu/Desktop/SimpleListMenuDesktop.cs
@@ -1,6 +1,9 @@
-using Michsky.UI.ModernUIPack;
+using System.Linq;
+using Michsky.UI.ModernUIPack;
+using SEE.GO;
using SEE.Utils;
using Sirenix.Utilities;
+using TMPro;
using UnityEngine;
using UnityEngine.UI;
@@ -52,7 +55,7 @@ public partial class SimpleListMenu where T : MenuEntry
///
/// The menu entry.
/// The game object of the entry.
- public GameObject EntryGameObject(T entry) => EntryList.transform.Find(entry.Title)?.gameObject;
+ protected GameObject EntryGameObject(T entry) => EntryList.transform.Cast().FirstOrDefault(x => x.name == entry.Title)?.gameObject;
///
/// Initializes the menu.
@@ -110,14 +113,18 @@ protected virtual void AddButton(T entry)
// title and icon
button.name = entry.Title;
- ButtonManagerBasicWithIcon buttonManager = button.GetComponent();
+ ButtonManagerBasic buttonManager = button.MustGetComponent();
+ TextMeshProUGUI iconText = button.transform.Find("Icon").gameObject.MustGetComponent();
buttonManager.buttonText = entry.Title;
- buttonManager.buttonIcon = entry.Icon;
+ iconText.text = entry.Icon.ToString();
// hover listeners
- PointerHelper pointerHelper = button.GetComponent();
- pointerHelper.EnterEvent.AddListener(_ => Tooltip.ActivateWith(entry.Description));
- pointerHelper.ExitEvent.AddListener(_ => Tooltip.Deactivate());
+ PointerHelper pointerHelper = button.MustGetComponent();
+ if (entry.Description != null)
+ {
+ pointerHelper.EnterEvent.AddListener(_ => Tooltip.ActivateWith(entry.Description));
+ pointerHelper.ExitEvent.AddListener(_ => Tooltip.Deactivate());
+ }
// adds clickEvent listener or show that button is disabled
if (entry.Enabled)
@@ -131,10 +138,10 @@ protected virtual void AddButton(T entry)
// colors
Color color = entry.Enabled ? entry.EntryColor : entry.DisabledColor;
- button.GetComponent().color = color;
+ button.MustGetComponent().color = color;
Color textColor = color.IdealTextColor();
buttonManager.normalText.color = textColor;
- buttonManager.normalImage.color = textColor;
+ iconText.color = textColor;
}
///
diff --git a/Assets/SEE/UI/Menu/MenuEntry.cs b/Assets/SEE/UI/Menu/MenuEntry.cs
index 560321cfa9..4690a82fbd 100644
--- a/Assets/SEE/UI/Menu/MenuEntry.cs
+++ b/Assets/SEE/UI/Menu/MenuEntry.cs
@@ -1,7 +1,6 @@
using System;
using SEE.Utils;
using UnityEngine;
-using UnityEngine.Events;
namespace SEE.UI.Menu
{
@@ -9,70 +8,21 @@ namespace SEE.UI.Menu
/// This class represents a platform-independent entry in a ,
/// which performs a designated action when it is chosen there.
///
- public class MenuEntry
+ /// The action to take when the entry is selected.
+ /// The action to take when the entry is unselected. May be null if nothing
+ /// should happen when it is unselected.
+ /// The title of the entry.
+ /// A description of the entry.
+ /// The color with which this entry shall be displayed.
+ /// Whether this entry should be enabled (i.e., whether it can be selected).
+ /// The icon which shall be displayed alongside this entry,
+ /// given as a FontAwesome codepoint. See for more information.
+ public record MenuEntry(Action SelectAction, string Title, Action UnselectAction = null, string Description = null,
+ Color EntryColor = default, bool Enabled = true, char Icon = ' ')
{
- ///
- /// The title of this entry.
- ///
- public readonly string Title;
-
- ///
- /// A description of this entry.
- ///
- public readonly string Description;
-
- ///
- /// The color of this entry.
- ///
- public readonly Color EntryColor;
-
- ///
- /// An icon for this entry.
- ///
- public readonly Sprite Icon;
-
- ///
- /// The action to be taken when the entry is selected.
- ///
- public readonly UnityAction SelectAction;
-
- ///
- /// The action to be taken when the entry is deselected.
- ///
- public readonly UnityAction UnselectAction;
-
- ///
- /// Whether this entry is currently enabled (i.e. whether it can be selected.)
- /// Defaults to true.
- ///
- public bool Enabled;
-
///
/// The color of this entry when disabled.
///
public Color DisabledColor => EntryColor.WithAlpha(0.2f);
-
- ///
- /// Instantiates and returns a new MenuEntry.
- ///
- /// What action to take when the entry is selected.
- /// What action to take when the entry is unselected.
- /// The title of the entry.
- /// A description of the entry.
- /// The color with which this entry shall be displayed.
- /// Whether this entry should be enabled on creation.
- /// The icon which shall be displayed alongside this entry.
- /// If is null.
- public MenuEntry(UnityAction selectAction, UnityAction unselectAction, string title, string description = null, Color entryColor = default,
- bool enabled = true, Sprite icon = null)
- {
- SelectAction = selectAction;
- UnselectAction = unselectAction ?? (() => { });
- Title = title ?? throw new ArgumentNullException(nameof(title));
- Description = description;
- EntryColor = entryColor;
- Enabled = enabled;
- Icon = icon;
- }
}
}
diff --git a/Assets/SEE/UI/Menu/NestedMenu.cs b/Assets/SEE/UI/Menu/NestedMenu.cs
index 1ee772b8f5..bb253abc20 100644
--- a/Assets/SEE/UI/Menu/NestedMenu.cs
+++ b/Assets/SEE/UI/Menu/NestedMenu.cs
@@ -132,7 +132,7 @@ private void DescendLevel(NestedMenuEntry nestedEntry, bool withBreadcrumb =
// as the title is technically the last element in the breadcrumb)
string breadcrumb = withBreadcrumb ? GetBreadcrumb() : string.Empty;
Description = nestedEntry.Description + (breadcrumb.Length > 0 ? $"\n{GetBreadcrumb()}" : "");
- Icon = nestedEntry.Icon;
+ Icon = nestedEntry.MenuIconSprite;
nestedEntry.InnerEntries.ForEach(AddEntry);
KeywordListener.Unregister(HandleKeyword);
KeywordListener.Register(HandleKeyword);
@@ -311,8 +311,7 @@ private async UniTaskVoid SearchTextEnteredAsync()
.Select(x => allEntries[x.Value])
.ToList();
- NestedMenuEntry resultEntry = new(results, Title, Description,
- default, default, Icon);
+ NestedMenuEntry resultEntry = new(results, Title, Description, menuIconSprite: Icon);
DescendLevel(resultEntry, withBreadcrumb: false);
}
finally
diff --git a/Assets/SEE/UI/Menu/NestedMenuEntry.cs b/Assets/SEE/UI/Menu/NestedMenuEntry.cs
index 70eae1fe08..ce96157c5f 100644
--- a/Assets/SEE/UI/Menu/NestedMenuEntry.cs
+++ b/Assets/SEE/UI/Menu/NestedMenuEntry.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
+using SEE.Utils;
using UnityEngine;
namespace SEE.UI.Menu
@@ -9,13 +10,18 @@ namespace SEE.UI.Menu
/// A button which opens another menu when clicking on it.
/// Must be used inside a .
///
- public class NestedMenuEntry : MenuEntry where T : MenuEntry
+ public record NestedMenuEntry : MenuEntry where T : MenuEntry
{
///
/// The menu entries which shall fill the menu when selecting this entry.
///
public readonly List InnerEntries;
+ ///
+ /// The sprite of the icon of the menu itself.
+ ///
+ public readonly Sprite MenuIconSprite;
+
///
/// Instantiates and returns a new .
///
@@ -24,13 +30,16 @@ public class NestedMenuEntry : MenuEntry where T : MenuEntry
/// A description of the entry.
/// The color with which this entry shall be displayed.
/// Whether this entry should be enabled on creation.
- /// The icon which shall be displayed alongside this entry.
+ /// The FontAwesome icon which shall be displayed alongside this entry.
+ /// The sprite of the icon of the menu itself.
/// If is null.
public NestedMenuEntry(IEnumerable innerEntries, string title, string description = null,
- Color entryColor = default, bool enabled = true, Sprite icon = null) :
- base(() => { }, () => { }, title, description, entryColor, enabled, icon)
+ Color entryColor = default, bool enabled = true,
+ char icon = Icons.Bars, Sprite menuIconSprite = null)
+ : base(() => { }, title, () => { }, description, entryColor, enabled, icon)
{
InnerEntries = innerEntries?.ToList() ?? throw new ArgumentNullException(nameof(innerEntries));
+ MenuIconSprite = menuIconSprite;
}
}
}
diff --git a/Assets/SEE/UI/Menu/SelectionMenu.cs b/Assets/SEE/UI/Menu/SelectionMenu.cs
index a269161a8b..a50f51c5db 100644
--- a/Assets/SEE/UI/Menu/SelectionMenu.cs
+++ b/Assets/SEE/UI/Menu/SelectionMenu.cs
@@ -34,7 +34,7 @@ public T ActiveEntry
activeEntry = value;
if (oldActiveEntry != null)
{
- oldActiveEntry.UnselectAction();
+ oldActiveEntry.UnselectAction?.Invoke();
OnEntryUnselected?.Invoke(oldActiveEntry);
}
OnActiveEntryChanged?.Invoke();
diff --git a/Assets/SEE/UI/Menu/SimpleListMenu.cs b/Assets/SEE/UI/Menu/SimpleListMenu.cs
index f8a8a4ec4a..5a0122caa4 100644
--- a/Assets/SEE/UI/Menu/SimpleListMenu.cs
+++ b/Assets/SEE/UI/Menu/SimpleListMenu.cs
@@ -1,6 +1,6 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
using System.Linq;
-using UnityEngine.Events;
using UnityEngine.Windows.Speech;
namespace SEE.UI.Menu
@@ -98,6 +98,11 @@ public void RemoveEntry(T entry)
OnEntryRemoved?.Invoke(entry);
}
+ ///
+ /// Removes all menu entries.
+ ///
+ public void ClearEntries() => entries.ToList().ForEach(RemoveEntry);
+
///
/// Selects a menu entry.
/// It is assumed that the menu contains the entry.
@@ -145,26 +150,26 @@ protected override void HandleKeyword(PhraseRecognizedEventArgs args)
///
/// Triggers when was changed.
///
- public event UnityAction OnAllowNoSelectionChanged;
+ public event Action OnAllowNoSelectionChanged;
///
/// Triggers when was changed.
///
- public event UnityAction OnHideAfterSelectionChanged;
+ public event Action OnHideAfterSelectionChanged;
///
/// Triggers when an entry was added. ()
///
- public event UnityAction OnEntryAdded;
+ public event Action OnEntryAdded;
///
/// Triggers when an entry was removed. ()
///
- public event UnityAction OnEntryRemoved;
+ public event Action OnEntryRemoved;
///
/// Triggers when an entry was selected. ()
///
- public event UnityAction OnEntrySelected;
+ public event Action OnEntrySelected;
}
}
diff --git a/Assets/SEE/UI/OpeningDialog.cs b/Assets/SEE/UI/OpeningDialog.cs
index 56b8f27cfb..1fb481eabc 100644
--- a/Assets/SEE/UI/OpeningDialog.cs
+++ b/Assets/SEE/UI/OpeningDialog.cs
@@ -53,34 +53,30 @@ private IList SelectionEntries()
return new List
{
- new(selectAction: StartHost,
- unselectAction: null,
- title: "Host",
- description: "Starts a server and local client process.",
- entryColor: NextColor(),
- icon: Resources.Load("Icons/Host")),
+ new(SelectAction: StartHost,
+ Title: "Host",
+ Description: "Starts a server and local client process.",
+ EntryColor: NextColor(),
+ Icon: Icons.Broadcast),
- new(selectAction: StartClient,
- unselectAction: null,
- title: "Client",
- description: "Starts a local client connection to a server.",
- entryColor: NextColor(),
- icon: Resources.Load("Icons/Client")),
+ new(SelectAction: StartClient,
+ Title: "Client",
+ Description: "Starts a local client connection to a server.",
+ EntryColor: NextColor(),
+ Icon: Icons.Link),
#if ENABLE_VR
- new(selectAction: ToggleEnvironment,
- unselectAction: null,
- title: "Toggle Desktop/VR",
- description: "Toggles between desktop and VR hardware.",
- entryColor: NextColor(),
- icon: Resources.Load("Icons/Client")),
+ new(SelectAction: ToggleEnvironment,
+ Title: "Toggle Desktop/VR",
+ Description: "Toggles between desktop and VR hardware.",
+ EntryColor: NextColor(),
+ Icon: Icons.VR),
#endif
- new(selectAction: Settings,
- unselectAction: null,
- title: "Settings",
- description: "Allows to set additional network settings.",
- entryColor: Color.gray,
- icon: Resources.Load("Icons/Settings")),
+ new(SelectAction: Settings,
+ Title: "Settings",
+ Description: "Allows to set additional network settings.",
+ EntryColor: Color.gray,
+ Icon: Icons.Gear)
};
Color NextColor()
diff --git a/Assets/SEE/UI/PropertyDialog/ButtonProperty.cs b/Assets/SEE/UI/PropertyDialog/ButtonProperty.cs
index 96b77785ab..374fc2bb4d 100644
--- a/Assets/SEE/UI/PropertyDialog/ButtonProperty.cs
+++ b/Assets/SEE/UI/PropertyDialog/ButtonProperty.cs
@@ -10,7 +10,7 @@
namespace SEE.UI.PropertyDialog
{
///
- /// A button for a for a property dialog.
+ /// A button for a property dialog.
///
public class ButtonProperty : Property
{
@@ -30,9 +30,9 @@ public class ButtonProperty : Property
private GameObject button;
///
- /// Used to store the icon of the button.
+ /// The codepoint of the icon for the button.
///
- public Sprite IconSprite;
+ public char Icon;
///
/// Saves which method of the hide action is to be executed.
@@ -80,6 +80,7 @@ protected override void StartDesktop()
SetupTooltip();
SetUpButton();
+ return;
void SetUpButton()
{
@@ -87,10 +88,10 @@ void SetUpButton()
GameObject text = button.transform.Find("Text").gameObject;
GameObject icon = button.transform.Find("Icon").gameObject;
- if (!button.TryGetComponentOrLog(out ButtonManagerBasicWithIcon buttonManager)
+ if (!button.TryGetComponentOrLog(out ButtonManagerBasic buttonManager)
|| !button.TryGetComponentOrLog(out Image buttonImage)
|| !text.TryGetComponentOrLog(out TextMeshProUGUI textMeshPro)
- || !icon.TryGetComponentOrLog(out Image iconImage)
+ || !icon.TryGetComponentOrLog(out TextMeshProUGUI iconText)
|| !button.TryGetComponentOrLog(out PointerHelper pointerHelper))
{
return;
@@ -99,8 +100,8 @@ void SetUpButton()
textMeshPro.fontSize = 20;
buttonImage.color = ButtonColor;
textMeshPro.color = ButtonColor.IdealTextColor();
- iconImage.color = ButtonColor.IdealTextColor();
- iconImage.sprite = IconSprite;
+ iconText.color = ButtonColor.IdealTextColor();
+ iconText.text = Icon.ToString();
buttonManager.buttonText = Name;
buttonManager.clickEvent.AddListener(Clicked);
diff --git a/Assets/SEE/UI/RuntimeConfigMenu/RuntimeTabMenu.cs b/Assets/SEE/UI/RuntimeConfigMenu/RuntimeTabMenu.cs
index 4d2964f799..a6737ad38f 100644
--- a/Assets/SEE/UI/RuntimeConfigMenu/RuntimeTabMenu.cs
+++ b/Assets/SEE/UI/RuntimeConfigMenu/RuntimeTabMenu.cs
@@ -263,7 +263,7 @@ string GetButtonGroup(MemberInfo memberInfo) =>
(memberInfo.GetCustomAttributes().OfType().FirstOrDefault()
?? new RuntimeButtonAttribute(null, null)).Name;
- // ordered depending if a setting is primitive or has nested settings
+ // ordered depending on whether a setting is primitive or has nested settings
bool SortIsNotNested(MemberInfo memberInfo)
{
object value;
@@ -388,12 +388,11 @@ private GameObject CreateOrGetViewGameObject(IEnumerable attributes)
if (entry == null)
{
entry = new MenuEntry(
- () => { },
- () => { },
- tabName,
- $"Settings for {tabName}",
- GetColorForTab(),
- Resources.Load("Materials/Charts/MoveIcon")
+ SelectAction: () => { },
+ Title: tabName,
+ Description: $"Settings for {tabName}",
+ EntryColor: GetColorForTab(),
+ Icon: Icons.Move
);
AddEntry(entry);
}
diff --git a/Assets/SEE/UI/Tooltip.cs b/Assets/SEE/UI/Tooltip.cs
index 7da0438271..8bb293d948 100644
--- a/Assets/SEE/UI/Tooltip.cs
+++ b/Assets/SEE/UI/Tooltip.cs
@@ -1,4 +1,5 @@
using System;
+using System.IO;
using System.Linq;
using DG.Tweening;
using Michsky.UI.ModernUIPack;
@@ -221,6 +222,12 @@ public static void ActivateWith(string text, AfterShownBehavior afterShownBehavi
Instance.ChangeText(text, afterShownBehavior);
}
+ ///
+ /// Whether the tooltip is currently active.
+ /// Note that "active" does not necessarily mean that the tooltip is currently visible.
+ ///
+ public static bool IsActivated => Instance.text != null;
+
///
/// Will hide the tooltip by fading it out if it's currently visible.
/// If has been called prior to this and is active, it will be halted.
@@ -286,8 +293,7 @@ protected override void StartDesktop()
tooltipManager.allowUpdating = true;
// Move tooltip to front of layer hierarchy
tooltipManager.gameObject.transform.SetAsLastSibling();
- // tooltipObject only has 1 child, and will never have more than that
- if (tooltipManager.tooltipObject.transform.GetChild(0).gameObject.TryGetComponentOrLog(out canvasGroup))
+ if (tooltipManager.tooltipObject.transform.Find("Anchor/Content").gameObject.TryGetComponentOrLog(out canvasGroup))
{
// Get the actual text object
TextMeshProUGUI[] texts = tooltipManager.tooltipContent.GetComponentsInChildren();
diff --git a/Assets/SEE/UI/Window/CodeWindow/CodeWindow.cs b/Assets/SEE/UI/Window/CodeWindow/CodeWindow.cs
index 3c65aa0b09..8543c927c2 100644
--- a/Assets/SEE/UI/Window/CodeWindow/CodeWindow.cs
+++ b/Assets/SEE/UI/Window/CodeWindow/CodeWindow.cs
@@ -1,6 +1,9 @@
using System;
using System.Linq;
+using Cysharp.Threading.Tasks;
using DG.Tweening;
+using MoreLinq;
+using SEE.Tools.LSP;
using SEE.Utils;
using TMPro;
using UnityEngine;
@@ -52,6 +55,19 @@ public partial class CodeWindow : BaseWindow
///
private int lines;
+ ///
+ /// The LSP handler for this code window.
+ ///
+ /// Will only be set if the LSP feature is enabled and active for this code window.
+ ///
+ private LSPHandler lspHandler;
+
+ ///
+ /// The handler for the context menu of this code window, which provides various navigation options,
+ /// such as "Go to Definition" or "Find References".
+ ///
+ private ContextMenuHandler contextMenu;
+
///
/// Path to the code window content prefab.
///
@@ -88,26 +104,34 @@ public partial class CodeWindow : BaseWindow
private static TMP_WordInfo? lastHoveredWord;
///
- /// Visually marks the line at the given and scrolls to it.
- /// Will also unmark any other line. Sets to
- /// .
+ /// Whether the code window contains text.
+ ///
+ public bool ContainsText => text != null;
+
+ ///
+ /// Visually highlights the line number at the given and scrolls to it.
+ /// Will also unhighlight any other line. Sets to .
/// Clears the markers for line numbers smaller than 1.
///
- /// The line number of the line to mark and scroll to (1-indexed)
+ /// The line number of the line to highlight and scroll to (1-indexed)
public void MarkLine(int lineNumber)
{
+ const string markColor = "";
+ int markColorLength = markColor.Length;
markedLine = lineNumber;
- string[] allLines = textMesh.text.Split('\n').Select(x => x.EndsWith("