OSDN Git Service

曲ツリーのライフサイクル処理のミスを修正。
authorくまかみ工房 <kumakamikoubou@gmail.com>
Thu, 18 May 2017 11:04:14 +0000 (20:04 +0900)
committerくまかみ工房 <kumakamikoubou@gmail.com>
Thu, 18 May 2017 11:04:14 +0000 (20:04 +0900)
フォーカスリストについて、二重に活性化・非活性化・デバイスリソースの作成/解放を行っていた。

StrokeStyleT/App.cs
StrokeStyleT/ステージ/ユーザ/ユーザステージ.cs
StrokeStyleT/曲/★曲.pptx
StrokeStyleT/曲/曲ツリー.cs

index 2f411d5..10500b5 100644 (file)
@@ -372,8 +372,15 @@ namespace SST
 
                private enum AppStatus { 開始, 実行中, 終了 };
 
+               /// <summary>
+               ///             アプリケーションの状態。
+               /// </summary>
                private AppStatus _AppStatus = AppStatus.開始;
 
+               /// <summary>
+               ///             進行タスクの状態。
+               ///             OFF:タスク起動前、ON:タスク実行中、OFF:タスク終了済み
+               /// </summary>
                private TriStateEvent _進行Status;
 
                private readonly object _進行描画間同期 = new object();
@@ -470,7 +477,7 @@ namespace SST
                        {
                                if( this._AppStatus != AppStatus.終了 )
                                {
-                                       this._進行Status.現在の状態 = TriStateEvent.状態種別.OFF;
+                                       this._進行Status.現在の状態 = TriStateEvent.状態種別.OFF;      // 進行タスクへ、終了を指示。
                                        this._AppStatus = AppStatus.終了;
                                }
 
@@ -485,11 +492,13 @@ namespace SST
                        Log.Info( "進行タスクを開始します。" );
 
                        this._進行Status.現在の状態 = TriStateEvent.状態種別.ON;
+
                        while( this._進行Status.現在の状態 == TriStateEvent.状態種別.ON )
                        {
                                this._進行処理を行う();
                                Thread.Sleep( 1 );  // ウェイト。
                        }
+
                        this._進行Status.現在の状態 = TriStateEvent.状態種別.無効;
 
                        Log.Info( "進行タスクを終了しました。" );
index 0bed0e9..7f4db5e 100644 (file)
@@ -5,6 +5,7 @@ using System.Linq;
 using SharpDX.DirectInput;
 using FDK;
 using FDK.メディア;
+using FDK.同期;
 using SST.曲;
 
 namespace SST.ステージ.ユーザ
@@ -46,6 +47,7 @@ namespace SST.ステージ.ユーザ
                        using( Log.Block( Utilities.現在のメソッド名 ) )
                        {
                                this.現在のフェーズ = フェーズ.ログアウト;
+
                                this._活性化した直後である = true;
                        }
                }
@@ -55,6 +57,7 @@ namespace SST.ステージ.ユーザ
                        using( Log.Block( Utilities.現在のメソッド名 ) )
                        {
                                this.現在のフェーズ = フェーズ.完了;
+
                                this._活性化した直後である = false;
                        }
                }
@@ -67,20 +70,15 @@ namespace SST.ステージ.ユーザ
                                this._背景動画.再生を開始する( 開始位置sec: 0.0, ループ再生する: true );
                        }
 
