YMM4 Plugin 制作メモ

ゆっくりムービーメーカー4(YMM4)のプラグイン機能について
- 2023/09/01についにプラグイン機能が公開された
- 公式
- プラグインを使用する | 饅頭遣いのおもちゃ箱
- プラグインを作成する | 饅頭遣いのおもちゃ箱
- repo
- manju-summoner/YukkuriMovieMaker4PluginSamples: YMM4用プラグインのサンプル集です
- manju-summoner/YukkuriMovieMaker.Plugin.Community: YMM4コミュニティで開発するYMM4プラグインです。 プラグインのサンプルも兼ねています。 ここで開発されたプラグインはYMM4にデフォルトで組み込まれます。
- manju-summoner/SampleReversePlaybackAudioEffectPlugin: キャッシュ機構を備えたYMM4音声エフェクトの実装サンプルです。音声の逆再生機能を提供します。ただし、仮実装のため実用には適しません。
- .NET SDK 9でプラグインを開発できる
- ※基本的に最新バージョンが必要
有志
- プラグイン作成準備
-
ymm4-plugin-document: 総合概要
- 自動生成APIドキュメント
-
YMM4 API Documentation
- エフェクト系のAPI説明中心
-
DeepWiki
manju-summoner/YukkuriMovieMaker4PluginSamples- AIでサンプルリポジトリを解析させたリファレンスサイト
自作
- InuInu2022/YmmeUtil: YMM4 Plugin utilities library
- InuInu2022/ymme-vscode-boilerplate: YMM4 plugin boilerplate template repository
- InuInu2022/YMM4VoiSonaPlugin: YMM4 Plugin for VoiSona Talk (unofficial)
- InuInu2022/YMM4SquirclePlugin: YMM4 スクワークル (Squircle) 角丸プラグイン
- InuInu2022/YMM4OpenJTalkPlugin: Open JTalk plugin for YMM4 (unofficial)
- InuInu2022/YMM4ObjectListPlugin: YMM4 オブジェクトリスト プラグイン)
解説記事

VSCode + dotnet cliで開発する
公式には本家VSの開発情報だけだが、csproj
の書き方工夫でVSCode+dotnet cliでもプラグイン作れる。
csprojの書き方
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0-windows10.0.19041.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<UseWPF>true</UseWPF>
</PropertyGroup>
<ItemGroup>
<!-- YMM4 plugins -->
<Reference Include="path\to\YukkuriMovieMaker4\YukkuriMovieMaker.Plugin.dll" />
<Reference Include="path\to\YukkuriMovieMaker4\YukkuriMovieMaker.Controls.dll" />
<!-- 環境変数を使う場合
<Reference Include="$(YMM4_PATH)\YukkuriMovieMaker.Plugin.dll" />
<Reference Include="$(YMM4_PATH)\YukkuriMovieMaker.Controls.dll" />
-->
<!-- ビルド時にdllを展開しない -->
<!--
<Reference Include="$(YMM4_PATH)\YukkuriMovieMaker.Plugin.dll">
<Private>false</Private>
<CopyLocal>false</CopyLocal>
</Reference>
<Reference Include="$(YMM4_PATH)\YukkuriMovieMaker.Controls.dll">
<Private>false</Private>
<CopyLocal>false</CopyLocal>
</Reference>
-->
</ItemGroup>
</Project>
cliコマンドdotnet add reference
でいけるかどうかは不明なので手書き。
パス
YMM4のメニューの「ヘルプ」>「その他」>「アプリケーションフォルダを開く」でYukkuriMovieMaker.Plugin.dll
へのパスを取得。
環境変数などに登録しておくと良い
- 例:
YMM4_PATH
- csproj内では
$(YMM4_PATH)
でパスが参照できる
<Reference Include="$(YMM4_PATH)\YukkuriMovieMaker.Plugin.dll" />
<Reference Include="$(YMM4_PATH)\YukkuriMovieMaker.Controls.dll" />
SampleSAPI5VoicePluginはdotnet cliでビルドできない
manju-summoner/YukkuriMovieMaker4PluginSamples: YMM4用プラグインのサンプル集です
以下にあるように、利用しているmsbuildが.NET Framework版である必要がある。そのままのdotnet build
では.NET Core系のmsbuildが呼ばれるため。

.NET SDK 8.0 移行
YMM v4.23.0.0で.NET7から.NET8に移行したため、プロジェクトの<TargetFramework>をnet7.0-windows10.0.19041.0からnet8.0-windows10.0.19041.0に変更する必要があります。
ゆっくりMovieMaker v4.22.x.x以前に作成されたプロジェクトファイルの移行手順
未検証だけど <TargetFrameworks>で.NET7/8両対応ビルドできるかも?
<TargetFrameworks>net7.0-windows10.0.19041.0;net8.0-windows10.0.19041.0;</TargetFrameworks>
dllの依存関係でダメかな?
参照先を変えれば?
→ だめだった…

