# ๐Ÿ“˜ Documentation: Flow Visualization Framework Based on .NET 8 ## ๐Ÿงฉ Project Overview This project is a **flow visualization framework** based on **.NET 8**. - All runtime dependencies, environment, and editor are **open-source** - Supports **secondary development**, suitable for scenarios such as embedded systems, industrial control, and data flow automation ๐Ÿ“บ **Bilibili Video Updates**: Project-related videos are periodically updated. Visit [my Bilibili profile](https://space.bilibili.com/33526379) for more. --- ## ๐Ÿ—“๏ธ Planned Tasks (Updated July 28, 2025) - โœ… Improving **"flowchart to C# code"** feature - ๐Ÿ”ฅ Designing **hot update mechanism** - ๐Ÿ”ง Designing **remote control logic** for multiple clients --- ## ๐Ÿ–Œ๏ธ How to Draw a Flow? ### ๐Ÿ› ๏ธ Preparation 1. Compile the `Serein.Workbench` project to ensure the workbench is operational 2. Create a class library project and reference `Serein.Library` (can also be acquired via Negut) ### โœจ Start Drawing 1. In the class library, add a class and mark it with the `[DynamicFlow]` attribute 2. Mark methods with the `[NodeAction]` attribute 3. Compile the project and drag the generated DLL into the left "Library" panel of the workbench 4. The workbench will automatically parse and load all node methods ### ๐ŸŽจ Draw Node Flows 1. Create a new canvas in the workbench 2. Drag methods from the left library panel onto the canvas to generate nodes 3. Drag between node connectors to create links, representing data/control flow 4. Repeat to build a complete flow ### โ–ถ๏ธ Run the Flow - **Run from start node**: - Set a node as "start node" โ†’ Click "Run" โ†’ Select "Run from current canvas" - **Run from a specific node**: - Select a single node โ†’ Press `F5` - **Run all canvases**: - In the "Run" menu, choose "Run all canvases" ### ๐Ÿ’พ Save/Load Projects - **Save Project**: `View` โ†’ `Save Project` โ†’ Choose save path - **Load Project**: `View` โ†’ `Load Local Project` โ†’ Choose project file ### ๐Ÿฉต View Output Logs - View logs, exceptions, and debug info via `View` โ†’ `Output Window` --- ## ๐Ÿงฑ How to Make a Method a Flow Node? - Mark methods with `[NodeAction]` attribute - Specify the appropriate node type (e.g., Action, Flipflop, Script, etc.) --- ## ๐Ÿ“š Key Interface Overview ### `IFlowContext` (Flow Context) > Core interface for data transfer between nodes, automatically injected by the runtime environment. #### ๐Ÿ”‘ Key Features - Global singleton environment interface, supports registration/retrieval (IoC pattern) - Context isolation per flow instance, preventing dirty data #### ๐Ÿ” Common Properties | Property | Type | Description | | ----------------- | ------ | --------------------------------------------------- | | `RunState` | Enum | Indicates flow run state (Init, Running, Completed) | | `NextOrientation` | Enum | Specifies next branch (Success, Failure, Exception) | | `Exit()` | Method | Terminates the current flow early | --- ## ๐Ÿงพ `DynamicNodeType` Enum Explained ### 1โƒฃ Nodes not Generated (Lifecycle Methods) | Enum Value | Description | | ---------- | -------------------------------------------------------- | | `Init` | Executes first at program start, suitable for init logic | | `Loading` | Called after all DLL `Init`s run, good for business init | | `Exit` | Invoked on shutdown, suitable for resource release | > Parameters are all `IFlowContext`. Return values can be async but are not handled by the framework. ### 2โƒฃ Basic Node Types #### ๐Ÿ“Œ `FlowCall` (Flow Interface Node) - Enables logic reuse across canvases - Supports shared (global sync) or isolated (local) parameter modes #### ๐Ÿ’ก `Script` (Script Node) - Executes dynamically via AST (Abstract Syntax Tree) - Built-in functions like `global()`, `now()` (see `Serein.Library.ScriptBaseFunc`) - Register more functions via: ```csharp SereinScript.AddStaticFunction("your function name", MethodInfo); ``` **Example:** ```csharp // Input is an object named "info" with Var, Data properties class Info { string PlcName; string Content; string LogType; DateTime LogTime; } plc = global("JC-PLC"); log = new Info() { Content = plc + " " + info.Var + " - Status Value: " + info.Data, PlcName = plc.Name, LogType = "info", LogTime = now(), }; return log; ``` #### ๐ŸŒ `GlobalData` (Global Data Node) - Get/share runtime data across nodes - Expression usage: `global("DataKey")` ### 3โƒฃ Nodes Generated from DLL Controls #### โš™๏ธ `Action` - Basic node type, input parameters auto-matched, supports async return #### ๐Ÿ” `Flipflop` (Trigger Node) - Can be triggered by external events or timeouts - Supports state returns (Success, Failure, Cancelled) and trigger source type #### ๐Ÿง  `ExpOp` (Expression Node) - Extracts sub-properties/fields/array/dictionary values - Examples: - `@Get .Array[22]` - `@Get .Dict["key"]` #### ๐Ÿ” `ExpCondition` (Conditional Expression Node) - Conditional logic based on bool/number/string **Example:** ```text .Age > 18 && data.Age < 35 or .Text.StartsWith("1100") ``` > `data` refers to the default name of the input object in expressions. #### ๐Ÿ–ผ๏ธ `UI` (Embedded Control) - Display custom `UserControl` on the workbench - Must return object implementing `IEmbeddedContent` **Sample Code:** ```csharp await context.Env.UIContextOperation.InvokeAsync(() => { var userControl = new UserControl(); adapter = new WpfUserControlAdapter(userControl, userControl); }); return adapter; public class WpfUserControlAdapter : IEmbeddedContent { private readonly UserControl userControl; private readonly IFlowControl flowControl; public WpfUserControlAdapter(UserControl userControl, IFlowControl flowControl) { this.userControl = userControl; this.flowControl= flowControl; } public IFlowControl GetFlowControl() { return flowControl; } public object GetUserControl() { return userControl; } } ``` --- ## โœ… Summary - This framework provides flexible flow editing, execution, and extension capabilities - Supports advanced features such as scripting, global data, and sub-flows - Suitable for AGV scheduling, PLC automation, visual logic control, and more --- > This documentation helps developers get started quickly and understand interface usage. For more information, refer to video demos or join the community discussion.