diff --git a/Library/Extensions/Builder/BlocklyExtensions.cs b/Library/Extensions/Builder/BlocklyExtensions.cs index aed6c2c..e0709fc 100644 --- a/Library/Extensions/Builder/BlocklyExtensions.cs +++ b/Library/Extensions/Builder/BlocklyExtensions.cs @@ -234,6 +234,7 @@ public static TParser AddCustomBlocks(this TParser parser, IScriptModel /* Add library extensions: blocks, any order. */ builder.AddBlock(); builder.AddBlock(); + builder.AddBlock(); builder.AddBlock(); builder.AddBlock(); builder.AddBlock(); diff --git a/Library/Extensions/ExecutionGroup.cs b/Library/Extensions/ExecutionGroup.cs new file mode 100644 index 0000000..993ba4d --- /dev/null +++ b/Library/Extensions/ExecutionGroup.cs @@ -0,0 +1,56 @@ +using System.Diagnostics.CodeAnalysis; +using System.Dynamic; +using BlocklyNet.Core.Model; +using BlocklyNet.Extensions.Builder; +using Newtonsoft.Json; + +namespace BlocklyNet.Extensions; + +/// +/// Execute a function as a Blockly.NET group. +/// +[CustomBlock( + "execute_group", + "", + @"{ + ""message0"": ""ExecutionGroup %1 %2 %3"", + ""args0"": [ + { + ""type"": ""input_dummy"" + }, + { + ""type"": ""field_label_serializable"", + ""name"": ""RESULT"", + ""text"": ""Result"" + }, + { + ""type"": ""input_value"", + ""name"": ""RESULT"" + } + ], + ""previousStatement"": null, + ""nextStatement"": null, + ""colour"": ""#107159"", + ""tooltip"": ""Execute something as a group."", + ""helpUrl"": """" + }", + "" +)] +public class ExecutionGroup : Block +{ + /// + public override async Task EvaluateAsync(Context context) + { + /* Register the group. */ + context.Engine.BeginGroup(Id); + + /* Execute the function to get the group result. */ + var groupResult = await Values.EvaluateAsync("RESULT", context); + + /* Finish the group. */ + context.Engine.EndGroup(groupResult); + + /* Continue with execution. */ + return await base.EvaluateAsync(context); + } +} diff --git a/Library/Scripting/Engine/IScriptSite.cs b/Library/Scripting/Engine/IScriptSite.cs index 94a52c4..4bd550e 100644 --- a/Library/Scripting/Engine/IScriptSite.cs +++ b/Library/Scripting/Engine/IScriptSite.cs @@ -79,4 +79,15 @@ public interface IScriptSite /// /// The block to execute. Task SingleStepAsync(Block block); + + /// + /// Start the execution of a new group. + /// + /// Unique identifier of the group. + void BeginGroup(string key); + + /// + /// End the execution of the current group. + /// + void EndGroup(object? result); } \ No newline at end of file diff --git a/Library/Scripting/Engine/ScriptEngine.Nested.cs b/Library/Scripting/Engine/ScriptEngine.Nested.cs index 18466dd..de0dc8f 100644 --- a/Library/Scripting/Engine/ScriptEngine.Nested.cs +++ b/Library/Scripting/Engine/ScriptEngine.Nested.cs @@ -72,6 +72,16 @@ protected class ScriptSite(ScriptEngine engine, IScript? parent, int depth) : IS public Task EvaluateAsync(string scriptAsXml, Dictionary presets) => _engine.Parser.Parse(scriptAsXml).EvaluateAsync(presets, this); + /// + public void BeginGroup(string key) + { + } + + /// + public void EndGroup(object? result) + { + } + /// public Task RunAsync(StartScript request, StartScriptOptions? options = null) => _engine.StartChildAsync(request, CurrentScript, options, depth); diff --git a/Library/Scripting/Engine/ScriptEngine.cs b/Library/Scripting/Engine/ScriptEngine.cs index ae76ffd..0712f34 100644 --- a/Library/Scripting/Engine/ScriptEngine.cs +++ b/Library/Scripting/Engine/ScriptEngine.cs @@ -16,7 +16,10 @@ namespace BlocklyNet.Scripting.Engine; /// Dependency injection manager. /// Logging helper. /// Script parser to use. -public partial class ScriptEngine(IServiceProvider _rootProvider, IScriptParser parser, ILogger logger, IScriptEngineNotifySink? context = null) : IScriptEngine, IScriptSite, IDisposable +public partial class ScriptEngine(IServiceProvider _rootProvider, IScriptParser parser, ILogger logger, IScriptEngineNotifySink? context = null) : + IScriptEngine, + IScriptSite, + IDisposable { /// public IScriptEngine Engine => this; @@ -429,4 +432,14 @@ protected virtual ScriptFinished CreateFinishNotification(IScriptInstance script /// public Task SingleStepAsync(Block block) => Task.CompletedTask; + + /// + public void BeginGroup(string key) + { + } + + /// + public void EndGroup(object? result) + { + } }