dotnet publish で ymme をつくる
やりかた
- MSBuildをつかってpublish -> zip圧縮 -> ymmeリネーム -> プラグインフォルダへ配置まで一括でやる
csproj
-
$(YMM4_PATH)
は環境変数で通しておく -
ビルド前に出力先をクリアしておくTarget
<Target Name="RemovePublishDirBeforeBuild" BeforeTargets="BeforeBuild">
<RemoveDir Directories="$(OutputPath)/publish/" />
<RemoveDir Directories="$(YMM4_PATH)\user\plugin\$(AssemblyName)\"/>
<Message Text="RemovePublishDirBeforeBuild" Importance="high" />
</Target>
- publish後にいろいろするTarget
<Target Name="MakeZipPackage" AfterTargets="Publish">
<!-- 一旦ymmeの出力先 -->
<MakeDir Directories="$(OutputPath)/../../../../../publish/" />
<ItemGroup>
<!-- 不要なファイルをymmeに取り込まない様にここで指定する -->
<FilesToDelete Include="$(OutputPath)\publish\YukkuriMovieMaker.*.dll"/>
</ItemGroup>
<Delete Files="@(FilesToDelete)">
<Output
TaskParameter="DeletedFiles"
ItemName="FilesDeleted"/>
</Delete>
<!-- zip圧縮、ymme拡張子変更 -->
<ZipDirectory
SourceDirectory="$(OutputPath)/publish/"
DestinationFile="$(OutputPath)/../../../../../publish/$(AssemblyName).ymme"
Overwrite="true" />
<Message Text="Actions After Publish" Importance="high" />
<!-- ※ここから下はやらなくてもymmeは既にできてる。そのままテストしたい場合用 -->
<!-- プラグインフォルダ以下にコピー -->
<Copy
SourceFiles="$(OutputPath)/../../../../../publish/$(AssemblyName).ymme"
DestinationFolder="$(YMM4_PATH)\user\plugin\"
/>
<!-- ymmeを展開して使えるようにする -->
<Unzip
SourceFiles="$(OutputPath)/../../../../../publish/$(AssemblyName).ymme" DestinationFolder="$(YMM4_PATH)\user\plugin\$(AssemblyName)\" />
</Target>

素材一覧に製作者・ニコニコIDを表示する
プラグイン本体
[PluginDetails(AuthorName = "YourName", ContentId = "YourNicoNicoID")]
public MyPlugin: IPlugin {}
または
public PluginDetailsAttribute Details => new()
{
//制作者
AuthorName = "InuInu",
//作品ID
ContentId = "",
};
※PluginDetails属性だけだと反映されないバグ? or プラグインの種類がある模様
その場合、面倒なのでリフレクションで取得。
public PluginDetailsAttribute Details
=> GetType().GetCustomAttribute<PluginDetailsAttribute>()
?? new();
ボイス(声質)
//ボイス(声質)の制作者
public string? SpeakerAuthor { get; } = "test";
//ボイス(声質)の作品ID (ニコニコIDとして有効じゃないとダメ)
public string? SpeakerContentId { get; } = "nc9999999";
//合成エンジン(アプリケーション)の制作者
public string? EngineAuthor { get; } = "test3";
//合成エンジン(アプリケーション)の作品ID (ニコニコIDとして有効じゃないとダメ)
public string? EngineContentId { get; } = "nc9999999";
VideoEffect、AudioEffect
PluginDetails属性

YmmeUtil
自作の便利なユーティリティライブラリ。詳しくはReadmeをみて。

