Editor 専用の C++ プラグインまたはツールからネイティブ Developer API を使います。利用する Editor モジュールの依存関係に Locus モジュールを追加し、取得には Locus.h、リクエストと結果には Developer/LocusDeveloperApi.h をインクルードします。
ライフタイムと非同期契約
Section titled “ライフタイムと非同期契約”GetLocusDeveloperApi() はアクティブな FLocusDeveloperApi を返します。初期化された Locus Editor のライフタイム外では nullptr です。
- Game Thread で取得と送信を行います。
- サブシステムまたはモジュールのシャットダウンをまたいで API ポインターを保持しないでください。
- すべての完了は Game Thread で正確に 1 回実行されます。
- 受け付けられた作業は、Locus の既存エグゼキューターの後続 tick で完了します。
- 受付に失敗した場合、送信から戻る前にインラインで完了することがあります。
- 送信前にコールバックが所有する状態を準備します。
- キャンセルは協調的です。キューに入った作業は防げますが、リポジトリ処理を中断したり、永続化が確定した変更を後からキャンセル結果に変えたりはできません。
- ブロッキング待機、スリープ、Game Thread のポンピング、
Future.Get()を追加しないでください。
返される FLocusDeveloperRequestHandle はリクエスト ID とスレッドセーフな協調的 Cancel() を公開します。
ドキュメントを作成する
Section titled “ドキュメントを作成する”#include "Locus.h"#include "Developer/LocusDeveloperApi.h"
void CreateCombatDocument(){ FLocusDeveloperApi* Locus = GetLocusDeveloperApi(); if (Locus == nullptr) { return; }
FLocusDeveloperCreateDocumentRequest Request; Request.Path = TEXT("Design/Combat.md"); Request.Markdown = TEXT("# Combat\n"); Request.PresentationRoot = ELocusDeveloperDocumentPresentationRoot::LocusDocuments;
FLocusDeveloperRequestHandle Handle = Locus->CreateDocument( MoveTemp(Request), [](TLocusDeveloperResult<FLocusDeveloperDocumentSnapshot> Result) { if (!Result.IsSuccess()) { UE_LOG(LogTemp, Error, TEXT("Locus: %s"), *Result.Error.Message); return; }
const FLocusDeveloperDocumentSnapshot& Document = Result.Value.GetValue(); UE_LOG(LogTemp, Display, TEXT("Created %s"), *Document.Identity.RelativePath); });
// Retain Handle only if this tool needs to offer cancellation.}入力パスは、選択した具体的な表示ルートからの相対パスです。返される ID は、ProjectDocuments を基準にした権威のあるパスのままです。
取得してから更新する
Section titled “取得してから更新する”リビジョン処理を隠さないでください。読み取り結果のリビジョンを変更の事前条件として使います。
FLocusDeveloperGetDocumentRequest GetRequest;GetRequest.Identity.RelativePath = TEXT("Design/Combat.md");
Locus->GetDocument( MoveTemp(GetRequest), [Locus](TLocusDeveloperResult<FLocusDeveloperDocumentSnapshot> GetResult) { if (!GetResult.IsSuccess()) { return; }
const FLocusDeveloperDocumentSnapshot& Current = GetResult.Value.GetValue(); FLocusDeveloperUpdateDocumentRequest UpdateRequest; UpdateRequest.Identity = Current.Identity; UpdateRequest.ExpectedRevision = Current.Revision; UpdateRequest.Markdown = Current.Markdown + TEXT("\n## Abilities\n");
Locus->UpdateDocument( MoveTemp(UpdateRequest), [](TLocusDeveloperResult<FLocusDeveloperDocumentSnapshot> Result) { if (Result.Error.Code == ELocusDeveloperErrorCode::StaleRevision) { // Reread before reconsidering the mutation. } }); });ノートスコープを明示する
Section titled “ノートスコープを明示する”FLocusDeveloperCreateNoteRequest Request;Request.Scope = ELocusDeveloperScope::Private;Request.Title = TEXT("Local investigation");Request.Body = TEXT("Not shared with the project repository.");Request.Tags = {TEXT("investigation")};
FLocusDeveloperRequestHandle Handle = Locus->CreateNote( MoveTemp(Request), [](TLocusDeveloperResult<FLocusDeveloperNoteSnapshot> Result) { if (Result.IsSuccess()) { const FLocusDeveloperNoteIdentifier Identity = Result.Value->Identity; // GUID + Private scope } });スコープのフィルターも明示的です。All にはプライベートコンテンツが含まれるため、ツールで共有コンテンツを含めない場合は Shared を要求します。
基本的なピンの作成
Section titled “基本的なピンの作成”FLocusDeveloperCreatePinRequest Request;Request.Scope = ELocusDeveloperScope::Shared;Request.WorldAssetPath = TEXT("/Game/Maps/Main.Main");Request.WorldLabel = TEXT("Main");Request.Location = FVector(120.0, 40.0, 180.0);Request.Title = TEXT("Check encounter cover");Request.PinType = ELocusDeveloperPinType::Issue;
FLocusDeveloperRequestHandle Handle = Locus->CreatePin( MoveTemp(Request), [](TLocusDeveloperResult<FLocusDeveloperPinSnapshot> Result) { if (!Result.IsSuccess()) { UE_LOG(LogTemp, Warning, TEXT("Pin create failed: %s"), LexToString(Result.Error.Code)); } });ピンの作成には、サポートされる保存済みプロジェクト所有ワールドが必要です。メタデータの更新では、位置、ワールド、アンカー、ビュー、スコープが保持されます。
操作マトリックス、ID の契約、エラー分類、リビジョン、操作ステータスについては、Developer API の概要を参照してください。