OSDN Git Service

D2D版を改名し、新しく曲パネルビュークラスを追加。
authorくまかみ工房 <kumakamikoubou@gmail.com>
Tue, 4 Oct 2016 07:13:31 +0000 (16:13 +0900)
committerくまかみ工房 <kumakamikoubou@gmail.com>
Wed, 5 Oct 2016 05:17:36 +0000 (14:17 +0900)
StrokeStyleT/StrokeStyleT.csproj
StrokeStyleT/ステージ/選曲/曲パネルビュー.cs
StrokeStyleT/ステージ/選曲/曲パネルビューD2D.cs [new file with mode: 0644]
StrokeStyleT/ステージ/選曲/選曲ステージ.cs

index 38163df..d251a3f 100644 (file)
@@ -88,6 +88,7 @@
     <Reference Include="System.Xml" />
   </ItemGroup>
   <ItemGroup>
+    <Compile Include="ステージ\選曲\曲パネルビュー.cs" />
     <Compile Include="設定\Config.cs" />
     <Compile Include="SSTException.cs" />
     <Compile Include="StrokeStyleT.cs" />
     <Compile Include="ステージ\演奏\演奏ステージ.cs" />
     <Compile Include="ステージ\結果\結果ステージ.cs" />
     <Compile Include="ステージ\起動\起動ステージ.cs" />
-    <Compile Include="ステージ\選曲\曲パネルビュー.cs" />
+    <Compile Include="ステージ\選曲\曲パネルビューD2D.cs" />
     <Compile Include="ステージ\選曲\選曲ステージ.cs" />
     <Compile Include="フォルダ.cs" />
     <Compile Include="ユーザ\XML.cs" />
index 8c5ad13..2959e02 100644 (file)
@@ -20,7 +20,55 @@ namespace SST.ステージ.選曲
        {
                public 曲パネルビュー()
                {
-                       this.子リスト.Add( this.Nullパネルの画像 = new 画像( @"$(Static)\images\選曲パネル.png" ) );
+                       this.子リスト.Add( this.Nullパネルの画像 = new テクスチャ( @"$(Static)\images\選曲パネル.png" ) );
+               }
+               public void カーソルを上に移動する()
+               {
+                       if( 0 < this.カーソル位置.Y )
+                       {
+                               this.カーソル位置.Y--;
+                       }
+                       else
+                       {
+                               this.カーソル位置.X--;
+                               this.カーソル位置.Y = 2;
+                       }
+
+                       // カーソルと一緒に、選択曲も移動する。
+                       StrokeStyleT.曲ツリー管理.前のノードを選択する();
+               }
+               public void カーソルを下に移動する()
+               {
+                       if( 2 > this.カーソル位置.Y )
+                       {
+                               this.カーソル位置.Y++;
+                       }
+                       else
+                       {
+                               this.カーソル位置.X++;
+                               this.カーソル位置.Y = 0;
+                       }
+
+                       // カーソルと一緒に、選択曲も移動する。
+                       StrokeStyleT.曲ツリー管理.次のノードを選択する();
+               }
+               public void カーソルを左に移動する()
+               {
+                       this.カーソル位置.X--;    // 制限なし
+
+                       // カーソルと一緒に、選択曲も移動する。
+                       StrokeStyleT.曲ツリー管理.前のノードを選択する();
+                       StrokeStyleT.曲ツリー管理.前のノードを選択する();
+                       StrokeStyleT.曲ツリー管理.前のノードを選択する();
+               }
+               public void カーソルを右に移動する()
+               {
+                       this.カーソル位置.X++;    // 制限なし
+
+                       // カーソルと一緒に、選択曲も移動する。
+                       StrokeStyleT.曲ツリー管理.次のノードを選択する();
+                       StrokeStyleT.曲ツリー管理.次のノードを選択する();
+                       StrokeStyleT.曲ツリー管理.次のノードを選択する();
                }
                protected override void On活性化( デバイスリソース dr )
                {
@@ -60,32 +108,32 @@ namespace SST.ステージ.選曲
 
                                        // オフセット と カーソル位置.X を更新する。
                                        if( ( 4 > this.カーソル位置.X ) ||
-                                               ( ( 4 == this.カーソル位置.X ) && ( 0 > this.曲パネルのY軸回転オフセット ) ) )
+                                               ( ( 4 == this.カーソル位置.X ) && ( 0 > this.パネル全体のY軸回転オフセット ) ) )
                                        {
-                                               #region "  パネルは、左から右へ、移動する。"
+                                               #region " (A) パネルは、左から右へ、移動する。"
                                                //-----------------
-                                               this.曲パネルのY軸回転オフセット += オフセットの加減算速度;
+                                               this.パネル全体のY軸回転オフセット += オフセットの加減算速度;
 
                                                // 1列分移動した
-                                               if( 64 <= this.曲パネルのY軸回転オフセット )
+                                               if( 64 <= this.パネル全体のY軸回転オフセット )
                                                {
-                                                       this.曲パネルのY軸回転オフセット -= 64;  // 0 付近に戻る
+                                                       this.パネル全体のY軸回転オフセット -= 64;  // 0 付近に戻る
                                                        this.カーソル位置.X++;
                                                }
                                                //-----------------
                                                #endregion
                                        }
                                        else if( ( 4 < this.カーソル位置.X ) ||
-                                               ( ( 4 == this.カーソル位置.X ) && ( 0 < this.曲パネルのY軸回転オフセット ) ) )
+                                               ( ( 4 == this.カーソル位置.X ) && ( 0 < this.パネル全体のY軸回転オフセット ) ) )
                                        {
-                                               #region " パネルは、右から左へ、移動する。"
+                                               #region " (B) パネルは、右から左へ、移動する。"
                                                //-----------------
-                                               this.曲パネルのY軸回転オフセット -= オフセットの加減算速度;
+                                               this.パネル全体のY軸回転オフセット -= オフセットの加減算速度;
 
                                                // 1列分移動した
-                                               if( -64 >= this.曲パネルのY軸回転オフセット )
+                                               if( -64 >= this.パネル全体のY軸回転オフセット )
                                                {
-                                                       this.曲パネルのY軸回転オフセット += 64;  // 0 付近に戻る
+                                                       this.パネル全体のY軸回転オフセット += 64;  // 0 付近に戻る
                                                        this.カーソル位置.X--;
                                                }
                                                //-----------------
@@ -97,9 +145,7 @@ namespace SST.ステージ.選曲
 
                        // 描画。
 
-                       Debug.Assert( null != StrokeStyleT.ユーザ管理 );
-                       Debug.Assert( null != StrokeStyleT.ユーザ管理.現在選択されているユーザ );
-                       Debug.Assert( null != StrokeStyleT.ユーザ管理.現在選択されているユーザ.曲ツリーのルートノード );
+                       Debug.Assert( null != StrokeStyleT.ユーザ管理?.現在選択されているユーザ?.曲ツリーのルートノード );
 
                        var 曲リスト管理 = StrokeStyleT.曲ツリー管理;
                        var 曲リスト = 曲リスト管理.現在選択されているノード?.親ノード.子ノードリスト ?? 曲リスト管理.現在の管理対象ツリー.子ノードリスト;
@@ -137,11 +183,7 @@ namespace SST.ステージ.選曲
                                }
                                else
                                {
-                                       this.パネルを一枚描画する(
-                                               dr,
-                                               描画する曲,
-                                               パネル位置,
-                                               これはカーソル位置のパネルである: false );
+                                       this.パネルを一枚描画する( dr, 描画する曲, パネル位置, これはカーソル位置のパネルである: false );
                                }
 
                                // 次のノードへ移動。(選択ノードは移動しない。)