デバッグ(YMM4 + VSCode)
以下の設定でデバッガー接続できる。
launch.json
- 環境変数
YMM_PATH
は以下のように${env:YMM4_PATH}
で参照可能。 -
"justMyCode": false
が無いとたぶんダメ。
{
"name": "Debug YMM4",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
"program": "${env:YMM4_PATH}/YukkuriMovieMaker.exe",
"args": [],
"cwd": "${workspaceFolder}",
"stopAtEntry": false,
"console": "internalConsole",
"justMyCode": false,
"logging": {
"moduleLoad": false
}
}
csproj
- dotnet build時にdllがYMM4のプラグインフォルダ以下にコピーすればデバッグできる
- pdbも必要
- ライブラリが使っているdllなどすべてがbin/Debug以下にあるわけではないのでpublishしたときのものを追加でコピーする
- 例:bin/Release/publish 以下のdllを全部持ってくる
- 注:publishした時pdbを消す処理していると除外されるのでどうにかする
<Target Name="CopyDebugDlls" BeforeTargets="AfterBuild" Condition="'$(Configuration)' == 'Debug'">
<ItemGroup>
<CommonPaths Include="$(OutputPath)../../Release/$(TargetFramework)/publish"/>
<MissingDlls Include="$(CommonPaths)/*.dll" Exclude="$(CommonPaths)/$(AssemblyName).dll"/>
<MissingPdbs Include="$(CommonPaths)/*.pdb" Exclude="$(CommonPaths)/$(AssemblyName).pdb"/>
</ItemGroup>
<Copy SourceFiles="@(MissingDlls)" DestinationFolder="$(OutputPath)" SkipUnchangedFiles="true"/>
<Copy SourceFiles="@(MissingPdbs)" DestinationFolder="$(OutputPath)" SkipUnchangedFiles="true"/>
<ItemGroup>
<SourceFiles Include="$(OutputPath)**/*.*" />
</ItemGroup>
<Copy SourceFiles="@(SourceFiles)" DestinationFolder="$(YMM4_PATH)\user\plugin\$(AssemblyName)\" />
</Target>
参考

プラグインの動的なUI付きパラメータ
- パラメータをコレクションで持たせてカスタムコントロールを作るケース
- パラメータをコレクションで持たせてカスタム属性で表示するケース
- 入れ子パラメータ内で既存の
TextBoxSlider
とか使いたい場合
がある(後者は饅頭遣いさんから教えていただいた)
- 入れ子パラメータ内で既存の
コレクションパラメータ
[Display(AutoGenerateField = true)]
で入れ子内の表示を自動生成に任せる
[Display(AutoGenerateField = true)]
public ImmutableList<MyChildParameter> ItemsCollection {/*...*/}
カスタム属性
-
CustomDisplayAttributeBase
を継承した属性を作成。- リフレクションでごにょごにょして表示させる
- カスタム表示させたいプロパティに付与
[MyCustomDisplay]
[TextBoxSlider("F2", "", 0, 1, Delay = -1)]
[Range(0, 1)]
[DefaultValue(0.0)]
public double Value { get => _value; set => Set(ref _value, value);}

Windowsタスクバーに進捗表示
var main = Application.Current.MainWindow;
var taskbar = new TaskbarItemInfo
{
ProgressState = TaskbarItemProgressState.Indeterminate,
};
main.TaskbarItemInfo = taskbar;
//do something...
taskbar.ProgressState = TaskbarItemProgressState.None;
-
Application.Current.MainWindow
でYMM4のメインウィンドウを取得 -
TaskbarItemInfo
に割り当てる -
ProgressState
で進捗表示。ProgressValue
で比率も指定できる。 -
注:UIスレッドの処理になるのでワーカースレッドから呼ぶ場合は注意が必要
- Epoxyの
UIThread
クラスなどを使うと楽
- Epoxyの
//EpoxyのUIThreadクラスを使う(この外はワーカースレッドなので呼べない)
await UIThread.InvokeAsync(()=>{
//ここはUIスレッドになってるのでここで呼び出す
TaskbarUtil.StartIndeterminate();
return ValueTask.CompletedTask;
}).ConfigureAwait(false);
-
YmmeUtil.Ymm4.TaskbarUtil
で使えるようにした

YMM4プラグイン用githubのテンプレートリポジトリ
-
src/Sample
以下に何もしないサンプルプラグインが設定済みです- これをもとにしても、公式のサンプルを元にしてもOK
- ソリューションファイル:
Sample.sln
も設定済みです
-
dotnet publish
コマンドでymmeファイルをpublish
以下に作成&YMM4のプラグインフォルダ以下に展開できます - Code Analyzerを色々有効にしています
- ビルド時に
LICENSE
やREADME.md
がdllやymmeに含まれるように設定済 -
licenses
フォルダ以下のファイルもdllやymmeに含まれるように - MinVerライブラリでgitのタグから自動でSemVerが付きます
- VSCode: VSCodeの
publish
タスクでも上記ができるようにしています - VSCode: プラグインをYMM4ごとデバッガ接続で起動することができます
- gitignore, editorconfig設定済み

