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入力?.ポーリングする();
90 // フォルダ変数を真っ先に登録する。(ほかのメンバのコンストラクタでフォルダ変数を利用できるようにするため。)
91 StrokeStyleT._フォルダ = new SST.フォルダ();
92 SST.フォルダ.フォルダ変数を追加する( "Static", StrokeStyleT.フォルダ.StaticFolder );
93 SST.フォルダ.フォルダ変数を追加する( "AppData", StrokeStyleT.フォルダ.AppDataFolder );
94 SST.フォルダ.フォルダ変数を追加する( "User", null );
97 public StrokeStyleT( string[] args )
99 #region " ビュアーモードかどうかを確認する。"
101 foreach( var arg in args )
103 if( ( "-v" == arg.ToLower() ) || ( "-viewer" == arg.ToLower() ) )
105 StrokeStyleT.ビュアーモードである = true;
112 this._State = ApplicationState.起動;
114 this._MainForm = new RenderForm();
115 this._MainForm.BackColor = System.Drawing.Color.Black;
116 this._MainForm.AllowUserResizing = false; // ユーザはフォームサイズを変更できない。
117 this._MainForm.UserResized += _フォームサイズが変更された;
118 this._MainForm.FormClosing += ( sender, e ) => {
128 Debug.Assert( null != this._MainForm );
130 SharpDX.Windows.RenderLoop.Run( this._MainForm, () => {
132 // アプリケーションの状態に応じて処理分岐。
133 switch( this._State )
135 case ApplicationState.起動:
137 this._State = ApplicationState.初期化;
138 break; // 初期化に移る前に、一度ウィンドウメッセージ処理を行わせて、画面を再描画させる。
140 case ApplicationState.初期化:
142 this._State = ApplicationState.進行描画;
145 case ApplicationState.進行描画:
147 if( this._State == ApplicationState.終了 )
151 case ApplicationState.終了:
159 #region " WCF サービスインターフェースの実装 "
161 // ・このサービスインターフェースは、シングルスレッド(GUIスレッド)で同期実行される。(StrokeStyleT クラスの ServiceBehavior属性を参照。)
162 // ・このサービスホストはシングルトンであり、すべてのクライアントセッションは同一(単一)のサービスインスタンスへ接続される。(Program.Main() を参照。)
170 /// <param name="path">
173 /// <param name="startPart">
176 /// <param name="drumsSound">
177 /// ドラムチップ音を発声させるなら true。
179 public void ViewerPlay( string path, int startPart = 0, bool drumsSound = true )
181 if( StrokeStyleT.ビュアーモードではない )
184 this._ビュアーメッセージキュー.Enqueue( new ViewerMessage() {
185 種別 = ViewerMessageType.演奏開始,
187 演奏開始小節番号 = startPart,
188 ドラムチップ発声 = drumsSound,
198 public void ViewerStop()
200 if( StrokeStyleT.ビュアーモードではない )
203 this._ビュアーメッセージキュー.Enqueue( new ViewerMessage() {
204 種別 = ViewerMessageType.演奏停止,
209 /// サウンドデバイスの発声遅延[ms]を返す。
214 public float GetSoundDelay()
216 if( StrokeStyleT.ビュアーモードではない )
219 return ( null != StrokeStyleT.サウンドデバイス ) ? (float) ( StrokeStyleT.サウンドデバイス.遅延sec * 1000.0 ) : 0f;
224 private enum ApplicationState { 起動, 初期化, 進行描画, 終了 }
226 private ApplicationState _State;
228 private SST.RenderForm _MainForm = null;
230 private SharpDX.Size2F _設計画面サイズdpx = SharpDX.Size2F.Empty;
232 private ConcurrentQueue<ViewerMessage> _ビュアーメッセージキュー = new ConcurrentQueue<ViewerMessage>();
234 private FDK.メディア.デバイスリソース _デバイスリソース = null;
236 private SST.ステージ.ステージ _最初のダミーステージ = null;
238 private SST.ステージ.起動.起動ステージ _起動ステージ = null;
240 private SST.ステージ.タイトル.タイトルステージ _タイトルステージ = null;
242 private SST.ステージ.ログイン.ログインステージ _ログインステージ = null;
244 private SST.ステージ.選曲.選曲ステージ _選曲ステージ = null;
246 private SST.ステージ.曲読込.曲読込ステージ _曲読込ステージ = null;
248 private SST.ステージ.演奏.演奏ステージ _演奏ステージ = null;
250 private SST.ステージ.結果.結果ステージ _結果ステージ = null;
252 private SST.ステージ.ステージ _現在のステージ = null;
254 private static SST.フォルダ _フォルダ = null;
256 private static FDK.入力.Keyboard _キーボード入力 = null;
258 private static FDK.入力.MidiIn _MIDI入力 = null;
260 private static FDK.メディア.サウンド.WASAPI.Device _サウンドデバイス = null;
262 private static readonly System.Random _乱数 = new Random( DateTime.Now.Millisecond );
264 private static SST.ユーザ.ユーザ管理 _ユーザ管理 = null;
266 private static SST.曲.曲ツリー管理 _曲ツリー管理 = null;
268 private static SST.設定.Config _Config = null;
272 FDK.Log.現在のスレッドに名前をつける( "Render" );
273 FDK.Log.BeginInfo( $"{FDK.Utilities.現在のメソッド名}" );
275 #region " コンフィグ を初期化する。"
277 StrokeStyleT._Config = new 設定.Config();
278 StrokeStyleT._Config.ConfigXmlを読み込む();
282 #region " コンフィグで指定されたウィンドウサイズに変更する。"
284 this._MainForm.ClientSize = new System.Drawing.Size( StrokeStyleT.Config.物理画面サイズpx.Width, StrokeStyleT.Config.物理画面サイズpx.Height );
287 #region " フォームタイトルと設計画面サイズを設定する。"
289 this._MainForm.Text = $"StrokeStyle<T> {System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString()}";
290 if( StrokeStyleT.ビュアーモードである )
291 this._MainForm.Text += " (Viewer)";
293 // 設計画面サイズは、フォームサイズ(物理画面サイズ)とは独立して固定。
294 this._設計画面サイズdpx = new SharpDX.Size2F( 1920f, 1080f );
298 FDK.Log.EndInfo( $"{FDK.Utilities.現在のメソッド名}" );
301 private void _初期化する()
303 FDK.Log.BeginInfo( $"{FDK.Utilities.現在のメソッド名}" );
306 Debug.Assert( null == this._デバイスリソース, "デバイスリソースの作成前であること。" );
308 StrokeStyleT._ユーザ管理 = new ユーザ.ユーザ管理();
309 StrokeStyleT._曲ツリー管理 = new 曲.曲ツリー管理();
311 #region " 高解像度タイマを使えないならエラー。"
313 if( false == System.Diagnostics.Stopwatch.IsHighResolution )
314 throw new SSTException( "このシステムは、高解像度タイマをサポートしていません。" );
317 #region " MediaFoundation を起動する。"
319 SharpDX.MediaFoundation.MediaManager.Startup();
322 #region " Sleep 精度を上げる。"
324 Win32.timeBeginPeriod( 1 );
328 #region " デバイスリソースを作成する。"
330 FDK.Log.Info( $"設計画面サイズ: {this._設計画面サイズdpx}" );
331 FDK.Log.Info( $"物理画面サイズ: {this._MainForm.ClientSize}" );
332 this._デバイスリソース = new FDK.メディア.デバイスリソース( this._設計画面サイズdpx );
333 this._デバイスリソース.すべてのリソースを作成する( this._MainForm.ClientSize, this._MainForm.Handle );
337 #region " ステージを生成する。"
339 this._最初のダミーステージ = new ステージ.ステージ();
340 this._起動ステージ = new ステージ.起動.起動ステージ();
341 this._タイトルステージ = new ステージ.タイトル.タイトルステージ();
342 this._ログインステージ = new ステージ.ログイン.ログインステージ();
343 this._選曲ステージ = new ステージ.選曲.選曲ステージ();
344 this._曲読込ステージ = new ステージ.曲読込.曲読込ステージ();
345 this._演奏ステージ = new ステージ.演奏.演奏ステージ();
346 this._結果ステージ = new ステージ.結果.結果ステージ();
349 this._曲読込ステージ.読込曲のファイルパスを取得する = () => ( ( StrokeStyleT.曲ツリー管理.現在選択されているノード as SST.曲.MusicNode )?.sstfファイルパス );
350 this._結果ステージ.演奏ステージインスタンスを取得する = () => ( this._演奏ステージ );
351 this._結果ステージ.BGMを停止する = () => { this._演奏ステージ.BGMを停止する(); };
354 #region " ユーザを初期化する。"
357 StrokeStyleT.ユーザ管理.UsersXmlを読み込む();
360 foreach( var ユーザ in StrokeStyleT.ユーザ管理.ユーザリスト )
361 ユーザ.SourcesXmlを読み込む();
364 #region " サウンドデバイスを初期化する。"
366 StrokeStyleT._サウンドデバイス = new FDK.メディア.サウンド.WASAPI.Device( CSCore.CoreAudioAPI.AudioClientShareMode.Shared );
369 #region " キーボード入力 を初期化する。"
371 StrokeStyleT._キーボード入力 = new FDK.入力.Keyboard( this._MainForm.Handle );
374 #region " MIDI入力 を初期化する。"
376 StrokeStyleT._MIDI入力 = new FDK.入力.MidiIn();
380 FDK.Log.Info( "最初のダミーステージを開始します。" );
381 this._現在のステージ = this._最初のダミーステージ;
383 //#warning 全画面モード切替えを仮実装。
384 this._MainForm.KeyDown += ( target, arg ) => {
387 if( arg.KeyCode == System.Windows.Forms.Keys.F11 )
389 this._全画面モードとウィンドウモードを切り替える();
395 Debug.Assert( SharpDX.Size2F.Empty != this._設計画面サイズdpx, "設計画面サイズが設定されていません。" );
397 FDK.Log.EndInfo( $"{FDK.Utilities.現在のメソッド名}" );
402 FDK.Log.BeginInfo( $"{FDK.Utilities.現在のメソッド名}" );
403 Debug.Assert( null != this._デバイスリソース, "デバイスリソースが解放される前であること。" );
405 this._State = ApplicationState.終了;
407 #region " ステージを終了し、解放する。"
409 if( ( null != this._現在のステージ ) && ( this._現在のステージ.活性化している ) ) // 念のため
410 this._現在のステージ.非活性化する( this._デバイスリソース );
412 this._最初のダミーステージ = null;
414 this._タイトルステージ = null;
415 this._ログインステージ = null;
417 this._曲読込ステージ = null;
418 this._演奏ステージ.BGMを停止する();
419 this._演奏ステージ?.BGMのキャッシュを解放する(); // BGMのキャッシュ(デコード済み WaveSource)を解放。
425 #region " ユーザ情報を保存する。"
427 // 要素が増えたときのため、変更がなくても保存する。
428 StrokeStyleT.ユーザ管理.UsersXmlを保存する();
432 #region " デバイスリソースを解放する。"
434 FDK.Utilities.解放する( ref this._デバイスリソース );
438 #region " MIDI入力デバイスを解放する。"
440 FDK.Log.Info( "MIDI入力デバイスを解放します。" );
441 FDK.Utilities.解放する( ref StrokeStyleT._MIDI入力 );
444 #region " キーボード入力デバイスを解放する。"
446 FDK.Log.Info( "キーボード入力デバイスを解放します。" );
447 FDK.Utilities.解放する( ref StrokeStyleT._キーボード入力 );
450 #region " サウンドデバイスを解放する。"
452 FDK.Log.Info( "サウンドデバイスを解放します。" );
453 FDK.Utilities.解放する( ref StrokeStyleT._サウンドデバイス );
457 #region " コンフィグを保存し、解放する。"
459 FDK.Log.Info( "コンフィグを解放します。" );
460 StrokeStyleT._Config.ConfigXmlを保存する();
461 StrokeStyleT._Config = null;
466 FDK.Utilities.解放する( ref this._MainForm );
470 #region " MediaFoundation を終了する。"
472 SharpDX.MediaFoundation.MediaManager.Shutdown();
476 FDK.Log.EndInfo( $"{FDK.Utilities.現在のメソッド名}" );
479 private void _進行描画する()
481 #region " D3Dデバイスが消失していれば再構築する。"
484 this._デバイスリソース.D3Dデバイスが消失していれば再構築する( out 異常発生 );
486 // 再構築不可能な異常の場合は、即終了する。
489 this._State = ApplicationState.終了;
494 #region " 描画の前処理を行う。"
497 var d3dDevice = (SharpDX.Direct3D11.Device) null;
498 using( var d3dLock = new FDK.同期.AutoD3DDeviceLock( this._デバイスリソース.DXGIDeviceManager, out d3dDevice ) )
500 using( var d3dContext = d3dDevice.ImmediateContext )
502 // 既定のD3Dレンダーターゲットビューを黒でクリアする。
503 d3dContext.ClearRenderTargetView( this._デバイスリソース.D3DRenderTargetView, SharpDX.Color4.Black );
505 // 深度バッファを 1.0f でクリアする。
506 d3dContext.ClearDepthStencilView(
507 this._デバイスリソース.D3DDepthStencilView,
508 SharpDX.Direct3D11.DepthStencilClearFlags.Depth,
515 #region " 現在のステージを進行描画する。"
517 this._現在のステージ?.進行描画する( this._デバイスリソース );
520 #region " スワップチェーンを表示する。"
522 if( StrokeStyleT.Config.垂直帰線待ちを行う )
524 // We recommend that you use Flush when the CPU waits for an arbitrary amount of time
525 // (such as when you call the Sleep function).
526 // → https://msdn.microsoft.com/ja-jp/library/windows/desktop/ff476425(v=vs.85).aspx
528 var d3dDevice = (SharpDX.Direct3D11.Device) null;
529 using( var d3dLock = new FDK.同期.AutoD3DDeviceLock( this._デバイスリソース.DXGIDeviceManager, out d3dDevice ) )
531 using( var d3dContext = d3dDevice.ImmediateContext )
537 this._デバイスリソース.SwapChain1.Present(
538 ( StrokeStyleT.Config.垂直帰線待ちを行う ) ? 1 : 0,
539 SharpDX.DXGI.PresentFlags.None );
543 #region " ステージの状態をチェックし、必要あれば遷移またはアプリを終了する。また、必要あればビュアーメッセージキューの処理も行う。"
545 if( null != this._現在のステージ )
547 switch( this._現在のステージ.GetType().Name )
549 case nameof( ステージ.ステージ ):
550 #region " ビュアーモード → AutoPlayerでログインして演奏ステージへ。"
552 if( StrokeStyleT.ビュアーモードである )
555 FDK.Log.Info( "ビュアーモード: AutoPlayer ユーザでログインします。" );
556 this._ログインする( Properties.Resources.AUTOPLAYER );
559 StrokeStyleT.曲ツリー管理.現在の管理対象ツリー = null;
560 StrokeStyleT.曲ツリー管理.現在選択されているノード = null;
563 StrokeStyleT.演奏スコア = null;
566 this._演奏ステージ.活性化する( this._デバイスリソース );
567 this._現在のステージ = this._演奏ステージ;
571 #region " 通常モード → 起動ステージへ。"
575 this._起動ステージ.活性化する( this._デバイスリソース );
576 this._現在のステージ = this._起動ステージ;
582 case nameof( ステージ.起動.起動ステージ ):
583 #region " 終了 → タイトルステージへ。"
585 if( this._起動ステージ.現在のフェーズ == ステージ.起動.起動ステージ.フェーズ.終了 )
587 this._現在のステージ.非活性化する( this._デバイスリソース );
588 this._現在のステージ = this._タイトルステージ;
589 this._現在のステージ.活性化する( this._デバイスリソース );
595 case nameof( ステージ.タイトル.タイトルステージ ):
596 #region " 確定 → ログインステージへ。"
598 if( this._タイトルステージ.現在のフェーズ == ステージ.タイトル.タイトルステージ.フェーズ.確定 )
600 this._現在のステージ.非活性化する( this._デバイスリソース );
601 this._現在のステージ = this._ログインステージ;
602 this._現在のステージ.活性化する( this._デバイスリソース );
606 #region " キャンセル → アプリを終了する。"
608 else if( this._タイトルステージ.現在のフェーズ == ステージ.タイトル.タイトルステージ.フェーズ.キャンセル )
610 this._現在のステージ.非活性化する( this._デバイスリソース );
611 this._現在のステージ = null;
612 this._State = ApplicationState.終了;
618 case nameof( ステージ.ログイン.ログインステージ ):
619 #region " 確定 → ログイン処理を行って、選曲ステージへ。"
621 if( this._ログインステージ.現在のフェーズ == ステージ.ログイン.ログインステージ.フェーズ.確定 )
623 var user = StrokeStyleT.ユーザ管理.現在選択されているユーザ;
627 foreach( var path in user.曲の検索元フォルダパスのリスト )
628 SST.曲.曲ツリー管理.フォルダから曲を再帰的に検索して子ノードリストに追加する( user.曲ツリーのルートノード, path );
630 StrokeStyleT.曲ツリー管理.現在の管理対象ツリー = StrokeStyleT.ユーザ管理.現在選択されているユーザ.曲ツリーのルートノード;
633 this._現在のステージ.非活性化する( this._デバイスリソース );
634 this._現在のステージ = this._選曲ステージ;
635 this._現在のステージ.活性化する( this._デバイスリソース );
639 #region " キャンセル → タイトルステージへ。"
641 else if( this._ログインステージ.現在のフェーズ == ステージ.ログイン.ログインステージ.フェーズ.キャンセル )
643 this._現在のステージ.非活性化する( this._デバイスリソース );
644 this._現在のステージ = this._タイトルステージ;
645 this._現在のステージ.活性化する( this._デバイスリソース );
651 case nameof( ステージ.選曲.選曲ステージ ):
652 #region " 曲確定 → 曲読込ステージへ。"
654 if( this._選曲ステージ.現在のフェーズ == ステージ.選曲.選曲ステージ.フェーズ.曲確定 )
656 // 曲ノードが選択されていることを確認。
657 Trace.Assert( null != StrokeStyleT.曲ツリー管理.現在選択されているノード, "[バグあり] 選択曲が null です。" );
658 this._現在のステージ.非活性化する( this._デバイスリソース );
659 this._現在のステージ = this._曲読込ステージ;
660 this._現在のステージ.活性化する( this._デバイスリソース );
664 #region " キャンセル → アプリを終了する。"
666 else if( this._選曲ステージ.現在のフェーズ == ステージ.選曲.選曲ステージ.フェーズ.キャンセル )
668 this._現在のステージ.非活性化する( this._デバイスリソース );
669 this._現在のステージ = null;
670 this._State = ApplicationState.終了;
676 case nameof( ステージ.曲読込.曲読込ステージ ):
677 #region " 終了 → 演奏ステージへ。"
678 //--------------------
679 if( this._曲読込ステージ.現在のフェーズ == ステージ.曲読込.曲読込ステージ.フェーズ.終了 )
681 this._現在のステージ.非活性化する( this._デバイスリソース );
682 this._現在のステージ = this._演奏ステージ;
683 this._現在のステージ.活性化する( this._デバイスリソース );
685 //--------------------
689 case nameof( ステージ.演奏.演奏ステージ ):
690 if( StrokeStyleT.ビュアーモードである )
694 #region " ビュアーメッセージがあれば処理する。"
696 var msg = this._ビュアーメッセージを取得する();
698 StrokeStyleT.最後に取得したビュアーメッセージ = msg; // 保存する。(演奏ステージに対して公開する)
702 FDK.Log.Info( msg.ToString() );
706 if( msg.種別 == ViewerMessageType.演奏開始 &&
707 ( this._演奏ステージ.現在のフェーズ.Value == ステージ.演奏.演奏ステージ.フェーズ.ビュアーメッセージ待機中 ||
708 this._演奏ステージ.現在のフェーズ.Value == ステージ.演奏.演奏ステージ.フェーズ.演奏中 ) )
712 // MusicNode を作成し、現在選択されているノードとして登録する。
713 StrokeStyleT.曲ツリー管理.現在選択されているノード = new 曲.MusicNode( msg.曲ファイルパス );
716 this._演奏ステージ.非活性化する( this._デバイスリソース );
717 this._演奏ステージ.BGMを停止する();
720 this._現在のステージ = this._曲読込ステージ;
721 this._現在のステージ.活性化する( this._デバイスリソース );
725 FDK.Log.ERROR( $"MusicNode の作成に失敗しました。" );
732 else if( msg.種別 == ViewerMessageType.演奏停止 && (
733 this._演奏ステージ.現在のフェーズ.Value == ステージ.演奏.演奏ステージ.フェーズ.ビュアーメッセージ待機中 ||
734 this._演奏ステージ.現在のフェーズ.Value == ステージ.演奏.演奏ステージ.フェーズ.演奏中 )
737 this._演奏ステージ.演奏を停止する();
738 this._演奏ステージ.現在のフェーズ.Value = ステージ.演奏.演奏ステージ.フェーズ.ビュアーメッセージ待機中;
753 #region " クリア/キャンセル → メッセージ待機へ。"
755 if( this._演奏ステージ.現在のフェーズ.Value == ステージ.演奏.演奏ステージ.フェーズ.クリアor失敗 ||
756 this._演奏ステージ.現在のフェーズ.Value == ステージ.演奏.演奏ステージ.フェーズ.キャンセル )
758 // フェーズのみ変更。BGM は止めない。
759 this._演奏ステージ.現在のフェーズ.Value = ステージ.演奏.演奏ステージ.フェーズ.ビュアーメッセージ待機中;
768 #region " 演奏終了 → 結果ステージへ。"
769 //--------------------
770 if( this._演奏ステージ.現在のフェーズ.Value == ステージ.演奏.演奏ステージ.フェーズ.クリアor失敗 )
772 this._現在のステージ.非活性化する( this._デバイスリソース );
773 this._現在のステージ = this._結果ステージ;
774 this._現在のステージ.活性化する( this._デバイスリソース );
776 //--------------------
778 #region " キャンセル → 選曲ステージへ。"
779 //--------------------
780 if( this._演奏ステージ.現在のフェーズ.Value == ステージ.演奏.演奏ステージ.フェーズ.キャンセル )
782 this._現在のステージ.非活性化する( this._デバイスリソース );
783 this._現在のステージ = this._選曲ステージ;
784 this._現在のステージ.活性化する( this._デバイスリソース );
786 //--------------------
791 case nameof( ステージ.結果.結果ステージ ):
792 #region " 終了 → 選曲ステージへ。"
793 //--------------------
794 if( this._結果ステージ.現在のフェーズ == ステージ.結果.結果ステージ.フェーズ.終了 )
796 this._現在のステージ.非活性化する( this._デバイスリソース );
797 this._現在のステージ = this._選曲ステージ;
798 this._現在のステージ.活性化する( this._デバイスリソース );
800 //--------------------
809 private void _デバイス依存リソースを解放する()
811 FDK.Log.BeginInfo( $"{FDK.Utilities.現在のメソッド名}" );
812 Debug.Assert( null != this._デバイスリソース ); // 解放前であること。
814 this._現在のステージ?.デバイス依存リソースを解放する( this._デバイスリソース );
816 FDK.Log.EndInfo( $"{FDK.Utilities.現在のメソッド名}" );
819 private void _デバイス依存リソースを再構築する()
821 FDK.Log.BeginInfo( $"{FDK.Utilities.現在のメソッド名}" );
822 Debug.Assert( null != this._デバイスリソース ); // 再生成済みであること。
824 this._現在のステージ?.デバイス依存リソースを作成する( this._デバイスリソース );
826 FDK.Log.EndInfo( $"{FDK.Utilities.現在のメソッド名}" );
829 private void _フォームサイズが変更された( object sender, EventArgs e )
831 FDK.Log.BeginInfo( $"{FDK.Utilities.現在のメソッド名}" );
832 FDK.Log.Info( $"新しいクライアントサイズ = {this._MainForm.ClientSize}" );
836 if( null == this._デバイスリソース )
838 FDK.Log.Info( " まだ初期化されてないので、何もしません。" );
839 FDK.Log.EndInfo( $"{FDK.Utilities.現在のメソッド名}" );
842 if( this._MainForm.WindowState == FormWindowState.Minimized )
844 FDK.Log.Info( "最小化されました。" );
845 FDK.Log.EndInfo( $"{FDK.Utilities.現在のメソッド名}" );
848 if( this._State != ApplicationState.進行描画 )
850 FDK.Log.Info( " アプリケーションの状態が進行描画じゃないので、何もしません。" );
851 FDK.Log.EndInfo( $"{FDK.Utilities.現在のメソッド名}" );
857 Debug.Assert( null != this._デバイスリソース, "デバイスリソースが作成済みであること。" );
859 // 現在の画面モードを取得しておく。(Alt+TABなど、勝手に全画面を解除されることもあるので。)
860 SharpDX.Mathematics.Interop.RawBool fullscreen;
861 SharpDX.DXGI.Output outputTarget;
862 this._デバイスリソース.SwapChain1.GetFullscreenState( out fullscreen, out outputTarget );
863 this._MainForm.IsFullscreen = fullscreen;
864 outputTarget?.Dispose();
865 FDK.Log.Info( $"現在、全画面モードである = {this._MainForm.IsFullscreen}" );
868 this._デバイス依存リソースを解放する();
869 this._デバイスリソース.サイズに依存するリソースを解放する();
872 this._デバイスリソース.物理画面サイズpx = new SharpDX.Size2F( this._MainForm.ClientSize.Width, this._MainForm.ClientSize.Height );
875 this._デバイスリソース.サイズに依存するリソースを作成する();
876 this._デバイス依存リソースを再構築する();
878 FDK.Log.EndInfo( $"{FDK.Utilities.現在のメソッド名}" );
881 private void _全画面モードとウィンドウモードを切り替える()
883 FDK.Log.BeginInfo( $"{FDK.Utilities.現在のメソッド名}" );
885 this._MainForm.IsFullscreen = !this._MainForm.IsFullscreen; // 切り替え
886 this._デバイスリソース.SwapChain1.SetFullscreenState( this._MainForm.IsFullscreen, null );
888 FDK.Log.EndInfo( $"{FDK.Utilities.現在のメソッド名}" );
891 private void _ログインする( string ユーザ名 )
893 StrokeStyleT.ユーザ管理.ユーザを選択する( ユーザ名 );
894 FDK.Log.Info( $"ユーザが選択されました。[{StrokeStyleT.ユーザ管理.現在選択されているユーザ.名前}]" );
898 /// メッセージがない場合は null を返す。
900 private ViewerMessage _ビュアーメッセージを取得する()
902 var msg = (ViewerMessage) null;
904 if( StrokeStyleT.ビュアーモードである &&
905 ( 0 < this._ビュアーメッセージキュー.Count ) &&
906 this._ビュアーメッセージキュー.TryDequeue( out msg ) )