@@ -163,218 +205,42 @@ namespace SST.ステージ.選曲
                        //-----------------
                        #endregion
                }
-               public void カーソルを上に移動する()
-               {
-                       if( 0 < this.カーソル位置.Y )
-                       {
-                               this.カーソル位置.Y--;
-                       }
-                       else
-                       {
-                               this.カーソル位置.X--;
-                               this.カーソル位置.Y = 2;
-                       }
-
-                       // カーソルと一緒に、選択曲も移動する。
-                       StrokeStyleT.曲ツリー管理.前のノードを選択する();
-               }
-               public void カーソルを下に移動する()
-               {
-                       Debug.Assert( this.活性化している );
-
-                       if( 2 > this.カーソル位置.Y )
-                       {
-                               this.カーソル位置.Y++;
-                       }
-                       else
-                       {
-                               this.カーソル位置.X++;
-                               this.カーソル位置.Y = 0;
-                       }
-
-                       // カーソルと一緒に、選択曲も移動する。
-                       StrokeStyleT.曲ツリー管理.次のノードを選択する();
-               }
-               public void カーソルを左に移動する()
-               {
-                       Debug.Assert( this.活性化している );
-
-                       this.カーソル位置.X--;    // 制限なし
-
-                       // カーソルと一緒に、選択曲も移動する。
-                       StrokeStyleT.曲ツリー管理.前のノードを選択する();
-                       StrokeStyleT.曲ツリー管理.前のノードを選択する();
-                       StrokeStyleT.曲ツリー管理.前のノードを選択する();
-               }
-               public void カーソルを右に移動する()
-               {
-                       Debug.Assert( this.活性化している );
-
-                       this.カーソル位置.X++;    // 制限なし
-
-                       // カーソルと一緒に、選択曲も移動する。
-                       StrokeStyleT.曲ツリー管理.次のノードを選択する();
-                       StrokeStyleT.曲ツリー管理.次のノードを選択する();
-                       StrokeStyleT.曲ツリー管理.次のノードを選択する();
-               }
-
-               protected void パネルを一枚描画する(
-                       デバイスリソース dr,
-                       曲.Node パネルノード,  // null 可
-                       SharpDX.Point パネル位置,
-                       bool これはカーソル位置のパネルである = false )
-               {
-                       const float カーソル位置のパネルの拡大率 = 1.25f;
-
-                       #region " 2D変換行列を作成する(ノード画像、タイトル画像共通)。"
-                       //-----------------
-                       // 全体的に、画面中央のちょい上に移動する。
-                       float ちょい上dpx = -70.0f;    // ステージ台とパネルが接触しない程度の位置へ。
-                       var 変換行列2Dpx = dr.行列を単位変換するDPXtoPX(
-                               SharpDX.Matrix3x2.Translation(
-                                       dr.設計画面サイズdpx.Width / 2.0f,
-                                       dr.設計画面サイズdpx.Height / 2.0f + ちょい上dpx ) );
-
-                       if( これはカーソル位置のパネルである )
-                       {
-                               // 拡大する分だけ表示座標を移動する。
-                               変換行列2Dpx *= dr.行列を単位変換するDPXtoPX(
-                                       SharpDX.Matrix3x2.Translation(
-                                               -パネルサイズdpx.全体dpx.Width * ( カーソル位置のパネルの拡大率 - 1.0f ) / 2.0f,
-                                               -パネルサイズdpx.全体dpx.Height * ( カーソル位置のパネルの拡大率 - 1.0f ) / 2.0f ) );
-                       }
-                       //-----------------
-                       #endregion
-
-                       // パネル位置にオフセットを加味し、横位置の割合を算出する。
-                       const float 列間隔の角度 = 0.104f;    // 等間隔
-                       float 横位置割合 = 0.920f - ( パネル位置.X + ( this.曲パネルのY軸回転オフセット / 64.0f ) ) * 列間隔の角度;
-
-                       var 変換行列3Dpx = SharpDX.Matrix.Identity;
-
-                       if( null != パネルノード )
-                       {
-                               #region " 3D変換行列を作成してノード画像を表示する。"
-                               //-----------------
-                               変換行列3Dpx = SharpDX.Matrix.Scaling(
-                                       x: パネルサイズdpx.画像領域dpx.Width / パネルノード.ノード画像サイズdpx.Width, // ノード画像を設計値サイズに拡大縮小する。
-                                       y: パネルサイズdpx.画像領域dpx.Height / パネルノード.ノード画像サイズdpx.Height,
-                                       z: 1.0f );
-
-                               // カーソル位置なら拡大する。
-                               if( これはカーソル位置のパネルである )
-                                       変換行列3Dpx *= SharpDX.Matrix.Scaling( カーソル位置のパネルの拡大率 );
-
-                               // 曲面変換。
-                               変換行列3Dpx *= this.横位置割合からパネルの変換行列を算出して返す( dr, 横位置割合, パネル位置.Y );
-
-                               // 描画。
-                               パネルノード.ノード画像を描画する( dr, 変換行列2Dpx, 変換行列3Dpx );
-                               //-----------------
-                               #endregion
-                               #region " 3D変換行列を作成してタイトル画像を表示する。"
-                               //-----------------
-                               変換行列3Dpx = SharpDX.Matrix.Scaling(
-                                       x: パネルサイズdpx.タイトル領域dpx.Width / パネルノード.タイトル画像サイズdpx.Width,  // タイトル画像を設計値サイズに拡大縮小する。
-                                       y: パネルサイズdpx.タイトル領域dpx.Height / パネルノード.タイトル画像サイズdpx.Height,
-                                       z: 1.0f );
-
-                               // カーソル位置なら拡大する。
-                               if( これはカーソル位置のパネルである )
-                                       変換行列3Dpx *= SharpDX.Matrix.Scaling( カーソル位置のパネルの拡大率 );
-
-                               // 曲面変換。
-                               変換行列3Dpx *= this.横位置割合からパネルの変換行列を算出して返す( dr, 横位置割合, パネル位置.Y );
-
-                               // 描画。
-                               パネルノード.タイトル画像を描画する( dr, 変換行列2Dpx, 変換行列3Dpx );
-                               //-----------------
-                               #endregion
-                       }
-                       else
-                       {
-                               #region " 3D変換行列を作成してノード画像を表示する。"
-                               //-----------------
-                               変換行列3Dpx = SharpDX.Matrix.Scaling(
-                                       x: パネルサイズdpx.画像領域dpx.Width / this.Nullパネルの画像.サイズdpx.Width, // ノード画像を設計値サイズに拡大縮小する。
-                                       y: パネルサイズdpx.画像領域dpx.Height / this.Nullパネルの画像.サイズdpx.Height,
-                                       z: 1.0f );
-
-                               // カーソル位置なら拡大する。
-                               if( これはカーソル位置のパネルである )
-                                       変換行列3Dpx *= SharpDX.Matrix.Scaling( カーソル位置のパネルの拡大率 );
-
-                               // 曲面変換。
-                               変換行列3Dpx *= this.横位置割合からパネルの変換行列を算出して返す( dr, 横位置割合, パネル位置.Y );
-
-                               // 描画。
-                               this.Nullパネルの画像.進行描画する( dr, 変換行列2Dpx, 変換行列3Dpx );
-                               //-----------------
-                               #endregion
-                       }
-               }
-
-               protected SharpDX.Matrix 横位置割合からパネルの変換行列を算出して返す( デバイスリソース dr, float 横位置割合, int Y位置0to2 )
-               {
-                       // 原点が画像の左上隅から画像の中央へ来るように移動。
-                       var 変換行列3Dpx = SharpDX.Matrix.Translation(
-                               x: -( パネルサイズdpx.全体dpx.Width * dr.拡大率DPXtoPX横方法 / 2.0f ),
-                               y: -( パネルサイズdpx.全体dpx.Height * dr.拡大率DPXtoPX縦方向 / 2.0f ),
-                               z: 0.0f );
-
-                       // 縦方向の移動(上、中、下段のいずれかへ)。
-                       変換行列3Dpx *= SharpDX.Matrix.Translation(
-                               0.0f,
-                               ( ( ( Y位置0to2 - 1 ) * 230.0f ) ) * dr.拡大率DPXtoPX縦方向,    // 1行は 230 dpx
-                               0.0f );
-
-                       // Y軸回転半径分、画面奥に移動。
-                       変換行列3Dpx *= SharpDX.Matrix.Translation(
-                               0.0f,
-                               0.0f,
-                               -1000.0f * dr.拡大率DPXtoPX横方法 );   // 回転半径は 1000 dpx; Direct2D では、画面手前ほどZ軸がプラス。なお、Z 軸だがここでは 横方向 の拡大率を使用。
-
-                       // Y軸回転。
-                       変換行列3Dpx *= SharpDX.Matrix.RotationY(
-                               (float) Math.PI * ( 横位置割合 - 0.5f ) );
-
-                       // 画面に近いので、全体的に画面の奥へ移動。
-                       変換行列3Dpx *= SharpDX.Matrix.Translation(
-                               0.0f,
-                               0.0f,
-                               950.0f * dr.拡大率DPXtoPX横方法 );     // 移動量 950 dpx; なお、Z 軸だがここでは 横方向 の拡大率を使用。
-
-                       // 射影変換。
-                       変換行列3Dpx *= FDK.Utilities.D2DPerspectiveProjection(
-                               dr.設計画面サイズdpx.Height * 1.67f * dr.拡大率DPXtoPX横方法 );        // 深さは約 1800 [px; 縦1080px時]; Direc2D では、パラメータは深さのみ。なお、(同上
-
-                       return 変換行列3Dpx;
-               }
-
-               // 設計定数
-               protected struct パネルサイズdpx
-               {
-                       public static readonly SharpDX.Size2F 全体dpx = new SharpDX.Size2F( 314f, 220f );
-                       public static readonly SharpDX.RectangleF 画像領域dpx = new SharpDX.RectangleF( 0f, 0f, 313f, 137f );
-                       public static readonly SharpDX.RectangleF タイトル領域dpx = new SharpDX.RectangleF( 0f, 138f, 313f, 219f );
-               }
 