FocusHelper
-
YukkuriMovieMaker.Commons.FocusHelper
- 外部のアプリ操作のときなどにYMM4にフォーカスを戻すことができる
//現在のフォーカスされたUI部品(WPFの`FrameworkElement`)を取得できる
//v4.45.1で削除
FocusHelper.DefaultFocus;
//YMM4のウィンドウ内の要素にフォーカスを移す
FocusHelper.FocusWindowContent(DependencyObject dependencyObject);
//外部アプリなどにフォーカスが移ったあとにYMM4にフォーカスを戻す
Window.GetWindow(FocusHelper.DefaultFocus).Activate();
FocusHelper.FocusWindowContent(FocusHelper.DefaultFocus);

IToolPlugin
IToolPlugin
を実装したプラグインを作り、View(UserControl
)とViewModelの型を渡すと、YMM4のツールメニューから呼び出し可能なツールが作れる。
public class MyToolPlugin : IToolPlugin
{
public string Name => "MyToolPlugin";
public Type ViewModelType
=> typeof(MyToolViewModel);
public Type ViewType
=> typeof(MyToolView);
}
ただし、YMM4内部のAPIとかは他の形式のプラグイン以下の事しかできないため、
ある程度独自処理のツールしか作れない。
サンプル
これ↓が参考になるかも。
作り方
必須ソースファイル
最低限、次の5つのソースファイルがあれば作れます。
例:SampleToolPlugin
という名前のプラグインを作る時
- SampleToolPlugin.cs
-
IToolPlugin
を実装したSampleToolPlugin
クラスを定義
-
- SampleToolPlugin.csproj
- プラグインのプロジェクトの設定ファイル
- 他の種類のプラグインと同じ
- SampleToolView.xaml
- ツールのGUIを定義するXAML
-
Window
ではなくUserControl
- SampleToolView.xaml.cs
-
SampleToolView
のコードビハインドクラス
-
- SampleToolViewModel.cs
- ViewModelクラス
- ツールプラグインはMVVMパターンでの実装が想定されています
あるといいソースファイル
必須ではないですが、IToolPlugin
向けのAPIはほとんど何もないので、以下のソースを使うとできることの幅が広がります。
- SampleToolPluginSettings.cs
-
SettingsBase<T>
を継承した設定保存処理クラス - 他のプラグインと同じくプラグインの設定を保存することができます
-
Category
プロパティは現状SettingsCategory.None
を指定しておくといいかと思います - ツールプラグインだと使うことが多いかも
-
- SampleToolPluginSettingsView.xaml
- 設定のGUIのXAML(
UserControl
) -
SampleToolPluginSettings.HasSettingView = true
にすると設定のGUIを定義できます - GUIはYMM4本来のメニューのファイル>設定の左のリストに表示されます
- ※ちょっと遠いので見つけにくいかも
- 設定のGUIのXAML(
- SampleToolPluginSettingsView.xaml.cs
-
SampleToolPluginSettingsView
のコードビハインドクラス - ここに処理をかく。ViewModelを別途定義してそちらで処理しても良い。
-

ymmeファイルの命名規則
ymmeからのインストール時、zip内の親フォルダの名前をプラグインフォルダの名前として使用するように仕様変更を行いました(親フォルダが存在しない場合や、すでにzipファイルの名前でプラグインがインストールされている場合はzipファイルの名前でフォルダが作成されます)
上記対応によってymmeファイル名にバージョン番号を入れて配布できるようになった。

思考実験:こんなプラグインを作るとしたら…
3Dモデル表示・立ち絵プラグイン
- Vorticeで3D描画し、出力先をDX2Dにすれば"原理的には"できる
- 問題
- 2D変換を書けるので多分重い
- DX直接叩いてるのと同じなので作るのが大変(基本機能から作る必要あり)
- 画像プラグインにするか、図形プラグインにするか
- 画角とかのパラメータを考えると画像プラグインだとできない…?要検証
- 使えそう
Live2D 立ち絵プラグイン
- Live2Dのライブラリはある
- Live2D Cubism SDK
- NativeかUnity版の活用?
- 「SDKリリースライセンス契約(正式名称:出版許諾契約)の締結と契約料のお支払いが必要となる場合があります」に該当する?
- プラグインじゃなくてYMM4側にかかる場合だと大事で難しい
VSTプラグイン(VST ホストプラグイン)
- 結論
- ライセンス取得が必要
- 技術的には…
- VSTホストになるYMM4音声加工プラグインを作ることができれば原理的にはできる
- 問題がいっぱいある
- 無料で作ろうとするとGPLになっちゃう(YMM4自体もソースコード公開義務がでちゃう)
- Steinburgにライセンス申請&取得必要
- C#でVSTホストを簡単に作れるライブラリがない
- 「VST.NET」はVST2形式なので作れるけど公開できない(今公開OKなのはVST3形式)
- 無料で作ろうとするとGPLになっちゃう(YMM4自体もソースコード公開義務がでちゃう)

YMM4本体のウィンドウを判定する
IMainViewModel
っていうインターフェイスが YukkuriMovieMaker.Plugin に公開されているのでこれを使って判定できる。
Window
のDataContext
がIMainViewModel
を実装していれば、YMM4のメインウィンドウだと判定できる。またIMainViewModel.Index
プロパティでウィンドウの区別ができる模様。
List<dynamic> windows = [.. Application.Current.Windows];
var wins = windows.OfType<Window>();
foreach(var window in wins)
{
if(window.DataContext is IMainViewModel ymmWindow)
{
// ymmWindowはYMM4本体のウインドウ(複数ある)
if(ymmWindow.Index == 0){
//最初のYMM4のメインウインドウが取れる?
}
}
}

複数のプラグインで同じライブラリを使っている場合、最初にYMM4に読まれたDLLしか使われない問題
複数のプラグインから異なるバージョンのライブラリlを参照すると、
最初にYmm4本体に読み込まれたDllしか使用されず、正しく機能しない問題があります。
(.NETの仕様)
YMM4本体で使っているライブラリの場合
YMM4本体同梱のdllを参照する様にすることでバージョン不一致問題がなく、プラグインと同時にライブラリのDLLを配布しなくとも良くなります。
プラグインの容量削減にもなります!
<Reference Include="$(YMM4_PATH)\【ライブラリのDLL名】.dll">
<Private>false</Private>
<CopyLocal>false</CopyLocal>
</Reference>
MSBuildのスクリプト組めば、YMM4本体で使ってるDllを動的に判定して除外することもできる。
<!-- 不要なDLLファイルを除外(YMM4本体のDLLなど) -->
<ItemGroup>
<!-- YMM4_PATHにあるDLLファイルを動的に取得 -->
<Ymm4SystemDlls Include="$(YMM4_PATH)\*.dll" />
<!-- YMM4本体のDLLを除外対象に追加 -->
<FilesToCopy Remove="@(Ymm4SystemDlls->'$(OutputPath)%(Filename)%(Extension)')" />
</ItemGroup>
<!-- デバッグ用:除外されるDLLの一覧表示 -->
<Message Text="=== YMM4 System DLLs to exclude ===" Importance="high" />
<Message Text="%(Ymm4SystemDlls.Filename)%(Ymm4SystemDlls.Extension)" Importance="high" />
<!-- 選択されたファイルをすべてコピー -->
<Copy SourceFiles="@(FilesToCopy)"
DestinationFiles="@(FilesToCopy->'$(PackageFolder)\%(Filename)%(Extension)')" />
YMM4本体で使ってない場合
ILRepack を利用してライブラリのDllをプラグインDLLに埋め込むことで回避できる可能性があります。
ILRepackはnugetパッケージが沢山あるんで間違えないように注意。
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="ILRepacker" AfterTargets="Build;AfterRebuild" BeforeTargets="PostBuildEvent"
Condition="'$(ILRepackExecuted)' != 'true' And Exists('$(OutputPath)\YmmeUtil.Bridge.dll')" >
<!-- 実行フラグを設定 -->
<PropertyGroup>
<ILRepackExecuted>true</ILRepackExecuted>
</PropertyGroup>
<!-- 元のファイルをバックアップ -->
<Copy SourceFiles="$(OutputPath)\$(AssemblyName).dll" DestinationFiles="$(OutputPath)\$(AssemblyName).dll.orig" />
<ItemGroup>
<!-- プライマリアセンブリを最初に配置 -->
<InputAssemblies Include="$(OutputPath)\$(AssemblyName).dll" />
<InputAssemblies Include="$(OutputPath)\YmmeUtil.Bridge.dll" />
<InputAssemblies Include="$(OutputPath)\YmmeUtil.Ymm4.dll" />
</ItemGroup>
<ItemGroup>
<DoNotInternalizeAssemblies Include="System" />
<DoNotInternalizeAssemblies Include="YukkuriMovieMaker" />
<DoNotInternalizeAssemblies Include="YukkuriMovieMaker.Plugin" />
<DoNotInternalizeAssemblies Include="YukkuriMovieMaker.Controls" />
</ItemGroup>
<ItemGroup>
<LibraryPath Include="$(YMM4_PATH)" />
<LibraryPath Include="$(OutputPath)" />
</ItemGroup>
<!-- 一時的な出力ファイルを使用 -->
<ILRepack
Parallel="true"
Internalize="false"
InternalizeExclude="@(DoNotInternalizeAssemblies)"
InputAssemblies="@(InputAssemblies)"
LibraryPath="@(LibraryPath)"
TargetKind="Dll"
OutputFile="$(OutputPath)\$(AssemblyName).dll"
Union="true"
XmlDocumentation="false"
LogFile="$(OutputPath)\ILRepack.log"
DebugInfo="true"
AllowDuplicateResources="true"
/>
<!-- マージされたDLLファイルを削除 -->
<Delete Files="$(OutputPath)\YmmeUtil.Bridge.dll" ContinueOnError="true" />
<Delete Files="$(OutputPath)\YmmeUtil.Ymm4.dll" ContinueOnError="true" />
<!-- マージが成功したかを確認 -->
<Message Text="ILRepack completed. Merged assemblies removed." Importance="high" />
</Target>
<!-- 重複実行を防ぐためのプロパティ設定 -->
<PropertyGroup>
<ILRepackExecuted Condition="'$(ILRepackExecuted)' == ''">false</ILRepackExecuted>
</PropertyGroup>
</Project>
この場合外部のライブラリDLLを参照しないようにする必要があります。
[assembly: TypeForwardedTo(typeof(YmmeUtil.Ymm4.WindowUtil))]

YMM4本体のリソースを使う&同じものを使う
翻訳テキスト
YMM4の本体の翻訳データはプラグインからも利用できる。
YukkuriMoveMaker.Plugin.dll
にあるYukkuriMovieMaker.Resources.Localization.Texts
が利用できる。
using YukkuriMovieMaker.Resources.Localization;
//動画アイテムの名称。日本語だと"動画"
var localizedVideoItemName= Texts.VideoItemName;
<UserConstrol
xmlns:loc="clr-namespace:YukkuriMovieMaker.Resources.Localization;assembly=YukkuriMovieMaker.Plugin"
>
<Label Content="{x:Static loc:Texts.VideoItemName}" />
</UserControl>
アイコン
- YMM4本体のアイコンは「Material Design Icons」
- XAMLのパスをコピーしてくるか、Material.Icons.WPF などのライブラリを使う
- Apache 2.0
icon | アイコン種類 | キー | Material.Iconsのキー |
---|---|---|---|
![]() |
ボイスアイテム | message-text-outline |
MessageTextOutline |
テキストアイテム | `` | FormatText |
|
動画アイテム | `` | Video |
|
音声アイテム | `` | Music |
|
画像アイテム | `` | Image |
|
図形アイテム | `` | ShapePlus |
|
立ち絵アイテム | `` | Account |
|
表情アイテム | `` | EmoticonOutline |
|
エフェクトアイテム | `` | ImageAutoAdjust |
|
場面切り替えアイテム | `` | GradientHorizontal |
|
シーンアイテム | `` | ChartTimeline |
|
画面の複製アイテム | `` | ImageMultiple |
|
グループ制御アイテム | `` | SelectGroup |
|
![]() |
上のアイテムでクリッピングを有効化 |
vector-difference-ab +vector-intersection
|
`` |
![]() |
プロジェクトを新規作成 |
file-plus の旧形状? |
? |
Exo出力 |
file-outline +filmstrip
|
`` | |
動画出力 |
file-outline +video
|
`` | |
![]() |
サムネイル画像をクリップボードに出力 |
clipboard-outline +camera
|
`` |
アイコン色
YMM4Colors.IconBrushKey
YMM4Colors.IconBorderBrushKey
Material.Icons.WPF
- WPF版はちょっと使いにくい。
- Size指定するか、ラップした親要素にWidth/Height指定しないと滅茶苦茶サイズが大きくなる。
- SizeはDepandancyPropertyじゃないのでBindできない。
<!-- これだと滅茶苦茶デカクなる -->
<materialIcons:MaterialIcon Kind="Abacus" />
<Button Content="{materialIcons:MaterialIconExt Kind=Abacus}" />
<!-- 大きさはSizeのみOK. Width/Heightは指定できない。Style関係全部効かない。 -->
<materialIcons:MaterialIcon Kind="Abacus" Size="16" />
<Button Content="{materialIcons:MaterialIconExt Kind=Abacus Size="16}" />
<!-- Panel系でラップする。Style指定できるし、Bindもできる。 -->
<Border Width="{Binding IconWidth}" Height="16">
<materialIcons:MaterialIconExt Kind="MessageTextOutline" />
</Border>
Control
Sampleリポジトリに説明のあるPropertyEditor
の中ではなくて、
ツールとかオリジナルControlでのXAMLでの使い方。
xmlns:c="clr-namespace:YukkuriMovieMaker.Controls;assembly=YukkuriMovieMaker.Controls"
FrameNumberEditor
フレーム表示だけは以下で機能するけど、秒数・時間表示は機能しない。
<c:FrameNumberEditor
Name="SampleFrameNumberEditor"
Width="200"
DefaultValue="0"
Max="{Binding SceneLength}"
Min="0"
Value="{Binding RangeStartFrame, Mode=TwoWay}"
/>
IEditorInfo info = // なんとかIEditorInfoをゲットしてくる
SampleFrameNumberEditor.SetEditorInfo(info);
IEditorInfo
にはFPSとかの情報があるのでフレーム数から秒数計算のために必要。
EnumComboBox
EnumTypeに{x:Type XXXEnum}
でEnum
型渡すと使える。
<c:EnumComboBox
DockPanel.Dock="Right"
EnumType="{x:Type viewmodels:LengthViewMode}"
Value="{Binding Source={x:Static core:ObjectListSettings.Default}, Path=ShowLengthViewMode}"
Margin="5"
/>
PropertyEditor
-
PropertyEditor
自体も呼び出せる - 公式サンプルのSamplePolygonShapeプラグインの独自UserControl(
PointsEditor
)で使われてる
TextEditor
<c:TextEditor Text="{Binding XXX}" BeginEdit="YYY" EndEdit="ZZZ"/>
YYY、ZZZの部分で親コントロールのBeginEdit、EndEditを呼び出す必要

