2 using System.Collections.Concurrent;
3 using System.Collections.Generic;
4 using System.Diagnostics;
6 using System.ServiceModel;
7 using System.Windows.Forms;
12 [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)] // サービスインターフェースをシングルスレッドで呼び出す。
13 class StrokeStyleT : SST.IStrokeStyleTService
17 public static SST.フォルダ フォルダ
19 get { return StrokeStyleT._フォルダ; }
22 public static FDK.メディア.サウンド.WASAPI.Device サウンドデバイス
24 get { return StrokeStyleT._サウンドデバイス; }
27 public static System.Random 乱数
29 get { return StrokeStyleT._乱数; }
32 public static SST.ユーザ.ユーザ管理 ユーザ管理
34 get { return StrokeStyleT._ユーザ管理; }
37 public static SST.曲.曲ツリー管理 曲ツリー管理
39 get { return StrokeStyleT._曲ツリー管理; }
42 public static SSTFormat.スコア 演奏スコア
48 public static SST.設定.Config Config
50 get { return StrokeStyleT._Config; }
53 public static bool ビュアーモードである
59 public static bool ビュアーモードではない
61 get { return !StrokeStyleT.ビュアーモードである; }
62 set { StrokeStyleT.ビュアーモードである = !value; }
65 public static SST.ViewerMessage 最後に取得したビュアーメッセージ
71 public static FDK.入力.Keyboard キーボード入力
73 get { return StrokeStyleT._キーボード入力; }
76 public static FDK.入力.MidiIn MIDI入力
78 get { return StrokeStyleT._MIDI入力; }
81 public static void すべての入力デバイスをポーリングする()
83 // hack: 追加の入力デバイスができたら、ここにポーリングコードを追加すること。
84 StrokeStyleT.キーボード入力?.ポーリングする();
85 StrokeStyleT.MIDI入力?.ポーリングする();
91 // フォルダ変数を真っ先に登録する。(ほかのメンバのコンストラクタでフォルダ変数を利用できるようにするため。)
92 StrokeStyleT._フォルダ = new SST.フォルダ();
93 SST.フォルダ.フォルダ変数を追加する( "Static", StrokeStyleT.フォルダ.StaticFolder );
94 SST.フォルダ.フォルダ変数を追加する( "AppData", StrokeStyleT.フォルダ.AppDataFolder );
95 SST.フォルダ.フォルダ変数を追加する( "User", null );
98 public StrokeStyleT( string[] args )
100 #region " ビュアーモードかどうかを確認する。"
102 foreach( var arg in args )
104 if( ( "-v" == arg.ToLower() ) || ( "-viewer" == arg.ToLower() ) )
106 StrokeStyleT.ビュアーモードである = true;
113 this._State = ApplicationState.起動;
115 this._MainForm = new RenderForm();
116 this._MainForm.BackColor = System.Drawing.Color.Black;
117 this._MainForm.AllowUserResizing = false; // ユーザはフォームサイズを変更できない。
118 this._MainForm.UserResized += フォームサイズが変更された;
119 this._MainForm.FormClosing += ( sender, e ) => {
129 Debug.Assert( null != this._MainForm );
131 SharpDX.Windows.RenderLoop.Run( this._MainForm, () => {
133 // アプリケーションの状態に応じて処理分岐。
134 switch( this._State )
136 case ApplicationState.起動:
138 this._State = ApplicationState.初期化;
139 break; // 初期化に移る前に、一度ウィンドウメッセージ処理を行わせて、画面を再描画させる。
141 case ApplicationState.初期化:
143 this._State = ApplicationState.進行描画;
146 case ApplicationState.進行描画:
148 if( this._State == ApplicationState.終了 )
152 case ApplicationState.終了:
160 #region " WCF サービスインターフェースの実装 "
162 // ・このサービスインターフェースは、シングルスレッド(GUIスレッド)で同期実行される。(StrokeStyleT クラスの ServiceBehavior属性を参照。)
163 // ・このサービスホストはシングルトンであり、すべてのクライアントセッションは同一(単一)のサービスインスタンスへ接続される。(Program.Main() を参照。)
171 /// <param name="path">
174 /// <param name="startPart">
177 /// <param name="drumsSound">
178 /// ドラムチップ音を発声させるなら true。
180 public void ViewerPlay( string path, int startPart = 0, bool drumsSound = true )
182 if( StrokeStyleT.ビュアーモードではない )
185 this._ビュアーメッセージキュー.Enqueue( new ViewerMessage() {
186 種別 = ViewerMessageType.演奏開始,
188 演奏開始小節番号 = startPart,
189 ドラムチップ発声 = drumsSound,
199 public void ViewerStop()
201 if( StrokeStyleT.ビュアーモードではない )
204 this._ビュアーメッセージキュー.Enqueue( new ViewerMessage() {
205 種別 = ViewerMessageType.演奏停止,
210 /// サウンドデバイスの発声遅延[ms]を返す。
215 public float GetSoundDelay()
217 if( StrokeStyleT.ビュアーモードではない )
220 return ( null != StrokeStyleT.サウンドデバイス ) ? (float) ( StrokeStyleT.サウンドデバイス.遅延sec * 1000.0 ) : 0f;
225 private enum ApplicationState { 起動, 初期化, 進行描画, 終了 }
226 private ApplicationState _State;
227 private SST.RenderForm _MainForm = null;
228 private SharpDX.Size2F _設計画面サイズdpx = SharpDX.Size2F.Empty;
229 private ConcurrentQueue<ViewerMessage> _ビュアーメッセージキュー = new ConcurrentQueue<ViewerMessage>();
230 private FDK.メディア.デバイスリソース _デバイスリソース = null;
231 private SST.ステージ.ステージ _最初のダミーステージ = null;
232 private SST.ステージ.起動.起動ステージ _起動ステージ = null;
233 private SST.ステージ.タイトル.タイトルステージ _タイトルステージ = null;
234 private SST.ステージ.ログイン.ログインステージ _ログインステージ = null;
235 private SST.ステージ.選曲.選曲ステージ _選曲ステージ = null;
236 private SST.ステージ.曲読込.曲読込ステージ _曲読込ステージ = null;
237 private SST.ステージ.演奏.演奏ステージ _演奏ステージ = null;
238 private SST.ステージ.結果.結果ステージ _結果ステージ = null;
239 private SST.ステージ.ステージ _現在のステージ = null;
240 private static SST.フォルダ _フォルダ = null;
241 private static FDK.入力.Keyboard _キーボード入力 = null;
242 private static FDK.入力.MidiIn _MIDI入力 = null;
243 private static FDK.メディア.サウンド.WASAPI.Device _サウンドデバイス = null;
244 private static readonly System.Random _乱数 = new Random( DateTime.Now.Millisecond );
245 private static SST.ユーザ.ユーザ管理 _ユーザ管理 = null;
246 private static SST.曲.曲ツリー管理 _曲ツリー管理 = null;
247 private static SST.設定.Config _Config = null;
251 FDK.Log.現在のスレッドに名前をつける( "Render" );
252 FDK.Log.BeginInfo( $"{FDK.Utilities.現在のメソッド名}" );
254 #region " コンフィグ を初期化する。"
256 StrokeStyleT._Config = new 設定.Config();
257 StrokeStyleT._Config.ConfigXmlを読み込む();
261 #region " コンフィグで指定されたウィンドウサイズに変更する。"
263 this._MainForm.ClientSize = new System.Drawing.Size( StrokeStyleT.Config.物理画面サイズpx.Width, StrokeStyleT.Config.物理画面サイズpx.Height );
266 #region " フォームタイトルと設計画面サイズを設定する。"
268 this._MainForm.Text = $"StrokeStyle<T> {System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString()}";
269 if( StrokeStyleT.ビュアーモードである )
270 this._MainForm.Text += " (Viewer)";
272 // 設計画面サイズは、フォームサイズ(物理画面サイズ)とは独立して固定。
273 this._設計画面サイズdpx = new SharpDX.Size2F( 1920f, 1080f );
277 FDK.Log.EndInfo( $"{FDK.Utilities.現在のメソッド名}" );
282 FDK.Log.BeginInfo( $"{FDK.Utilities.現在のメソッド名}" );
285 Debug.Assert( null == this._デバイスリソース, "デバイスリソースの作成前であること。" );
287 StrokeStyleT._ユーザ管理 = new ユーザ.ユーザ管理();
288 StrokeStyleT._曲ツリー管理 = new 曲.曲ツリー管理();
290 #region " 高解像度タイマを使えないならエラー。"
292 if( false == System.Diagnostics.Stopwatch.IsHighResolution )
293 throw new SSTException( "このシステムは、高解像度タイマをサポートしていません。" );
296 #region " MediaFoundation を起動する。"
298 SharpDX.MediaFoundation.MediaManager.Startup();
301 #region " Sleep 精度を上げる。"
303 Win32.timeBeginPeriod( 1 );
307 #region " デバイスリソースを作成する。"
309 FDK.Log.Info( $"設計画面サイズ: {this._設計画面サイズdpx}" );
310 FDK.Log.Info( $"物理画面サイズ: {this._MainForm.ClientSize}" );
311 this._デバイスリソース = new FDK.メディア.デバイスリソース( this._設計画面サイズdpx );
312 this._デバイスリソース.すべてのリソースを作成する( this._MainForm.ClientSize, this._MainForm.Handle );
316 #region " ステージを生成する。"
318 this._最初のダミーステージ = new ステージ.ステージ();
319 this._起動ステージ = new ステージ.起動.起動ステージ();
320 this._タイトルステージ = new ステージ.タイトル.タイトルステージ();
321 this._ログインステージ = new ステージ.ログイン.ログインステージ();
322 this._選曲ステージ = new ステージ.選曲.選曲ステージ();
323 this._曲読込ステージ = new ステージ.曲読込.曲読込ステージ();
324 this._演奏ステージ = new ステージ.演奏.演奏ステージ();
325 this._結果ステージ = new ステージ.結果.結果ステージ();
328 this._曲読込ステージ.読込曲のファイルパスを取得する = () => ( ( StrokeStyleT.曲ツリー管理.現在選択されているノード as SST.曲.MusicNode )?.sstfファイルパス );
329 this._結果ステージ.演奏ステージインスタンスを取得する = () => ( this._演奏ステージ );
330 this._結果ステージ.BGMを終了する = () => { this._演奏ステージ.BGMを解放する(); };
333 #region " ユーザを初期化する。"
336 StrokeStyleT.ユーザ管理.UsersXmlを読み込む();
339 foreach( var ユーザ in StrokeStyleT.ユーザ管理.ユーザリスト )
340 ユーザ.SourcesXmlを読み込む();
343 #region " サウンドデバイスを初期化する。"
345 StrokeStyleT._サウンドデバイス = new FDK.メディア.サウンド.WASAPI.Device( CSCore.CoreAudioAPI.AudioClientShareMode.Shared );
348 #region " キーボード入力 を初期化する。"
350 StrokeStyleT._キーボード入力 = new FDK.入力.Keyboard( this._MainForm.Handle );
353 #region " MIDI入力 を初期化する。"
355 StrokeStyleT._MIDI入力 = new FDK.入力.MidiIn();
359 FDK.Log.Info( "最初のダミーステージを開始します。" );
360 this._現在のステージ = this._最初のダミーステージ;
362 //#warning 全画面モード切替えを仮実装。
363 this._MainForm.KeyDown += ( target, arg ) => {
366 if( arg.KeyCode == System.Windows.Forms.Keys.F11 )
368 this.全画面モードとウィンドウモードを切り替える();
374 Debug.Assert( SharpDX.Size2F.Empty != this._設計画面サイズdpx, "設計画面サイズが設定されていません。" );
376 FDK.Log.EndInfo( $"{FDK.Utilities.現在のメソッド名}" );
381 FDK.Log.BeginInfo( $"{FDK.Utilities.現在のメソッド名}" );
382 Debug.Assert( null != this._デバイスリソース, "デバイスリソースが解放される前であること。" );
384 this._State = ApplicationState.終了;
386 #region " ステージを終了し、解放する。"
388 if( ( null != this._現在のステージ ) && ( this._現在のステージ.活性化している ) ) // 念のため
389 this._現在のステージ.非活性化する( this._デバイスリソース );
391 this._演奏ステージ.BGMを解放する();
393 this._最初のダミーステージ = null;
395 this._タイトルステージ = null;
396 this._ログインステージ = null;
398 this._曲読込ステージ = null;
404 #region " ユーザ情報を保存する。"
406 // 要素が増えたときのため、変更がなくても保存する。
407 StrokeStyleT.ユーザ管理.UsersXmlを保存する();
411 #region " デバイスリソースを解放する。"
413 FDK.Utilities.解放する( ref this._デバイスリソース );
417 #region " MIDI入力デバイスを解放する。"
419 FDK.Log.Info( "MIDI入力デバイスを解放します。" );
420 FDK.Utilities.解放する( ref StrokeStyleT._MIDI入力 );
423 #region " キーボード入力デバイスを解放する。"
425 FDK.Log.Info( "キーボード入力デバイスを解放します。" );
426 FDK.Utilities.解放する( ref StrokeStyleT._キーボード入力 );
429 #region " サウンドデバイスを解放する。"
431 FDK.Log.Info( "サウンドデバイスを解放します。" );
432 FDK.Utilities.解放する( ref StrokeStyleT._サウンドデバイス );
436 #region " コンフィグを保存し、解放する。"
438 FDK.Log.Info( "コンフィグを解放します。" );
439 StrokeStyleT._Config.ConfigXmlを保存する();
440 StrokeStyleT._Config = null;
445 FDK.Utilities.解放する( ref this._MainForm );
449 #region " MediaFoundation を終了する。"
451 SharpDX.MediaFoundation.MediaManager.Shutdown();
455 FDK.Log.EndInfo( $"{FDK.Utilities.現在のメソッド名}" );
458 private void 進行描画する()
460 #region " D3Dデバイスが消失していれば再構築する。"
463 this._デバイスリソース.D3Dデバイスが消失していれば再構築する( out 異常発生 );
465 // 再構築不可能な異常の場合は、即終了する。
468 this._State = ApplicationState.終了;
473 #region " 描画の前処理を行う。"
476 var d3dDevice = (SharpDX.Direct3D11.Device) null;
477 using( var d3dLock = new FDK.同期.AutoD3DDeviceLock( this._デバイスリソース.DXGIDeviceManager, out d3dDevice ) )
479 using( var d3dContext = d3dDevice.ImmediateContext )
481 // 既定のD3Dレンダーターゲットビューを黒でクリアする。
482 d3dContext.ClearRenderTargetView( this._デバイスリソース.D3DRenderTargetView, SharpDX.Color4.Black );
484 // 深度バッファを 1.0f でクリアする。
485 d3dContext.ClearDepthStencilView(
486 this._デバイスリソース.D3DDepthStencilView,
487 SharpDX.Direct3D11.DepthStencilClearFlags.Depth,
494 #region " 現在のステージを進行描画する。"
496 this._現在のステージ?.進行描画する( this._デバイスリソース );
499 #region " スワップチェーンを表示する。"
501 if( StrokeStyleT.Config.垂直帰線待ちを行う )
503 // We recommend that you use Flush when the CPU waits for an arbitrary amount of time
504 // (such as when you call the Sleep function).
505 // → https://msdn.microsoft.com/ja-jp/library/windows/desktop/ff476425(v=vs.85).aspx
507 var d3dDevice = (SharpDX.Direct3D11.Device) null;
508 using( var d3dLock = new FDK.同期.AutoD3DDeviceLock( this._デバイスリソース.DXGIDeviceManager, out d3dDevice ) )
510 using( var d3dContext = d3dDevice.ImmediateContext )
516 this._デバイスリソース.SwapChain1.Present(
517 ( StrokeStyleT.Config.垂直帰線待ちを行う ) ? 1 : 0,
518 SharpDX.DXGI.PresentFlags.None );
522 #region " ステージの状態をチェックし、必要あれば遷移またはアプリを終了する。また、必要あればビュアーメッセージキューの処理も行う。"
524 if( null != this._現在のステージ )
526 switch( this._現在のステージ.GetType().Name )
528 case nameof( ステージ.ステージ ):
529 #region " ビュアーモード → AutoPlayerでログインして演奏ステージへ。"
531 if( StrokeStyleT.ビュアーモードである )
534 FDK.Log.Info( "ビュアーモード: AutoPlayer ユーザでログインします。" );
535 this.ログインする( Properties.Resources.AUTOPLAYER );
538 StrokeStyleT.曲ツリー管理.現在の管理対象ツリー = null;
539 StrokeStyleT.曲ツリー管理.現在選択されているノード = null;
542 StrokeStyleT.演奏スコア = null;
545 this._演奏ステージ.活性化する( this._デバイスリソース );
546 this._現在のステージ = this._演奏ステージ;
550 #region " 通常モード → 起動ステージへ。"
554 this._起動ステージ.活性化する( this._デバイスリソース );
555 this._現在のステージ = this._起動ステージ;
561 case nameof( ステージ.起動.起動ステージ ):
562 #region " 終了 → タイトルステージへ。"
564 if( this._起動ステージ.現在のフェーズ == ステージ.起動.起動ステージ.フェーズ.終了 )
566 this._現在のステージ.非活性化する( this._デバイスリソース );
567 this._現在のステージ = this._タイトルステージ;
568 this._現在のステージ.活性化する( this._デバイスリソース );
574 case nameof( ステージ.タイトル.タイトルステージ ):
575 #region " 確定 → ログインステージへ。"
577 if( this._タイトルステージ.現在のフェーズ == ステージ.タイトル.タイトルステージ.フェーズ.確定 )
579 this._現在のステージ.非活性化する( this._デバイスリソース );
580 this._現在のステージ = this._ログインステージ;
581 this._現在のステージ.活性化する( this._デバイスリソース );
585 #region " キャンセル → アプリを終了する。"
587 else if( this._タイトルステージ.現在のフェーズ == ステージ.タイトル.タイトルステージ.フェーズ.キャンセル )
589 this._現在のステージ.非活性化する( this._デバイスリソース );
590 this._現在のステージ = null;
591 this._State = ApplicationState.終了;
597 case nameof( ステージ.ログイン.ログインステージ ):
598 #region " 確定 → ログイン処理を行って、選曲ステージへ。"
600 if( this._ログインステージ.現在のフェーズ == ステージ.ログイン.ログインステージ.フェーズ.確定 )
602 var user = StrokeStyleT.ユーザ管理.現在選択されているユーザ;
606 foreach( var path in user.曲の検索元フォルダパスのリスト )
607 SST.曲.曲ツリー管理.フォルダから曲を再帰的に検索して子ノードリストに追加する( user.曲ツリーのルートノード, path );
609 StrokeStyleT.曲ツリー管理.現在の管理対象ツリー = StrokeStyleT.ユーザ管理.現在選択されているユーザ.曲ツリーのルートノード;
612 this._現在のステージ.非活性化する( this._デバイスリソース );
613 this._現在のステージ = this._選曲ステージ;
614 this._現在のステージ.活性化する( this._デバイスリソース );
618 #region " キャンセル → タイトルステージへ。"
620 else if( this._ログインステージ.現在のフェーズ == ステージ.ログイン.ログインステージ.フェーズ.キャンセル )
622 this._現在のステージ.非活性化する( this._デバイスリソース );
623 this._現在のステージ = this._タイトルステージ;
624 this._現在のステージ.活性化する( this._デバイスリソース );
630 case nameof( ステージ.選曲.選曲ステージ ):
631 #region " 曲確定 → 曲読込ステージへ。"
633 if( this._選曲ステージ.現在のフェーズ == ステージ.選曲.選曲ステージ.フェーズ.曲確定 )
635 // 曲ノードが選択されていることを確認。
636 Trace.Assert( null != StrokeStyleT.曲ツリー管理.現在選択されているノード, "[バグあり] 選択曲が null です。" );
637 this._現在のステージ.非活性化する( this._デバイスリソース );
638 this._現在のステージ = this._曲読込ステージ;
639 this._現在のステージ.活性化する( this._デバイスリソース );
643 #region " キャンセル → アプリを終了する。"
645 else if( this._選曲ステージ.現在のフェーズ == ステージ.選曲.選曲ステージ.フェーズ.キャンセル )
647 this._現在のステージ.非活性化する( this._デバイスリソース );
648 this._現在のステージ = null;
649 this._State = ApplicationState.終了;
655 case nameof( ステージ.曲読込.曲読込ステージ ):
656 #region " 終了 → 演奏ステージへ。"
657 //--------------------
658 if( this._曲読込ステージ.現在のフェーズ == ステージ.曲読込.曲読込ステージ.フェーズ.終了 )
660 this._現在のステージ.非活性化する( this._デバイスリソース );
661 this._現在のステージ = this._演奏ステージ;
662 this._現在のステージ.活性化する( this._デバイスリソース );
664 //--------------------
668 case nameof( ステージ.演奏.演奏ステージ ):
669 if( StrokeStyleT.ビュアーモードである )
673 #region " ビュアーメッセージがあれば処理する。"
675 var msg = this.ビュアーメッセージを取得する();
677 StrokeStyleT.最後に取得したビュアーメッセージ = msg; // 保存する。(演奏ステージに対して公開する)
681 FDK.Log.Info( msg.ToString() );
685 if( msg.種別 == ViewerMessageType.演奏開始 &&
686 ( this._演奏ステージ.現在のフェーズ.Value == ステージ.演奏.演奏ステージ.フェーズ.ビュアーメッセージ待機中 ||
687 this._演奏ステージ.現在のフェーズ.Value == ステージ.演奏.演奏ステージ.フェーズ.演奏中 ) )
691 // MusicNode を作成し、現在選択されているノードとして登録する。
692 StrokeStyleT.曲ツリー管理.現在選択されているノード = new 曲.MusicNode( msg.曲ファイルパス );
695 this._演奏ステージ.非活性化する( this._デバイスリソース );
696 this._演奏ステージ.BGMを解放する();
699 this._現在のステージ = this._曲読込ステージ;
700 this._現在のステージ.活性化する( this._デバイスリソース );
704 FDK.Log.ERROR( $"MusicNode の作成に失敗しました。" );
711 else if( msg.種別 == ViewerMessageType.演奏停止 && (
712 this._演奏ステージ.現在のフェーズ.Value == ステージ.演奏.演奏ステージ.フェーズ.ビュアーメッセージ待機中 ||
713 this._演奏ステージ.現在のフェーズ.Value == ステージ.演奏.演奏ステージ.フェーズ.演奏中 )
716 this._演奏ステージ.演奏を停止する();
717 this._演奏ステージ.現在のフェーズ.Value = ステージ.演奏.演奏ステージ.フェーズ.ビュアーメッセージ待機中;
732 #region " クリア/キャンセル → メッセージ待機へ。"
734 if( this._演奏ステージ.現在のフェーズ.Value == ステージ.演奏.演奏ステージ.フェーズ.クリアor失敗 ||
735 this._演奏ステージ.現在のフェーズ.Value == ステージ.演奏.演奏ステージ.フェーズ.キャンセル )
737 // フェーズのみ変更。BGM は止めない。
738 this._演奏ステージ.現在のフェーズ.Value = ステージ.演奏.演奏ステージ.フェーズ.ビュアーメッセージ待機中;
747 #region " 演奏終了 → 結果ステージへ。"
748 //--------------------
749 if( this._演奏ステージ.現在のフェーズ.Value == ステージ.演奏.演奏ステージ.フェーズ.クリアor失敗 )
751 this._現在のステージ.非活性化する( this._デバイスリソース );
752 this._現在のステージ = this._結果ステージ;
753 this._現在のステージ.活性化する( this._デバイスリソース );
755 //--------------------
757 #region " キャンセル → 選曲ステージへ。"
758 //--------------------
759 if( this._演奏ステージ.現在のフェーズ.Value == ステージ.演奏.演奏ステージ.フェーズ.キャンセル )
761 this._現在のステージ.非活性化する( this._デバイスリソース );
762 this._現在のステージ = this._選曲ステージ;
763 this._現在のステージ.活性化する( this._デバイスリソース );
765 //--------------------
770 case nameof( ステージ.結果.結果ステージ ):
771 #region " 終了 → 選曲ステージへ。"
772 //--------------------
773 if( this._結果ステージ.現在のフェーズ == ステージ.結果.結果ステージ.フェーズ.終了 )
775 this._現在のステージ.非活性化する( this._デバイスリソース );
776 this._現在のステージ = this._選曲ステージ;
777 this._現在のステージ.活性化する( this._デバイスリソース );
779 //--------------------
788 private void デバイス依存リソースを解放する()
790 FDK.Log.BeginInfo( $"{FDK.Utilities.現在のメソッド名}" );
791 Debug.Assert( null != this._デバイスリソース ); // 解放前であること。
793 this._現在のステージ?.デバイス依存リソースを解放する( this._デバイスリソース );
795 FDK.Log.EndInfo( $"{FDK.Utilities.現在のメソッド名}" );
798 private void デバイス依存リソースを再構築する()
800 FDK.Log.BeginInfo( $"{FDK.Utilities.現在のメソッド名}" );
801 Debug.Assert( null != this._デバイスリソース ); // 再生成済みであること。
803 this._現在のステージ?.デバイス依存リソースを作成する( this._デバイスリソース );
805 FDK.Log.EndInfo( $"{FDK.Utilities.現在のメソッド名}" );
808 private void フォームサイズが変更された( object sender, EventArgs e )
810 FDK.Log.BeginInfo( $"{FDK.Utilities.現在のメソッド名}" );
811 FDK.Log.Info( $"新しいクライアントサイズ = {this._MainForm.ClientSize}" );
815 if( null == this._デバイスリソース )
817 FDK.Log.Info( " まだ初期化されてないので、何もしません。" );
818 FDK.Log.EndInfo( $"{FDK.Utilities.現在のメソッド名}" );
821 if( this._MainForm.WindowState == FormWindowState.Minimized )
823 FDK.Log.Info( "最小化されました。" );
824 FDK.Log.EndInfo( $"{FDK.Utilities.現在のメソッド名}" );
827 if( this._State != ApplicationState.進行描画 )
829 FDK.Log.Info( " アプリケーションの状態が進行描画じゃないので、何もしません。" );
830 FDK.Log.EndInfo( $"{FDK.Utilities.現在のメソッド名}" );
836 Debug.Assert( null != this._デバイスリソース, "デバイスリソースが作成済みであること。" );
838 // 現在の画面モードを取得しておく。(Alt+TABなど、勝手に全画面を解除されることもあるので。)
839 SharpDX.Mathematics.Interop.RawBool fullscreen;
840 SharpDX.DXGI.Output outputTarget;
841 this._デバイスリソース.SwapChain1.GetFullscreenState( out fullscreen, out outputTarget );
842 this._MainForm.IsFullscreen = fullscreen;
843 outputTarget?.Dispose();
844 FDK.Log.Info( $"現在、全画面モードである = {this._MainForm.IsFullscreen}" );
847 this.デバイス依存リソースを解放する();
848 this._デバイスリソース.サイズに依存するリソースを解放する();
851 this._デバイスリソース.物理画面サイズpx = new SharpDX.Size2F( this._MainForm.ClientSize.Width, this._MainForm.ClientSize.Height );
854 this._デバイスリソース.サイズに依存するリソースを作成する();
855 this.デバイス依存リソースを再構築する();
857 FDK.Log.EndInfo( $"{FDK.Utilities.現在のメソッド名}" );
860 private void 全画面モードとウィンドウモードを切り替える()
862 FDK.Log.BeginInfo( $"{FDK.Utilities.現在のメソッド名}" );
864 this._MainForm.IsFullscreen = !this._MainForm.IsFullscreen; // 切り替え
865 this._デバイスリソース.SwapChain1.SetFullscreenState( this._MainForm.IsFullscreen, null );
867 FDK.Log.EndInfo( $"{FDK.Utilities.現在のメソッド名}" );
870 private void ログインする( string ユーザ名 )
872 StrokeStyleT.ユーザ管理.ユーザを選択する( ユーザ名 );
873 FDK.Log.Info( $"ユーザが選択されました。[{StrokeStyleT.ユーザ管理.現在選択されているユーザ.名前}]" );
877 /// メッセージがない場合は null を返す。
879 private ViewerMessage ビュアーメッセージを取得する()
881 var msg = (ViewerMessage) null;
883 if( StrokeStyleT.ビュアーモードである &&
884 ( 0 < this._ビュアーメッセージキュー.Count ) &&
885 this._ビュアーメッセージキュー.TryDequeue( out msg ) )