+               protected const float カーソル位置のパネルの拡大率 = 1.25f;
+               protected bool 活性化した直後である = false;
+               protected readonly FDK.メディア.テクスチャ Nullパネルの画像;
+               protected FDK.カウンタ.定間隔進行 横スクロール用カウンタ = null;
                /// <summary>
                /// 左上隅のパネルを (0,0) とした時の、カーソル位置の座標。
                /// 負数も可。
                /// </summary>
                protected SharpDX.Point カーソル位置 = new SharpDX.Point( 4, 1 );
-
                /// <summary>
-               /// -63~63。パネルの表示位置を、負数は 左 へ、正数は 右 へずらす 。(正負と左右の対応に注意。)
+               /// -63~63。パネル全体の表示位置を、負数は 左 へ、正数は 右 へずらす 。(正負と左右の対応に注意。)
                /// </summary>
                /// <remarks>
                /// ±64 は、パネル1列分を表すサイズ。
                /// </remarks>
-               protected int 曲パネルのY軸回転オフセット = 0;
+               protected int パネル全体のY軸回転オフセット = 0;
 
-               protected bool 活性化した直後である = false;
-               protected FDK.カウンタ.定間隔進行 横スクロール用カウンタ = null;
-               protected readonly FDK.メディア.画像 Nullパネルの画像;
+               /// <summary>
+               /// パネルを一枚(ノード画像とタイトル画像)を、指定したパネル位置に描画する。
+               /// </summary>
+               /// <param name="パネルノード">null 可。</param>
+               protected void パネルを一枚描画する( デバイスリソース dr, 曲.Node パネルノード, SharpDX.Point パネル位置, bool これはカーソル位置のパネルである = false )
+               {
+                       /*
+                       if( null != パネルノード )
+                       {
+                               // ノード画像を表示する。
+                               // タイトル文字列画像を表示する。
+                       }
+                       else
+                       */
+                       {
+                               // Nullパネル画像を表示する。
+                               this.Nullパネルの画像.進行描画する( dr, SharpDX.Matrix.Identity );
+                       }
+               }
        }
 }