プラグインがウィルス判定されたら
- 通信処理(アップデートチェック等)を入れるとウィルス誤判定されやすくなるらしい
Defenderの場合:申請してみる

PropertyEditorの属性/パラメータ
.NET用
YMM4用属性
[FrameNumberEditor]
- フレーム数表現につかう
- 対象プロパティは
int
等 -
SetEditorInfo()
を呼び出さないと正しく機能しない
[RichTextEditor]
- テキストアイテムのテキストや字幕アイテムのセリフの入力欄でつかってるUI
[CodeEditor]
- YMM4はAvalonEditが内蔵されてるのでコードエディタのコントロールが呼び出せる
PropertyEditorAttribute2
共通
YMM4
PropertyEditorSize
パラメータ
UIの幅を指定する。
[TextEditor(PropertyEditorSize = PropertyEditorSize.Normal)]
-
Normal
: 通常 -
FullWidth
: 2列表示の時でもサイドバー(アイテムエディタ)の幅いっぱいに広がる -
Half
: 通常の半分
デフォルトで幅がNormal以外のものもある。
-
ToggleSlider
はHalf
,RichTextEditor
はFullWidth

*Parameter
クラスのAnimation
プロパティの変化を取得する
カスタムエディタのVMから- カスタムエディタを持つプラグインの場合
-
*Parameter
クラスのAnimation
プロパティの変化を通知したい
とりあえずできた方法(もっといいのがあるかも)
*Parameter
をVMで取得
カスタムエディタのAttribute(例:MyCustomEditorAttribute
)の SetBindingの中で、
VM(例:MyCustomEditorViewModel
)の引数にItemProperty[] properties
を渡す。
public override void SetBindings(
FrameworkElement control,
ItemProperty[] itemProperties
)
{
if (control is not MyCustomEditorViewModel editor)
{
return;
}
editor.DataContext = new MyCustomEditorViewModel(
itemProperties
);
}
VM側で受け取ったItemProperty[] properties
はItemProperty.PropertyOwner
が*Parameter
(例:MyCustomParameter
)なのでキャストして取得する。
※配列でわたってくるのは、複数同時編集用
public MyCustomEditorViewModel(
ItemProperty[] properties
)
{
if(properties[0].PropertyOwner is MyCustomParameter param ){ return; }
_param = param;
}
*Parameter
クラスのAnimation
型プロパティの変更通知を登録
Animation
型プロパティ自体のPropertyChangedにイベントを登録しても、値の変化を検知できない。
//これはダメ、なぜならAnimation型プロパティそのものの差し替えしか検知できない
_param.MyAnimProp.PropertyChanged += (s, e) => {/*...*/};
//値の変化はAnimation.Valuesのコレクションそれぞれに対してイベントを登録
//Animation.Valuesの要素はINotifyPropertyChangedを実装する
foreach (var v in _param.MyAnimProp.Values.OfType<INotifyPropertyChanged>())
{
v.PropertyChanged += (s, e) => {/*...*/};
}
IEditorInfo
を持ってくる
Animationプロパティの値を取るためにやっと変更が通知取れるようになるが、今度はAnimation型のプロパティが取れない。
なぜならAnimation型プロパティは現在のフレーム、アイテムの長さフレーム数、シーンFPSの情報がないと値をGETできないから。
カスタムエディターのUserControl
をIPropertyEditorControl2
を実装するようにすると、
SetEditorInfo()
経由でIEditorInfo
が取れる。
//コードビハインドクラス
public partial MyCustomEditor: UserControl, IIPropertyEditorControl2
{
//IEditorInfoの更新あるたび毎回自動でよばれる
public void SetEditorInfo(IEditorInfo info)
{
if (info is not null && DataContext is MyCustomEditorViewModel vm)
{
//更新受け取ったら、VMにわたす
vm.EditorInfo = info;
}
}
}
IEditorInfo
には ItemPositon.Frame / ItemDuration.Frame / VideoInfo.FPS があるので、
これを使ってAnimationプロパティの値をVM内で取得する。

