2 using System.Collections.Generic;
3 using System.Diagnostics;
10 /// 曲パネルリスト(9列3行)を表示する。
13 /// 静止時の可視範囲は、左右両端の1列を除いた7列3行。
14 /// 左右両端の列は、静止時は画面外に位置しており、左右スクロール中にのみ画面内に一部が表示される。
15 /// 「カーソル」は、常に、曲パネル内のいずれか1枚の曲を選択している。
16 /// カーソルは、初期状態では中央の曲を選択しており、本クラスのメソッドを使って上下左右に移動することができる。
17 /// カーソルが選択している曲は強調表示(視覚効果として少し拡大して表示)される。
19 class 曲パネルビュー : FDK.Activity
23 this.子リスト.Add( this.Nullパネルの画像 = new テクスチャ( @"$(Static)\images\選曲パネル.png" ) );
25 public void カーソルを上に移動する()
27 if( 0 < this.カーソル位置.Y )
38 StrokeStyleT.曲ツリー管理.前のノードを選択する();
40 public void カーソルを下に移動する()
42 if( 2 > this.カーソル位置.Y )
53 StrokeStyleT.曲ツリー管理.次のノードを選択する();
55 public void カーソルを左に移動する()
57 this.カーソル位置.X--; // 制限なし
60 StrokeStyleT.曲ツリー管理.前のノードを選択する();
61 StrokeStyleT.曲ツリー管理.前のノードを選択する();
62 StrokeStyleT.曲ツリー管理.前のノードを選択する();
64 public void カーソルを右に移動する()
66 this.カーソル位置.X++; // 制限なし
69 StrokeStyleT.曲ツリー管理.次のノードを選択する();
70 StrokeStyleT.曲ツリー管理.次のノードを選択する();
71 StrokeStyleT.曲ツリー管理.次のノードを選択する();
73 protected override void On活性化( デバイスリソース dr )
75 this.活性化した直後である = true;
77 protected override void On非活性化( デバイスリソース dr )
80 public void 進行描画する( デバイスリソース dr )
86 this.活性化した直後である = false;
87 this.横スクロール用カウンタ = new FDK.カウンタ.定間隔進行();
91 #region " カーソルの移動に伴う全パネルの横方向スクロール進行。"
93 this.横スクロール用カウンタ.経過時間の分だけ進行する( 8, () => {
97 #region " カーソルが中央から遠いほど速くなるよう、オフセットの加減算速度(絶対値)を計算する。"
99 int 距離 = Math.Abs( 4 - this.カーソル位置.X );
111 // オフセット と カーソル位置.X を更新する。
112 if( ( 4 > this.カーソル位置.X ) ||
113 ( ( 4 == this.カーソル位置.X ) && ( 0 > this.パネル全体のY軸回転オフセット ) ) )
115 #region " (A) パネルは、左から右へ、移動する。"
117 this.パネル全体のY軸回転オフセット += オフセットの加減算速度;
120 if( 64 <= this.パネル全体のY軸回転オフセット )
122 this.パネル全体のY軸回転オフセット -= 64; // 0 付近に戻る
128 else if( ( 4 < this.カーソル位置.X ) ||
129 ( ( 4 == this.カーソル位置.X ) && ( 0 < this.パネル全体のY軸回転オフセット ) ) )
131 #region " (B) パネルは、右から左へ、移動する。"
133 this.パネル全体のY軸回転オフセット -= オフセットの加減算速度;
136 if( -64 >= this.パネル全体のY軸回転オフセット )
138 this.パネル全体のY軸回転オフセット += 64; // 0 付近に戻る
152 Debug.Assert( null != StrokeStyleT.ユーザ管理?.現在選択されているユーザ?.曲ツリーのルートノード );
154 var 曲リスト管理 = StrokeStyleT.曲ツリー管理;
155 var 曲リスト = 曲リスト管理.現在選択されているノード?.親ノード.子ノードリスト ?? 曲リスト管理.現在の管理対象ツリー.子ノードリスト;
156 var 描画する曲 = 曲リスト管理.現在選択されているノード; // null 可
157 var カーソル位置の曲 = (曲.Node) null; // null 可
159 #region " 左上隅パネルに対応する曲リストノードを検索する。"
161 int 現在のカーソルから左上隅までの差 = 0 - ( this.カーソル位置.X * 3 + this.カーソル位置.Y ); // 現在のカーソルの位置に、現在選択されている曲が対応するものとする。
163 if( 0 < 現在のカーソルから左上隅までの差 )
166 for( int i = 0; i < 現在のカーソルから左上隅までの差; i++ )
167 描画する曲 = 描画する曲?.次のノード;
172 for( int i = 現在のカーソルから左上隅までの差; i < 0; i++ )
173 描画する曲 = 描画する曲?.前のノード;
177 #region " 9×3枚の曲パネルを描画する。"
179 for( int i = 0; i < ( 9 * 3 ); i++ )
181 var パネル位置 = new SharpDX.Point( i / 3, i % 3 );
183 if( パネル位置 == this.カーソル位置 )
185 // カーソル位置にあるパネルは後で描画するので、覚えておく。
190 this.パネルを一枚描画する( dr, 描画する曲, パネル位置, これはカーソル位置のパネルである: false );
193 // 次のノードへ移動。(選択ノードは移動しない。)
194 描画する曲 = 描画する曲?.次のノード;
198 #region " カーソル位置のパネルを描画する。"
200 if( ( 0 <= this.カーソル位置.X ) && ( 9 > this.カーソル位置.X ) &&
201 ( 0 <= this.カーソル位置.Y ) && ( 3 > this.カーソル位置.Y ) )
205 カーソル位置の曲, // 先の for ループ内で取得済み。
207 これはカーソル位置のパネルである: true );
213 protected const float カーソル位置のパネルの拡大率 = 1.25f;
214 protected bool 活性化した直後である = false;
215 protected readonly FDK.メディア.テクスチャ Nullパネルの画像;
216 protected FDK.カウンタ.定間隔進行 横スクロール用カウンタ = null;
218 /// 左上隅のパネルを (0,0) とした時の、カーソル位置の座標。
221 protected SharpDX.Point カーソル位置 = new SharpDX.Point( 4, 1 );
223 /// -63~63。パネル全体の表示位置を、負数は 左 へ、正数は 右 へずらす 。(正負と左右の対応に注意。)
226 /// ±64 は、パネル1列分を表すサイズ。
228 protected int パネル全体のY軸回転オフセット = 0;
231 /// パネルを一枚(ノード画像とタイトル画像)を、指定したパネル位置に描画する。
233 /// <param name="パネルノード">null 可。</param>
234 protected void パネルを一枚描画する( デバイスリソース dr, 曲.Node パネルノード, SharpDX.Point パネル位置, bool これはカーソル位置のパネルである = false )
236 // 画面を見ながら直観的に調整した固定パラメータたち。
237 const float 見かけの倍率 = 3.0f;
238 const float パネル全体のY方向移動量dpx = +250f; // パネル全体を少しだけ上にシフトする。
239 const float パネル全体のZ方向移動量dpx = +3000f;
240 const float 行間 = 1.1f;
241 const float パネル間X方向角度deg = 19f;
245 var 拡大縮小 = SharpDX.Matrix.Scaling( パネルノード.ノードの全体サイズdpx.Width, パネルノード.ノードの全体サイズdpx.Height, 1f )
246 * SharpDX.Matrix.Scaling( 見かけの倍率 );
248 var 平行移動 = SharpDX.Matrix.Translation(
250 パネル全体のY方向移動量dpx + ( 1 - パネル位置.Y ) * ( パネルノード.ノードの全体サイズdpx.Height * 見かけの倍率 * 行間 ),
253 var Y軸回転 = SharpDX.Matrix.RotationY( SharpDX.MathUtil.DegreesToRadians( ( パネル位置.X - 4 ) * パネル間X方向角度deg ) );
255 this.Nullパネルの画像.進行描画する( dr, ( 拡大縮小 * 平行移動 * Y軸回転 ) );
261 var 拡大縮小 = SharpDX.Matrix.Scaling( パネルノード.ノードの画像領域のサイズdpx.Width, パネルノード.ノードの画像領域のサイズdpx.Height, 1f )
262 * SharpDX.Matrix.Scaling( 見かけの倍率 );
264 var 平行移動 = SharpDX.Matrix.Translation(
267 + ( 1 - パネル位置.Y ) * ( パネルノード.ノードの全体サイズdpx.Height * 見かけの倍率 * 行間 )
268 + ( パネルノード.ノードのタイトル領域のサイズdpx.Height / 2f ) * 見かけの倍率,
269 パネル全体のZ方向移動量dpx + 1f );
271 var Y軸回転 = SharpDX.Matrix.RotationY( SharpDX.MathUtil.DegreesToRadians( ( パネル位置.X - 4 ) * パネル間X方向角度deg ) );
273 パネルノード.ノード画像を描画する( dr, ( 拡大縮小 * 平行移動 * Y軸回転 ) );
278 float 幅dpx = Math.Min( パネルノード.タイトル画像サイズdpx.Width, パネルノード.ノードのタイトル領域のサイズdpx.Width ); // 左右にはみ出さないよう圧縮
279 var 拡大縮小 = SharpDX.Matrix.Scaling( 幅dpx, パネルノード.タイトル画像サイズdpx.Height, 1f )
280 * SharpDX.Matrix.Scaling( 見かけの倍率 );
282 var 平行移動 = SharpDX.Matrix.Translation(
285 + ( 1 - パネル位置.Y ) * ( パネルノード.ノードの全体サイズdpx.Height * 見かけの倍率 * 行間 )
286 - ( パネルノード.ノードの画像領域のサイズdpx.Height / 2f ) * 見かけの倍率,
287 パネル全体のZ方向移動量dpx + 2f );
289 var Y軸回転 = SharpDX.Matrix.RotationY( SharpDX.MathUtil.DegreesToRadians( ( パネル位置.X - 4 ) * パネル間X方向角度deg ) );
291 パネルノード.タイトル画像を描画する( dr, ( 拡大縮小 * 平行移動 * Y軸回転 ) );