-
                        App.入力管理.すべての入力デバイスをポーリングする();
 
                        switch( this.現在のフェーズ )
                        {
                                case フェーズ.ログアウト:
-                                       this._ログアウトする();
-                                       this.現在のフェーズ = ( App.ビュアーモードである ) ?
-                                               フェーズ.AutoPlayer選択 :     // ビュアーモードでは常に AutoPlayer でログインする。
-                                               フェーズ.ユーザ一覧;
                                        break;
 
                                case フェーズ.ユーザ一覧:
-                                       #region " *** "
+                                       #region " 進行・入力 "
                                        //----------------
                                        this._ドラムセット.進行する();
 
@@ -142,15 +140,7 @@ namespace SST.ステージ.ユーザ
                                        break;
 
                                case フェーズ.AutoPlayer選択:
-                                       App.ユーザ管理.ユーザを選択する( Properties.Resources.AUTOPLAYER );
-                                       this.現在のフェーズ = フェーズ.ログイン;
-                                       break;
-
                                case フェーズ.ログイン:
-                                       this._ログインする();
-                                       this.現在のフェーズ = フェーズ.完了;
-                                       break;
-
                                case フェーズ.完了:
                                case フェーズ.キャンセル:
                                        break;
@@ -167,8 +157,20 @@ namespace SST.ステージ.ユーザ
 
                        switch( this.現在のフェーズ )
                        {
+                               case フェーズ.ログアウト:
+                                       this._ログアウトする( dr );
+                                       this.現在のフェーズ = ( App.ビュアーモードである ) ?
+                                               フェーズ.AutoPlayer選択 :     // ビュアーモードでは常に AutoPlayer でログインする。
+                                               フェーズ.ユーザ一覧;
+                                       break;
+
+                               case フェーズ.AutoPlayer選択:
+                                       App.ユーザ管理.ユーザを選択する( Properties.Resources.AUTOPLAYER );
+                                       this.現在のフェーズ = フェーズ.ログイン;
+                                       break;
+
                                case フェーズ.ユーザ一覧:
-                                       #region " *** "
+                                       #region " 描画 "
                                        //----------------
                                        {
                                                this._背景動画.進行描画する( dr, new SharpDX.RectangleF( 0f, 0f, dr.設計画面サイズ.Width, dr.設計画面サイズ.Height ) );
@@ -197,9 +199,11 @@ namespace SST.ステージ.ユーザ
                                        #endregion
                                        break;
 
-                               case フェーズ.ログアウト:
-                               case フェーズ.AutoPlayer選択:
                                case フェーズ.ログイン:
+                                       this._ログインする( dr );
+                                       this.現在のフェーズ = フェーズ.完了;
+                                       break;
+
                                case フェーズ.完了:
                                case フェーズ.キャンセル:
                                        break;
@@ -230,9 +234,9 @@ namespace SST.ステージ.ユーザ
 
                /// <summary>
                ///             <see cref="App.ユーザ管理.現在選択されているユーザ"/> のログイン処理を行う。
-               ///             未選択なら何もしない。
+               ///             ユーザが未選択なら何もしない。
                /// </summary>
-               private void _ログインする()
+               private void _ログインする( デバイスリソース dr )
                {
                        using( Log.Block( Utilities.現在のメソッド名 ) )
                        {
@@ -240,15 +244,19 @@ namespace SST.ステージ.ユーザ
 
                                if( null != user )
                                {
+                                       // ユーザ情報を再構築する。
                                        App.ユーザ管理.ユーザを再構築する( user.プロパティ.名前 );
-                                       user = App.ã\83¦ã\83¼ã\82¶ç®¡ç\90\86\81¸æ\8a\9eã\81\95ã\82\8cã\81¦ã\81\84ã\82\8bã\83¦ã\83¼ã\82¶;    // å\86\8dæ§\8bç¯\89å¾\8cã\81¯å\8f\82ç\85§ã\81\8cç\84¡å\8a¹ã\81«ã\81ªã\82\8bã\81®ã\81§ã\80\81å\86\8d参照が必須。
+                                       user = App.ã\83¦ã\83¼ã\82¶ç®¡ç\90\86\81¸æ\8a\9eã\81\95ã\82\8cã\81¦ã\81\84ã\82\8bã\83¦ã\83¼ã\82¶;    // å\86\8dæ§\8bç¯\89å¾\8cã\81¯å\8f¤ã\81\84å\8f\82ç\85§ã\81\8cç\84¡å\8a¹ã\81«ã\81ªã\82\8bã\81®ã\81§ã\80\81æ\96°ã\81\97ã\81\84参照が必須。
 
                                        // 曲検索&曲ツリー構築。
                                        if( App.ビュアーモードではない )
                                        {
                                                user.曲ツリー = new 曲ツリー();
+
                                                foreach( var path in user.プロパティ.曲検索フォルダパスリスト )
                                                        user.曲ツリー.曲を検索してツリーを構築する( user.曲ツリー.ルートノード, path );
+
+                                               user.曲ツリー.活性化する( dr );
                                        }
                                        else
                                        {
@@ -267,9 +275,9 @@ namespace SST.ステージ.ユーザ
 
                /// <summary>
                ///             <see cref="App.ユーザ管理.現在選択されているユーザ"/> のログアウト処理を行う。
-               ///             未選択なら何もしない。
+               ///             ユーザが未選択なら何もしない。
                /// </summary>
-               private void _ログアウトする()
+               private void _ログアウトする( デバイスリソース dr )
                {
                        using( Log.Block( Utilities.現在のメソッド名 ) )
                        {
@@ -279,10 +287,12 @@ namespace SST.ステージ.ユーザ
                                {
                                        user.保存する();
 
-                                       // 曲ツリーの解放。
-                                       user.曲ツリー?.Dispose();
-                                       user.曲ツリー = null;
-
+                                       if( null != user.曲ツリー )
+                                       {
+                                               user.曲ツリー.非活性化する( dr );
+                                               user.曲ツリー.Dispose();
+                                               user.曲ツリー = null;
+                                       }
                                        Log.Info( $"ユーザ [{user.プロパティ.名前}] をログアウトしました。" );
                                }
                                else
index ec02ad6..efb4f6c 100644 (file)
Binary files a/StrokeStyleT/曲/★曲.pptx and b/StrokeStyleT/曲/★曲.pptx differ
index 3927d8f..59f5207 100644 (file)
@@ -12,13 +12,13 @@ namespace SST.曲
        ///             選曲画面で使用される、曲ツリーを管理する。
        ///             曲ツリーは、<see cref="ユーザ"/>ごとに1つずつ持つことができる。
        /// </summary>
-       class 曲ツリー : FDK.Activity, IDisposable
+       class 曲ツリー : Activity, IDisposable
        {
                public RootNode ルートノード
                {
                        get;
                        protected set;
-               } = new RootNode();
+               } = null;
 
                /// <summary>
                ///             現在選択されているノード。
@@ -30,46 +30,53 @@ namespace SST.曲
                public Node フォーカスノード
                {
                        get
-                               => ( 0 <= this.フォーカスリスト.SelectedIndex ) ? this.フォーカスリスト[ this.フォーカスリスト.SelectedIndex ] : null;
+                               => ( null == this.フォーカスリスト ) ? null : // フォーカスリストが未設定なら null。
+                                  ( 0 > this.フォーカスリスト.SelectedIndex ) ? null : // フォーカスリストが空なら null。
+                                  this.フォーカスリスト[ this.フォーカスリスト.SelectedIndex ];
                }
 
                /// <summary>
-               ///             フォーカスノード(現在選択されているノード)が存在するノードリスト。
-               ///             非 null 
+               ///             フォーカスノードが存在するノードリスト。
+               ///             変更するには、変更先のリスト内の任意のノードを選択すること
                /// </summary>
                public SelectableList<Node> フォーカスリスト
                {
-                       get
-                               => this._フォーカスリストの親ノード.子ノードリスト;
-               }
+                       get;
+                       protected set;
+               } = null;
 
 
                public 曲ツリー()
                {
-                       this._フォーカスリストの親ノード = this.ルートノード;
+                       this.ルートノード = new RootNode();
                }
 
                public void Dispose()
                {
-                       this.ルートノード = new RootNode();   // 曲ツリーまるごと解放。
+                       Debug.Assert( this.活性化していない, "曲ツリーが活性化中です。曲ツリーを破棄するには、先に非活性化を行ってください。" );
+
+                       // 全ノードへの参照を破棄する。
+                       this.フォーカスリスト = null;
+                       this.ルートノード = null;
                }
 
                /// <remarks>
-               ///             ツリーを構成する各Nodeの活性化は行わない。
+               ///             ここでは構築のみ行い、構築された各ノードの活性化は行わない。
+               ///             必要あれば呼び出し元から活性化を行うこと。
                /// </remarks>
                public void 曲を検索してツリーを構築する( Node 親ノード, string フォルダパス )
                {
                        フォルダパス = SST.IO.Folder.絶対パスに含まれるフォルダ変数を展開して返す( フォルダパス );
+                       var ログ用フォルダパス = SST.IO.Folder.絶対パスをフォルダ変数付き絶対パスに変換して返す( フォルダパス );
 
                        // フォルダが存在しないなら何もしない。
                        if( false == Directory.Exists( フォルダパス ) )
                        {
-                               Log.WARNING( $"指定されたフォルダが存在しません。無視します。[{SST.IO.Folder.絶対パスをフォルダ変数付き絶対パスに変換して返す( フォルダパス )}]" );
+                               Log.WARNING( $"指定されたフォルダが存在しません。無視します。[{ログ用フォルダパス}]" );
                                return;
                        }
 
-                       Log.Info( $"曲検索: {SST.IO.Folder.絶対パスをフォルダ変数付き絶対パスに変換して返す( フォルダパス )}" );
-
+                       Log.Info( $"曲検索: {ログ用フォルダパス}" );
                        var dirInfo = new DirectoryInfo( フォルダパス );
 
                        // (1) このフォルダにあるすべてのsstfファイルから、曲ノードを作成する。
@@ -78,10 +85,10 @@ namespace SST.曲
                                親ノード.子ノードリスト.Add( new MusicNode( fileInfo.FullName, 親ノード ) );
                        }
 
-                       // (2) このフォルダのすべてのサブフォルダについて……
+                       // (2) このフォルダのすべてのサブフォルダについて再帰処理。
                        foreach( var subDirInfo in dirInfo.GetDirectories() )
                        {
-                               // box.def を含むフォルダの場合 → BOX ノードを作成する。
+                               // box.def を含むフォルダの場合、BOXノードを作成する。
                                var boxファイルパス = Path.Combine( subDirInfo.FullName, @"box.def" );
                                if( File.Exists( boxファイルパス ) )
                                {
@@ -93,34 +100,46 @@ namespace SST.曲
                        }
                }
 
+               /// <summary>
+               ///             指定されたノードをフォーカスする。
+               ///             <see cref="フォーカスリスト"/>もそのノードのあるリストへ変更される。
+               /// </summary>
                public void フォーカスする( デバイスリソース dr, Node ノード )
                {
                        using( Log.Block( Utilities.現在のメソッド名 ) )
                        {
-                               Trace.Assert( ( null != ノード ), "フォーカスするノードが null です。" );
-                               Trace.Assert( ( ノード.GetType() != typeof( RootNode ) ), "RootNode をフォーカスすることはできません。" );
-                               Trace.Assert( ( null != ノード.親ノード ), "ノードの親ノードが null です。" );
+                               var 親ノード = ノード?.親ノード ?? this.ルートノード;
+                               Trace.Assert( null != 親ノード?.子ノードリスト );
 
-                               // 必要なら、フォーカスリストの変更を行う。
-                               if( ノード.親ノード != this._フォーカスリストの親ノード )
-                               {
-                                       // 変更前のフォーカスリスト内のノードを非活性化する。
-                                       foreach( var node in this.フォーカスリスト )
-                                               node.非活性化する( dr );
+                               var 旧フォーカスリスト = this.フォーカスリスト;        // 初回は null 。
 
-                                       // フォーカスリストを切り替える。
-                                       this._フォーカスリストの親ノード = ノード.親ノード;
-                                       Log.Info( "フォーカスリストが変更されました。" );
-                               }
+                               this.フォーカスリスト = 親ノード.子ノードリスト;     // 常に非null。(先のAssertで保証されている。)
 
-                               // フォーカスノードを変更する。(ここの時点で、ノードは現在のフォーカスリスト内に存在しているはず。)
-                               this.フォーカスリスト.SelectItem( ノード );
+                               if( null != ノード )
+                               {
+                                       // (A) ノードの指定がある(非null)なら、それを選択する。
+                                       this.フォーカスリスト.SelectItem( ノード );
+                               }
+                               else
+                               {
+                                       // (B) ノードの指定がない(null)なら、フォーカスノードは現状のまま維持する。
+                               }
 
-                               // 変更語のフォーカスリスト内のノードが活性化されていない場合のみ、活性化する。
-                               foreach( var node in this.フォーカスリスト )
+                               if( 旧フォーカスリスト != this.フォーカスリスト )
                                {
-                                       if( node.活性化していない )
-                                               node.活性化する( dr );
+                                       Log.Info( "フォーカスリストが変更されました。" );
+
+                                       if( this.活性化している )
+                                       {
+                                               if( null != 旧フォーカスリスト )       // 初回は null 。
+                                               {
+                                                       foreach( var node in 旧フォーカスリスト )
+                                                               node.非活性化する( dr );
+                                               }
+
+                                               foreach( var node in this.フォーカスリスト )
+                                                       node.活性化する( dr );
+                                       }
                                }
                        }
                }
@@ -133,7 +152,7 @@ namespace SST.曲
                        var index = this.フォーカスリスト.SelectedIndex;
 
                        if( 0 > index )
-                               return; // 未選択
+                               return; // 現在フォーカスされているノードがない
 
                        index = ( index + 1 ) % this.フォーカスリスト.Count;
 
@@ -148,60 +167,11 @@ namespace SST.曲
                        var index = this.フォーカスリスト.SelectedIndex;
 
                        if( 0 > index )
-                               return; // 未選択
+                               return; // 現在フォーカスされているノードがない
 
                        index = ( index - 1 + this.フォーカスリスト.Count ) % this.フォーカスリスト.Count;
 
                        this.フォーカスリスト.SelectItem( index );
                }
-
-               protected override void On活性化( デバイスリソース dr )
-               {
-                       using( Log.Block( Utilities.現在のメソッド名 ) )
-                       {
-                               //this._フォーカスリストの親ノード = this.ルートノード;      --> フォーカスリストは初期化せず、前回の値をそのまま使用する。
-
-                               // フォーカスリストに含まれるNodeを活性化する。(※フォーカスリストは静的な子Activityではない。)
-                               foreach( var node in this.フォーカスリスト )
-                                       node.活性化する( dr );
-                       }
-               }
-
-               protected override void On非活性化( デバイスリソース dr )
-               {
-                       using( Log.Block( Utilities.現在のメソッド名 ) )
-                       {
-                               // フォーカスリストに含まれるNodeを非活性化する。(※フォーカスリストは静的な子Activityではない。)
-                               foreach( var node in this.フォーカスリスト )
-                                       node.非活性化する( dr );
-                       }
-               }
-
-               protected override void Onデバイス依存リソースの作成( デバイスリソース dr )
-               {
-                       using( Log.Block( Utilities.現在のメソッド名 ) )
-                       {
-                               // フォーカスリストに含まれるNodeのデバイス依存リソースを作成する。(※フォーカスリストは静的な子Activityではない。)
-                               foreach( var node in this.フォーカスリスト )
-                                       node.デバイス依存リソースを作成する( dr );
-                       }
-               }
-
-               protected override void Onデバイス依存リソースの解放( デバイスリソース dr )
-               {
-                       using( Log.Block( Utilities.現在のメソッド名 ) )
-                       {
-                               // フォーカスリストに含まれるNodeのデバイス依存リソースを解放する。(※フォーカスリストは静的な子Activityではない。)
-                               foreach( var node in this.フォーカスリスト )
-                                       node.デバイス依存リソースを解放する( dr );
-                       }
-               }
-
-
-               /// <summary>
-               ///             現在のフォーカスリストの親ノード、または RootNode。
-               ///             null は不可(コンストラクタで必ずRootNodeに設定)。
-               /// </summary>
-               private Node _フォーカスリストの親ノード;
        }
 }