プラグインで使える便利クラス
YukkuriMovieMaker.Plugin.dllにパスを通すと使える=プラグインから標準で使える
YukkuriMovieMaker.Commons.AppVersion
- AppVersion
-
Current
- 現在のYMM4本体のバージョンを
Version
型でゲットできる
- 現在のYMM4本体のバージョンを
-
YukkuriMovieMaker.Commons.AppDirectories
YMM4関係のディレクトリパスを取れる便利クラス
- AppDirectories
- IsPortable
- AppPath
- AppDirectory
- UserDirectory
- PluginDirectory
- BackupDirectory
- LogDirectory
- SettingDirectory
- TemporaryDirectory
- ResourceDirectory
- Desktop
- Documents
- ComputeSettingsDirectoryHash()
-
SettingDirectory
をハッシュ値で返す - ユーザー名とかの個人情報を公開や記録したくない時に使う
-
YukkuriMovieMaker.Commons.Log
Log.Default.Write(string, Exception?)
で通常のYMM4のログ・ファイルに追記できる。
-
Log.GetAnonymousExceptionString(Exception)
- 個人情報を取り除いた例外メッセージをGETできる

Animation
型の値を取る
*Parameterでよくあるスライダー付きの数値で、値のアニメーションを設定できるパラメータは、
Animation
型というのが使われます。
これの値の取り方は少しクセがあります。
というのもアニメーション情報なので、どのタイミングかを指定しないと値が確定しないから。
GetValue(frame, length, fps)
MyAnimationPropというプロパティの場合
public Animation MyAnimationProp {/*...*/.}
double val = MyAnimationProp.GetValue(frame, length, fps);
現在のフレーム、アイテムの長さフレーム数、シーンFPSの情報がないと取得できません。
※GetValue(0,0,30 /* or 60 */)
で無理やり初期値を取ることもできなくはないです。
frame, length, fps
図形など
Update(timelineItemSourceDescription)
の引数のTimelineItemSourceDescription
にまとめられています。
var frame = timelineItemSourceDescription
.ItemPosition
.Frame;
var length = timelineItemSourceDescription
.ItemDuration
.Frame;
var fps = timelineItemSourceDescription.FPS;
IEditorInfo
Update()
関数外や無いタイプのプラグインの場合は、IEditorInfo
型のものをGETすると求められる。
たとえばIIPropertyEditorControl2
を実装するカスタムエディタの場合はSetEditorInfo()
が呼ばれるのでそこで取得できる。