diff --git a/StrokeStyleT/ステージ/選曲/曲パネルビューD2D.cs b/StrokeStyleT/ステージ/選曲/曲パネルビューD2D.cs
new file mode 100644 (file)
index 0000000..15cd759
--- /dev/null
@@ -0,0 +1,380 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using FDK.メディア;
+
+namespace SST.ステージ.選曲
+{
+       /// <summary>
+       /// 曲パネルリスト(9列3行)を表示する。
+       /// </summary>
+       /// <remarks>
+       /// 静止時の可視範囲は、左右両端の1列を除いた7列3行。
+       /// 左右両端の列は、静止時は画面外に位置しており、左右スクロール中にのみ画面内に一部が表示される。
+       /// 「カーソル」は、常に、曲パネル内のいずれか1枚の曲を選択している。
+       /// カーソルは、初期状態では中央の曲を選択しており、本クラスのメソッドを使って上下左右に移動することができる。
+       /// カーソルが選択している曲は強調表示(視覚効果として少し拡大して表示)される。
+       /// </remarks>
+       class 曲パネルビューD2D : FDK.Activity
+       {
+               public 曲パネルビューD2D()
+               {
+                       this.子リスト.Add( this.Nullパネルの画像 = new 画像( @"$(Static)\images\選曲パネル.png" ) );
+               }
+               protected override void On活性化( デバイスリソース dr )
+               {
+                       this.活性化した直後である = true;
+               }
+               protected override void On非活性化( デバイスリソース dr )
+               {
+               }
+               public void 進行描画する( デバイスリソース dr )
+               {
+                       // 進行。
+
+                       if( this.活性化した直後である )
+                       {
+                               this.活性化した直後である = false;
+                               this.横スクロール用カウンタ = new FDK.カウンタ.定間隔進行();
+                       }
+                       else
+                       {
+                               this.横スクロール用カウンタ.経過時間の分だけ進行する( 8, () => {
+
+                                       int オフセットの加減算速度 = 1;
+
+                                       #region " カーソルが中央から遠いほど速くなるよう、オフセットの加減算速度(絶対値)を計算する。"
+                                       //------------------
+                                       int 距離 = Math.Abs( 4 - this.カーソル位置.X );
+                                       if( 1 >= 距離 )
+                                               オフセットの加減算速度 = 2;
+                                       else if( 4 >= 距離 )
+                                               オフセットの加減算速度 = 4;
+                                       else if( 6 >= 距離 )
+                                               オフセットの加減算速度 = 6;
+                                       else
+                                               オフセットの加減算速度 = 8;
+                                       //------------------
+                                       #endregion
+
+                                       // オフセット と カーソル位置.X を更新する。
+                                       if( ( 4 > this.カーソル位置.X ) ||
+                                               ( ( 4 == this.カーソル位置.X ) && ( 0 > this.曲パネルのY軸回転オフセット ) ) )
+                                       {
+                                               #region "  パネルは、左から右へ、移動する。"
+                                               //-----------------
+                                               this.曲パネルのY軸回転オフセット += オフセットの加減算速度;
+
+                                               // 1列分移動した
+                                               if( 64 <= this.曲パネルのY軸回転オフセット )
+                                               {
+                                                       this.曲パネルのY軸回転オフセット -= 64;  // 0 付近に戻る
+                                                       this.カーソル位置.X++;
+                                               }
+                                               //-----------------
+                                               #endregion
+                                       }
+                                       else if( ( 4 < this.カーソル位置.X ) ||
+                                               ( ( 4 == this.カーソル位置.X ) && ( 0 < this.曲パネルのY軸回転オフセット ) ) )
+                                       {
+                                               #region " パネルは、右から左へ、移動する。"
+                                               //-----------------
+                                               this.曲パネルのY軸回転オフセット -= オフセットの加減算速度;
+
+                                               // 1列分移動した
+                                               if( -64 >= this.曲パネルのY軸回転オフセット )
+                                               {
+                                                       this.曲パネルのY軸回転オフセット += 64;  // 0 付近に戻る
+                                                       this.カーソル位置.X--;
+                                               }
+                                               //-----------------
+                                               #endregion
+                                       }
+
+                               } );
+                       }
+
+                       // 描画。
+
+                       Debug.Assert( null != StrokeStyleT.ユーザ管理 );
+                       Debug.Assert( null != StrokeStyleT.ユーザ管理.現在選択されているユーザ );
+                       Debug.Assert( null != StrokeStyleT.ユーザ管理.現在選択されているユーザ.曲ツリーのルートノード );
+
+                       var 曲リスト管理 = StrokeStyleT.曲ツリー管理;
+                       var 曲リスト = 曲リスト管理.現在選択されているノード?.親ノード.子ノードリスト ?? 曲リスト管理.現在の管理対象ツリー.子ノードリスト;
+                       var 描画する曲 = 曲リスト管理.現在選択されているノード;    // null 可
+                       var カーソル位置の曲 = (曲.Node) null;   // null 可
+
+                       #region " 左上隅パネルに対応する曲リストノードを検索する。"
+                       //-----------------
+                       int 現在のカーソルから左上隅までの差 = 0 - ( this.カーソル位置.X * 3 + this.カーソル位置.Y );   // 現在のカーソルの位置に、現在選択されている曲が対応するものとする。
+
+                       if( 0 < 現在のカーソルから左上隅までの差 )
+                       {
+                               // 曲リストを前方へたどる。
+                               for( int i = 0; i < 現在のカーソルから左上隅までの差; i++ )
+                                       描画する曲 = 描画する曲?.次のノード;
+                       }
+                       else
+                       {
+                               // 曲リストを後方へたどる。
+                               for( int i = 現在のカーソルから左上隅までの差; i < 0; i++ )
+                                       描画する曲 = 描画する曲?.前のノード;
+                       }
+                       //-----------------
+                       #endregion
+                       #region " 9×3枚の曲パネルを描画する。"
+                       //-----------------
+                       for( int i = 0; i < ( 9 * 3 ); i++ )
+                       {
+                               var パネル位置 = new SharpDX.Point( i / 3, i % 3 );
+
+                               if( パネル位置 == this.カーソル位置 )
+                               {
+                                       // カーソル位置にあるパネルは後で描画するので、覚えておく。
+                                       カーソル位置の曲 = 描画する曲;
+                               }
+                               else
+                               {
+                                       this.パネルを一枚描画する(
+                                               dr,
+                                               描画する曲,
+                                               パネル位置,
+                                               これはカーソル位置のパネルである: false );
+                               }
+
+                               // 次のノードへ移動。(選択ノードは移動しない。)
+                               描画する曲 = 描画する曲?.次のノード;
+                       }
+                       //-----------------
+                       #endregion
+                       #region " カーソル位置のパネルを描画する。"
+                       //-----------------
+                       if( ( 0 <= this.カーソル位置.X ) && ( 9 > this.カーソル位置.X ) &&
+                               ( 0 <= this.カーソル位置.Y ) && ( 3 > this.カーソル位置.Y ) )
+                       {
+                               this.パネルを一枚描画する(
+                                       dr,
+                                       カーソル位置の曲,   // 先の for ループ内で取得済み。
+                                       this.カーソル位置,
+                                       これはカーソル位置のパネルである: true );
+                       }
+                       //-----------------
+                       #endregion
+               }
+               public void カーソルを上に移動する()
+               {
+                       if( 0 < this.カーソル位置.Y )
+                       {
+                               this.カーソル位置.Y--;
+                       }
+                       else
+                       {
+                               this.カーソル位置.X--;
+                               this.カーソル位置.Y = 2;
+                       }
+
+                       // カーソルと一緒に、選択曲も移動する。
+                       StrokeStyleT.曲ツリー管理.前のノードを選択する();
+               }
+               public void カーソルを下に移動する()
+               {
+                       Debug.Assert( this.活性化している );
+
+                       if( 2 > this.カーソル位置.Y )
+                       {
+                               this.カーソル位置.Y++;
+                       }
+                       else
+                       {
+                               this.カーソル位置.X++;
+                               this.カーソル位置.Y = 0;
+                       }
+
+                       // カーソルと一緒に、選択曲も移動する。
+                       StrokeStyleT.曲ツリー管理.次のノードを選択する();
+               }
+               public void カーソルを左に移動する()
+               {
+                       Debug.Assert( this.活性化している );
+
+                       this.カーソル位置.X--;    // 制限なし
+
+                       // カーソルと一緒に、選択曲も移動する。
+                       StrokeStyleT.曲ツリー管理.前のノードを選択する();
+                       StrokeStyleT.曲ツリー管理.前のノードを選択する();
+                       StrokeStyleT.曲ツリー管理.前のノードを選択する();
+               }
+               public void カーソルを右に移動する()
+               {
+                       Debug.Assert( this.活性化している );
+
+                       this.カーソル位置.X++;    // 制限なし
+
+                       // カーソルと一緒に、選択曲も移動する。
+                       StrokeStyleT.曲ツリー管理.次のノードを選択する();
+                       StrokeStyleT.曲ツリー管理.次のノードを選択する();
+                       StrokeStyleT.曲ツリー管理.次のノードを選択する();
+               }
+
+               protected void パネルを一枚描画する(
+                       デバイスリソース dr,
+                       曲.Node パネルノード,  // null 可
+                       SharpDX.Point パネル位置,
+                       bool これはカーソル位置のパネルである = false )
+               {
+                       const float カーソル位置のパネルの拡大率 = 1.25f;
+
+                       #region " 2D変換行列を作成する(ノード画像、タイトル画像共通)。"
+                       //-----------------
+                       // 全体的に、画面中央のちょい上に移動する。
+                       float ちょい上dpx = -70.0f;    // ステージ台とパネルが接触しない程度の位置へ。
+                       var 変換行列2Dpx = dr.行列を単位変換するDPXtoPX(
+                               SharpDX.Matrix3x2.Translation(
+                                       dr.設計画面サイズdpx.Width / 2.0f,
+                                       dr.設計画面サイズdpx.Height / 2.0f + ちょい上dpx ) );
+
+                       if( これはカーソル位置のパネルである )
+                       {
+                               // 拡大する分だけ表示座標を移動する。
+                               変換行列2Dpx *= dr.行列を単位変換するDPXtoPX(
+                                       SharpDX.Matrix3x2.Translation(
+                                               -パネルサイズdpx.全体dpx.Width * ( カーソル位置のパネルの拡大率 - 1.0f ) / 2.0f,
+                                               -パネルサイズdpx.全体dpx.Height * ( カーソル位置のパネルの拡大率 - 1.0f ) / 2.0f ) );
+                       }
+                       //-----------------
+                       #endregion
+
+                       // パネル位置にオフセットを加味し、横位置の割合を算出する。
+                       const float 列間隔の角度 = 0.104f;    // 等間隔
+                       float 横位置割合 = 0.920f - ( パネル位置.X + ( this.曲パネルのY軸回転オフセット / 64.0f ) ) * 列間隔の角度;
+
+                       var 変換行列3Dpx = SharpDX.Matrix.Identity;
+
+                       if( null != パネルノード )
+                       {
+                               #region " 3D変換行列を作成してノード画像を表示する。"
+                               //-----------------
+                               変換行列3Dpx = SharpDX.Matrix.Scaling(
+                                       x: パネルサイズdpx.画像領域dpx.Width / パネルノード.ノード画像サイズdpx.Width, // ノード画像を設計値サイズに拡大縮小する。
+                                       y: パネルサイズdpx.画像領域dpx.Height / パネルノード.ノード画像サイズdpx.Height,
+                                       z: 1.0f );
+
+                               // カーソル位置なら拡大する。
+                               if( これはカーソル位置のパネルである )
+                                       変換行列3Dpx *= SharpDX.Matrix.Scaling( カーソル位置のパネルの拡大率 );
+
+                               // 曲面変換。
+                               変換行列3Dpx *= this.横位置割合からパネルの変換行列を算出して返す( dr, 横位置割合, パネル位置.Y );
+
+                               // 描画。
+                               パネルノード.ノード画像を描画する( dr, 変換行列2Dpx, 変換行列3Dpx );
+                               //-----------------
+                               #endregion
+                               #region " 3D変換行列を作成してタイトル画像を表示する。"
+                               //-----------------
+                               変換行列3Dpx = SharpDX.Matrix.Scaling(
+                                       x: パネルサイズdpx.タイトル領域dpx.Width / パネルノード.タイトル画像サイズdpx.Width,  // タイトル画像を設計値サイズに拡大縮小する。
+                                       y: パネルサイズdpx.タイトル領域dpx.Height / パネルノード.タイトル画像サイズdpx.Height,
+                                       z: 1.0f );
+
+                               // カーソル位置なら拡大する。
+                               if( これはカーソル位置のパネルである )
+                                       変換行列3Dpx *= SharpDX.Matrix.Scaling( カーソル位置のパネルの拡大率 );
+
+                               // 曲面変換。
+                               変換行列3Dpx *= this.横位置割合からパネルの変換行列を算出して返す( dr, 横位置割合, パネル位置.Y );
+
+                               // 描画。
+                               パネルノード.タイトル画像を描画する( dr, 変換行列2Dpx, 変換行列3Dpx );
+                               //-----------------
+                               #endregion
+                       }
+                       else
+                       {
+                               #region " 3D変換行列を作成してノード画像を表示する。"
+                               //-----------------
+                               変換行列3Dpx = SharpDX.Matrix.Scaling(
+                                       x: パネルサイズdpx.画像領域dpx.Width / this.Nullパネルの画像.サイズdpx.Width, // ノード画像を設計値サイズに拡大縮小する。
+                                       y: パネルサイズdpx.画像領域dpx.Height / this.Nullパネルの画像.サイズdpx.Height,
+                                       z: 1.0f );
+
+                               // カーソル位置なら拡大する。
+                               if( これはカーソル位置のパネルである )
+                                       変換行列3Dpx *= SharpDX.Matrix.Scaling( カーソル位置のパネルの拡大率 );
+
+                               // 曲面変換。
+                               変換行列3Dpx *= this.横位置割合からパネルの変換行列を算出して返す( dr, 横位置割合, パネル位置.Y );
+
+                               // 描画。
+                               this.Nullパネルの画像.進行描画する( dr, 変換行列2Dpx, 変換行列3Dpx );
+                               //-----------------
+                               #endregion
+                       }
+               }
+
+               protected SharpDX.Matrix 横位置割合からパネルの変換行列を算出して返す( デバイスリソース dr, float 横位置割合, int Y位置0to2 )
+               {
+                       // 原点が画像の左上隅から画像の中央へ来るように移動。
+                       var 変換行列3Dpx = SharpDX.Matrix.Translation(
+                               x: -( パネルサイズdpx.全体dpx.Width * dr.拡大率DPXtoPX横方法 / 2.0f ),
+                               y: -( パネルサイズdpx.全体dpx.Height * dr.拡大率DPXtoPX縦方向 / 2.0f ),
+                               z: 0.0f );
+
+                       // 縦方向の移動(上、中、下段のいずれかへ)。
+                       変換行列3Dpx *= SharpDX.Matrix.Translation(
+                               0.0f,
+                               ( ( ( Y位置0to2 - 1 ) * 230.0f ) ) * dr.拡大率DPXtoPX縦方向,    // 1行は 230 dpx
+                               0.0f );
+
+                       // Y軸回転半径分、画面奥に移動。
+                       変換行列3Dpx *= SharpDX.Matrix.Translation(
+                               0.0f,
+                               0.0f,
+                               -1000.0f * dr.拡大率DPXtoPX横方法 );   // 回転半径は 1000 dpx; Direct2D では、画面手前ほどZ軸がプラス。なお、Z 軸だがここでは 横方向 の拡大率を使用。
+
+                       // Y軸回転。
+                       変換行列3Dpx *= SharpDX.Matrix.RotationY(
+                               (float) Math.PI * ( 横位置割合 - 0.5f ) );
+
+                       // 画面に近いので、全体的に画面の奥へ移動。
+                       変換行列3Dpx *= SharpDX.Matrix.Translation(
+                               0.0f,
+                               0.0f,
+                               950.0f * dr.拡大率DPXtoPX横方法 );     // 移動量 950 dpx; なお、Z 軸だがここでは 横方向 の拡大率を使用。
+
+                       // 射影変換。
+                       変換行列3Dpx *= FDK.Utilities.D2DPerspectiveProjection(
+                               dr.設計画面サイズdpx.Height * 1.67f * dr.拡大率DPXtoPX横方法 );        // 深さは約 1800 [px; 縦1080px時]; Direc2D では、パラメータは深さのみ。なお、(同上
+
+                       return 変換行列3Dpx;
+               }
+
+               // 設計定数
+               protected struct パネルサイズdpx
+               {
+                       public static readonly SharpDX.Size2F 全体dpx = new SharpDX.Size2F( 314f, 220f );
+                       public static readonly SharpDX.RectangleF 画像領域dpx = new SharpDX.RectangleF( 0f, 0f, 313f, 137f );
+                       public static readonly SharpDX.RectangleF タイトル領域dpx = new SharpDX.RectangleF( 0f, 138f, 313f, 219f );
+               }
+
+               /// <summary>
+               /// 左上隅のパネルを (0,0) とした時の、カーソル位置の座標。
+               /// 負数も可。
+               /// </summary>
+               protected SharpDX.Point カーソル位置 = new SharpDX.Point( 4, 1 );
+
+               /// <summary>
+               /// -63~63。パネルの表示位置を、負数は 左 へ、正数は 右 へずらす 。(正負と左右の対応に注意。)
+               /// </summary>
+               /// <remarks>
+               /// ±64 は、パネル1列分を表すサイズ。
+               /// </remarks>
+               protected int 曲パネルのY軸回転オフセット = 0;
+
+               protected bool 活性化した直後である = false;
+               protected FDK.カウンタ.定間隔進行 横スクロール用カウンタ = null;
+               protected readonly FDK.メディア.画像 Nullパネルの画像;
+       }
+}
index d24f8a7..24a43b7 100644 (file)
@@ -112,9 +112,9 @@ namespace SST.ステージ.選曲
                        }
                }
 
-               protected readonly FDK.メディア.動画 背景動画 = new 動画( @"$(Static)\images\選曲画面BGV.mp4" );
-               protected readonly FDK.メディア.画像 ステージ台 = new 画像( @"$(Static)\images\ステージ台.png" );
-               protected readonly SST.ステージ.汎用.ドラムセット ドラムセット = new 汎用.ドラムセット();
-               protected readonly 曲パネルビュー 曲パネルビュー = new 曲パネルビュー();
+               protected FDK.メディア.動画 背景動画 = null;
+               protected FDK.メディア.画像 ステージ台 = null;
+               protected SST.ステージ.汎用.ドラムセット ドラムセット = null;
+               protected 曲パネルビュー 曲パネルビュー = null;
        }
 }