外掛開發
最簡單的外掛形式就是一個普通的 C# 類。如果你只想公開一些簡單的函式,請使用靜態類:
public static class MyPlugin
{
public static int GetValue() => 15;
}
1. 外掛功能標誌
宿主通過 PluginFeature 標誌公開一組能力。在嘗試使用某個子系統之前,外掛應呼叫 GetFeatureSet() 並檢查相關標誌。可用的功能如下:
- Menus (1) 宿主可以建立新的頂級選單和巢狀子選單。
- DynamicPackages (2) 宿主可以在執行時向 Divooka 的工具箱中新增新的節點型別(通常稱為“包”)。
- EditorQuery (4) 宿主允許查詢和修改圖的執行時狀態(例如讀取節點值、連線/斷開引腳)。
- ConnectorVisualCustomizations (8) 宿主允許自訂節點引腳連線的外觀(形狀 + 顏色)。
- CustomNodeSurface (16) [已過時] 已計劃但尚未實現:完全自訂節點表面(超出內建的引腳/聯結器渲染範圍)。
- PreviewProcessor (32) 宿主支援註冊例程,將任意資料轉換為 Divooka 可以原生預覽的型別(例如影像、文字、圖)。
- CustomPreviewControl (64) [已過時] 已計劃但尚未實現:嵌入自訂預覽控制元件(例如自訂的 WPF 或 Godot 控制元件)。
- CustomPreviewHandler (128) 宿主支援為任何節點型別提供完全自訂的“彈出式”預覽處理程式(外掛完全控制預覽在單獨視窗中的渲染方式)。
外掛應通過按位運算組合這些標誌(例如 if ((features & PluginFeature.Menus) != 0) { … }),以確定在執行時要註冊或啟用哪些內容。
2. 選單註冊
外掛確認 PluginFeature.Menus 可用後,就可以向 Divooka 的主選單欄新增選單項並註冊巢狀子選單。每個選單項在被按一下時呼叫一個回撥。
// Add or remove a top‑level menu item:
void RegisterMenu(
string menu, // unique identifier (e.g. "MyPlugin/Tools")
string title, // user‑facing text
string? tooltip, // optional hover text
Action<IDivookaEngineHostEnvironment> clickCallback,
bool autoUnregister // if true, host will remove it on plugin unload
);
void UnregisterMenu(string menu, string title);
// Add or remove a submenu under an existing menu:
void RegisterSubmenu(
string menu, // same “menu” key as above
string submenu, // unique identifier for the submenu entry
string title,
string? tooltip,
Action<IDivookaEngineHostEnvironment> clickCallback,
bool autoUnregister
);
void UnregisterSubMenu(string menu, string submenu, string title);
- 要點
menu和submenu是識別符號(不一定是顯示的文字)。title是終端使用者看到的內容。autoUnregister讓宿主在外掛解除安裝時進行清理。
3. 節點聯結器外觀
如果支援 ConnectorVisualCustomizations,外掛就可以為任意給定的資料型別自訂引腳(輸入/輸出埠)和連線的外觀。
void RegisterTypeConnectionAppearance(
Type type, // the .NET type to style (e.g., typeof(MyCustomData))
BuiltinConnectorShape shape, // one of: HollowCircle, SolidSquare, etc.
Color color // base color for the connector (e.g., System.Drawing.Color.Red)
);
BuiltinConnectorShape一個包含內建形狀的小型列舉(HollowCircle、HollowRectangle、HollowTriangle、HollowArrow、HollowSquare,以及對應的“Solid”形狀)。- 用法 儘早註冊(例如在外掛初始化期間)。之後,Divooka 會使用你選擇的形狀 + 顏色來渲染所有承載該 CLR 型別的引腳。
4. 預覽處理
Divooka 允許節點為其資料提供一個小型預覽(例如顯示影像、文字片段或圖)。有兩種不同的擴充點:
Preview Processor(需要
PreviewProcessor標誌)void RegisterPreviewProcessor( Type type, // the data type your plugin wants to handle Func<object, object> processor // a function that converts “type” into a built‑in previewable type (e.g., Bitmap, string, List<float>, etc.) );- 何時使用: 如果你的外掛的節點輸出 Divooka 無法原生渲染的自訂資料型別,請實現一個處理器,把它轉換為宿主已經知道如何顯示的型別。
- 示例:
將
MyImageData例項轉換為System.Drawing.Bitmap。
Custom Preview Handler(需要
CustomPreviewHandler標誌)void RegisterCustomPreviewHandler( Type instanceType, // the .NET type for which you supply full control Action<ProcessorNode, object> previewHandler );- 何時使用: 如果你需要一個宿主無法處理的完全自訂的彈出式預覽(例如互動式圖表或 3D 檢視)。
- 行為:
每當使用者請求預覽時,Divooka 都會呼叫你的
previewHandler,並將節點例項以及原始資料物件傳給你。你的程式碼負責顯示視窗或控制元件、渲染內容、掛接關閉事件等。注意:這隻能以單獨的彈出視窗形式工作,不能內嵌在畫布上。
5. 動態型別 / 工具箱註冊
如果啟用了 DynamicPackages,外掛就可以向 Divooka 告知新的節點型別——既包括後端功能(節點做什麼),也包括前端工具箱條目(它在介面中出現在哪裡)。RegisterPackages 呼叫統一處理以下幾類定義集合:
void RegisterPackages(
IEnumerable<ToolboxIndexer.AssemblyToolboxDefinition>? assemblyToolboxes,
IEnumerable<ToolboxIndexer.FrontendToolboxDefinition>? frontendToolboxes,
IEnumerable<ToolboxIndexer.TypeToolboxDefinition>? typedToolboxes,
IEnumerable<ToolboxIndexer.SpecificToolboxEndPointDefinition>? specificEndpoints,
IEnumerable<ToolboxIndexer.ProceduralContextBaseTypeDefinition>? proceduralContextTypes,
bool autoUnregister = true
);
AssemblyToolboxDefinition定義整個程式集的節點——Divooka 可以在執行時掃描程式集,找到被註解為節點的類,然後自動填充工具箱。FrontendToolboxDefinition描述你希望如何在 Divooka 的介面中對節點進行分組和標註(例如資料夾圖示、類別)。TypeToolboxDefinition將單個 .NET 型別顯式註冊為節點——如果你希望精細控制其名稱、圖示和出現位置,這會很有用。SpecificToolboxEndPointDefinition讓你可以把一個節點放在多個位置,或放在專門的上下文選單下。ProceduralContextBaseTypeDefinition如果你的外掛提供了一個“過程式上下文”(一種以自訂方式執行一組節點的有狀態環境),就在這裡註冊其基型別,讓 Divooka 瞭解你的執行時執行模型。
註冊完成後,Divooka 的介面會在工具箱中顯示這些新的節點型別;使用者可以像使用內建節點一樣,將它們拖放到畫布上。
6. 過程式上下文執行執行器
對於引入自訂過程式執行上下文的外掛,請使用:
void RegisterProceduralContextExecutionRunner(
Type baseType, // the abstract base for all of your procedural contexts
Type instantiatorType // a factory/runner class that knows how to execute that context
);
- 用途
告訴 Divooka:“每當一個以派生自
baseType的型別為根的節點圖需要執行時,就使用這個instantiatorType來執行它。” - 行為 Divooka 會在執行時例項化你的執行器並把節點圖交給它;你的執行器負責遍歷節點、按正確的順序對它們求值併產生輸出。
7. 總結
- 啟動時
- 查詢
GetFeatureSet()。 - 如果支援選單,則按條件呼叫
RegisterMenu/RegisterSubmenu。 - 如果你有自訂資料型別,呼叫
RegisterTypeConnectionAppearance為它們設定獨特的引腳形狀/顏色。 - 如果你想新增新節點,請準備好工具箱定義(程式集掃描、型別描述符等)並呼叫
RegisterPackages。
- 查詢
- 外掛初始化期間
- 如果需要為預覽轉換節點輸出,請使用
RegisterPreviewProcessor註冊一個處理器。 - 如果需要完全控制預覽(例如在浮動視窗中顯示 3D 模型),請使用
RegisterCustomPreviewHandler註冊一個處理程式。 - 如果你的節點需要特殊的執行環境,請註冊一個 ProceduralContextExecutionRunner。
- 如果需要為預覽轉換節點輸出,請使用
- 關閉(或解除安裝)時
- 如果你設定了
autoUnregister = true,那麼當 Divooka 解除安裝外掛時,大多數註冊內容(選單、包、預覽處理程式)都會被自動清理。否則,請顯式呼叫UnregisterMenu、UnregisterSubMenu以及所需的任何自訂清理操作。
- 如果你設定了
外掛作者檢查清單
功能檢測
var features = host.GetFeatureSet(); if ((features & PluginFeature.Menus) != 0) RegisterMenus(); if ((features & PluginFeature.DynamicPackages) != 0) RegisterPackages(...); // etc.選單
- 使用
RegisterMenu/RegisterSubmenu新增按一下即執行的操作。 - 始終提供唯一的鍵(例如
"MyPlugin/Tools/DoSomething")。
- 使用
節點外觀
- 使用
RegisterTypeConnectionAppearance(typeof(MyType), BuiltinConnectorShape.SolidCircle, Color.Blue)為MyType的節點設定藍色圓形引腳。
- 使用
預覽支援
- 如果你的節點輸出自訂資料型別,請實現
Func<object, object>,將其轉換為現有的可預覽物件(字串、Bitmap、陣列等)。 - 如果你需要彈出式編輯器,或者需要 Divooka 無法原生預覽的內容,請實現自訂預覽處理程式。
- 如果你的節點輸出自訂資料型別,請實現
動態型別(工具箱)
- 在
RegisterPackages中提供一個或多個工具箱定義。 - 如果只想掃描整個程式集,請使用
AssemblyToolboxDefinition。如果想嚴格控制單個節點的後設資料,請使用TypeToolboxDefinition。
- 在
執行
- 如果你的外掛包含必須在專門上下文中執行的節點,請註冊一個
ProceduralContextExecutionRunner,將你的圖的基型別對映到某個執行器/工廠。
- 如果你的外掛包含必須在專門上下文中執行的節點,請註冊一個
上述各部分就緒後,Divooka 會自動顯示你的選單、渲染你的節點引腳、讓使用者把你的自訂節點型別拖入圖中,並且在使用者按一下“Run”或請求預覽時,在底層呼叫你的轉換器或自訂預覽程式碼。
通過把功能歸入這六個方面(功能標誌、選單、節點外觀、預覽、動態型別註冊和執行執行器),你可以確保外掛與 Divooka 的宿主環境順暢整合,並遵循預期的擴充點。
另請參閱
更多 C# 技巧。