v4.45+のドッキングウィンドウ関連
AvalonDock
今回のアプデのドッキングウィンドウ対応は、
WPF定番のライブラリ、AvalonDock が使われてる。
AvalonDockの基本的な構造 とか参考になります。
英語だけどgithub wikiに詳しいマニュアルがある
ツールプラグイン
IToolPlugin
のウィンドウはAvalonDockのおそらくLayoutAnchorable
になったので、
ツールペインとしてドッキングできるようになった。
最初の起動時は子ウィンドウだけど、自分でドッキングすると次回からはドッキングされた状態に記録される。
※たぶんレイアウトの保存にも対応してるはず
プラグインからドッキング可能なWindowを作る(調査中)
-
そのままだとWPFのWindowなのでドッキングできない
-
AvalonDockのウィンドウを生成しないといけない
- 2種類ある(ドキュメントウィンドウはLayoutDocument,ツールウィンドウはLayoutAnchorableとして定義)
-
YMM4のAvalonDockを参照しないとうまくいかない気がするのでなんとかそれをしないといけない
-
MainViewModel.LayoutService.DockingManager
にあるけど非公開
-
-
AvalonDock.DockingManager.CreateFloatingWindow()
- DockingManager経由でウィンドウをつくるのはこれっぽい
-
ツリーの子に追加する方法:開発Tips① : 動的なウィンドウの追加