KanColleViewer プラグインの作り方などをダラダラと書きます。
(何か思いついたら適宜更新するかも)
※ KanColleViewer 4.2 現在のもの
チュートリアル
めとべや東京 #9 でLTしたやつ。
プラグイン開発用パッケージ一覧
NuGet Gallery から取得できる、プラグイン開発用のパッケージ郡です。
KanColleViewer.Composition のみ必須となります。
KanColleViewer.Composition
プラグイン向けのインターフェイス郡です。
これがないとプラグインが作れません。
詳細は「プラグイン インターフェイス一覧」を参照してください。
KanColleViewer.PluginAnalyzer
プラグイン開発を支援する Roslyn Analyzer & Fixer です。(要: VS 2015)
必要な実装方法や修正候補を提示してくれます。
インストール後、Visual Studio の再起動が必要な場合があります。
KanColleViewer.Controls
KanColleViewer のUI部品です。
Style, Theme も含みますので、UI があるプラグインならインストールした方が良いでしょう。
使用方法は KanColleViewer 本体で使用している部分を参照すると良いかと。
KanColleWrapper
KanColleViewer の通信部とデータ部です。
本体が保持するデータへのアクセスや、通信の読み取りに利用します。
大体のデータ構造
- KanColleClient
- KanColleProxy
- SessionSource
- ApiSessionSource
- Master
- Ships
- SlotItemEquipTypes
- SlotItems
- UseItems
- ShipTypes
- Missions
- MapAreas
- MapInfos
- MapCells
- Homeport
- Organization
- Ships
- Fleets
- CombinedFleet
- Materials
- Itemyard
- SlotItems
- UseItems
- Dockyard
- Repairyard
- Quests
- Admiral
- Organization
- KanColleProxy
Grabacr07.KanColleWrapper.KanColleClient
KanColleWrapper のコア部品です。
基本的にはここに全て集約されています。
インスタンスは KanColleClient.Current
で取得できます。
Grabacr07.KanColleWrapper.KanColleProxy
KanColleWrapper の通信部です。
SessionSource
から全HTTP通信データが、ApiSessionSource
から /kcsapi
以下の通信データが取得できます。
KanColleClient が解析していないデータは、これらを用いてプラグイン側で独自に解析することが可能です。
Grabacr07.KanColleWrapper.Master
api_start2
から取得された、艦これのマスターデータです。
Grabacr07.KanColleWrapper.Homeport
艦これのユーザーデータです。
api_start2
が降ってきて、KanColleClient.Current.IsStarted
が true
になるまでは null
なので注意。
プラグインコードで参照したい場合の変更通知購読方法は、Grabacr07.KanColleViewer.Models.NotifyService
の RegisterHomeportListener
の登録が参考になります。
Grabacr07.KanColleWrapper.Models.SvData
svdata=
から始まる艦これのjsonデータの解析に用います。
IObservable.TryParse<SvData<T>>()
で解析する際に頻出します。
Data
プロパティでレスポンスデータを、Request
プロパティでリクエストパラメーターを取得可能です。
KanColleClient.Current.Proxy.ApiSessionSource
.Where(x => x.Request.PathAndQuery == "/kcsapi/api_req_sortie/airbattle")
.TryParse<sortie_airbattle>().Subscribe(x => this.Update(x.Data));
プラグイン インターフェイス一覧
KanColleViewer.Composition に含まれる各種プラグインインターフェイスです。
プラグインアセンブリには IPlugin
インターフェイスを実装したクラスが最低1つは必要となります。
IPlugin
プラグインを表します。
画面や設定等が不要なプラグインは、これだけ実装すれば済むこともあるでしょう。
ITool
[ツール] タブに表示される画面を用意したい場合に実装します。
Member | Description |
---|---|
string Name | [ツール]タブに表示される名前 |
object View | [ツール]タブ内に表示するUIのルート要素 |
- Name プロパティは、長い名前をつけるとツールタブの幅が広がってしまうため、短めの名称をつけることをお勧めします。
- View プロパティは、当該プラグインのタブが開かれるたびに呼び出されます。
- 一見、毎度同一インスタンスを返せば良い用に思えますが、マルチウィンドウ時に正常に表示されなくなるため、今のところは毎回 new して返す必要があります。
- ViewModel は使いまわすことをお勧めします。
ISettings
プラグインの設定画面を用意したい場合に実装します。
Member | Description |
---|---|
object View | プラグイン一覧画面の[設定]リンクをクリック時に表示されるUIのルート要素 |
INotifier
通知要求を受けて、ユーザーに通知を行いたい場合に実装します。
Member | Description |
---|---|
void Notify(INotification notification) | 本体からの通知要求時に呼び出されます。 |
IRequestNotify
プラグイン側から本体に通知を要求したい場合に実装します。
Member | Description |
---|---|
event EventHandler‹NotifyEventArgs› NotifyRequested | 本体に通知要求を送りたい時に Invoke します。 |
ILocalizable
多言語対応を行いたい場合に実装します。
Member | Description |
---|---|
void ChangeCulture(string cultureName) | 言語設定が変更された際に呼びだされ、言語が通知されます。 |
ITaskbarProgress
タスク バーのプログレス インジケーターに状態を報告したい場合に実装します。
Member | Description |
---|---|
string Id | この機能をシステムが識別するための ID を取得します。 |
string DisplayName | この機能をユーザーが選択するときに識別するための名前を取得します。 |
TaskbarItemProgressState State | プログレス インジケーターに報告する現在の状態を取得します。 |
double Value | プログレス インジケーターに報告する現在の値を取得します。 |
event EventHandler Updated | State または Value が変更されたときに発生します。 |
プラグイン識別用属性(Export, ExportMetadata)のルール
この項については、基本的には KanColleViewer.PluginAnalyzer を入れていればそれが全部指摘してくれます。
- プラグイン インターフェイスを実装したら、対応する
Export
を記述しなければなりません。- MEF の仕組み上、
Export
属性を手がかりにプラグインが Import されるためです。
- MEF の仕組み上、
IPlugin
インターフェイスを実装したクラスは、ExportMetadata
のGuid
,Title
,Description
,Version
,Author
を記述しなければなりません。- その他のプラグイン インターフェイスを実装したクラスは、
ExportMetadata
のGuid
を記述しなければなりません。 ExportMetadata
のGuid
が同一なクラスは、同一プラグインとみなされます。- つまりもし機能別にクラスを分割した場合、機能側のクラスには、機能を付与したい
IPlugin
のクラスのGuid
と同じGuid
を記述する必要があります。 - 逆に1クラスに全て集約する場合は
Guid
のExportMetadata
の記述は1つで済みます。
- つまりもし機能別にクラスを分割した場合、機能側のクラスには、機能を付与したい
画面系プラグインのデザイナ表示に必要な Styles
画面系プラグインを実装する場合、そのままではXAMLデザイナ上で実行時の表示を確認することができません。
デザイナで確認したい場合は、以下のような ResourceDictionary を読み込むようにしてください。
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/MetroRadiance;component/Styles/Colors.xaml" />
<ResourceDictionary Source="pack://application:,,,/MetroRadiance;component/Styles/Controls.xaml" />
<ResourceDictionary Source="pack://application:,,,/MetroRadiance;component/Styles/Controls.Button.xaml" />
<ResourceDictionary Source="pack://application:,,,/MetroRadiance;component/Styles/Controls.CheckBox.xaml" />
<ResourceDictionary Source="pack://application:,,,/MetroRadiance;component/Styles/Controls.Expander.xaml" />
<ResourceDictionary Source="pack://application:,,,/MetroRadiance;component/Styles/Controls.FocusVisualStyle.xaml" />
<ResourceDictionary Source="pack://application:,,,/MetroRadiance;component/Styles/Controls.PasswordBox.xaml" />
<ResourceDictionary Source="pack://application:,,,/MetroRadiance;component/Styles/Controls.RadioButton.xaml" />
<ResourceDictionary Source="pack://application:,,,/MetroRadiance;component/Styles/Controls.Scrollbar.xaml" />
<ResourceDictionary Source="pack://application:,,,/MetroRadiance;component/Styles/Controls.Tooltip.xaml" />
<ResourceDictionary Source="pack://application:,,,/MetroRadiance;component/Styles/Icons.xaml" />
<ResourceDictionary Source="pack://application:,,,/MetroRadiance;component/Themes/Dark.xaml" />
<ResourceDictionary Source="pack://application:,,,/MetroRadiance;component/Themes/Accents/Purple.xaml" />
<ResourceDictionary Source="pack://application:,,,/KanColleViewer.Controls;component/Styles/Colors.xaml" />
<ResourceDictionary Source="pack://application:,,,/KanColleViewer.Controls;component/Styles/Controls.xaml" />
<ResourceDictionary Source="pack://application:,,,/KanColleViewer.Controls;component/Styles/Controls.HorizontalFlatListBox.xaml" />
<ResourceDictionary Source="pack://application:,,,/KanColleViewer.Controls;component/Styles/Controls.ListView.xaml" />
<ResourceDictionary Source="pack://application:,,,/KanColleViewer.Controls;component/Styles/Controls.PinButton.xaml" />
<ResourceDictionary Source="pack://application:,,,/KanColleViewer.Controls;component/Styles/Controls.TabControl.xaml" />
<ResourceDictionary Source="pack://application:,,,/KanColleViewer.Controls;component/Styles/Controls.Text.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
加えて、画面のルート要素に以下の設定を行ってください。
Background="{DynamicResource ThemeBrushKey}"
Foreground="{DynamicResource ActiveForegroundBrushKey}"
なお MetroRadiance のアクセントカラーですが、プラグイン側で読み込んでしまうと本体側のアクセントカラーの変更に追従できなくなるため、追従したい場合は現状では読み込まないようにする必要があります。
→ MetroRadiance が修正され、追従できるようになりました。
また上記で Controls.xaml の内容を全て展開しているのは、ネストした MergedDictionaries をデザイナがうまく解釈してくれないためです。
その他利用できるライブラリ
本体が使っているライブラリに関しては、プラグイン側で導入しても特別なにもしないでも動作するはずです。
それ以外のライブラリについては、プラグイン インストール時にパスの通るフォルダに DLL を配置する必要があるでしょう。
以下は本体でも利用しており、プラグイン開発にも便利なライブラリ群です。
Livet
参照 : Livet – ProjectHome – the sea of fertility
StatefulModel
参照 : StatefulModelについて – the sea of fertility
Rx (Reactive Extensions)
参照 : Rx入門 – xin9le.net
MetroRadiance
参照 : ウィンドウの枠を簡単に光らせるライブラリを公開しました | grabacr.nét
MetroTrilithon
設定ファイル保存に使える SerializableProperty
、FileSettingsProvider
や、クリック時に VM の指定メソッドを呼び出せる CallMethodButton
、各種 Converter 等を含みます。
使い方は KanColleViewer.exe のソースを参照すると良いでしょう。
設定関連は Grabacr07.KanColleViewer.Models.Settings
名前空間にあります。
小ネタ
プラグイン読み込みタイミング
プラグインは、アプリケーション起動後、通信開始前に読み込まれます
KanColleViewer.exe の Grabacr07.KanColleViewer.Composition.PluginService
にてプラグインを読み込んでいますので、詳細が知りたい場合はそちらを参照してください。
プラグインのデバッグ実行
プロセスにアタッチするか、本体付属のプラグイン同様、ソリューションの Plugins
フォルダに追加してしまう手があります。
Plugins
フォルダに入れる場合は、他のプラグイン同様ビルド イベントを用いてバイナリが自動的にコピーされるようにすると便利でしょう。
mkdir "$(SolutionDir)Grabacr07.KanColleViewer\bin\$(ConfigurationName)\Plugins"
xcopy /Y "$(TargetDir)*.*" "$(SolutionDir)Grabacr07.KanColleViewer\bin\$(ConfigurationName)"
move "$(SolutionDir)Grabacr07.KanColleViewer\bin\$(ConfigurationName)\$(TargetName).*" "$(SolutionDir)Grabacr07.KanColleViewer\bin\$(ConfigurationName)\Plugins"
プラグイン プロジェクトの新規作成
「クラス ライブラリ」テンプレートでも良いのですが、画面系の場合はどうせユーザー コントロールを作ることになるため、「WPF ユーザー コントロール ライブラリ」で作成することをお勧めします。
プラグインでリソースの後始末とかしたい場合
IDisposable を実装しておけば、MEF が勝手に Dispose() 呼んでくれるっぽい。
Managed Extensibility Framework – Documentation
Parts that implement IDisposable will have the Dispose method called
- IPlugin の生存期間はアプリの起動時~終了時
- アプリ終了時に CompositionContainer のデストラクタが Dispose() 呼んでくれてる気がする
- 今のところ(ver.4.2)クラッシュした時はダメかもしれんね