/// <param name="行番号"> /// 一番上:0 ~ 9:一番下。 /// 「静止時の」可視範囲は 1~8。 /// 4 がフォーカスノード。 /// </param> private void _ノードを描画する(DeviceContext1 dc, int 行番号, Node ノード) { Debug.Assert(0 <= 行番号 && 9 >= 行番号); Debug.Assert(null != ノード); Debug.Assert((ノード as RootNode) is null); var ノード画像 = ノード.ノード画像 ?? Node.既定のノード画像; bool 選択ノードである = (4 == 行番号); if (null == ノード画像) { return; } // テクスチャは画面中央が (0,0,0) で、Xは右がプラス方向, Yは上がプラス方向, Zは奥がプラス方向+。 var 画面左上dpx = new Vector3( // 3D視点で見る画面左上の座標。 -グラフィックデバイス.Instance.設計画面サイズ.Width / 2f, +グラフィックデバイス.Instance.設計画面サイズ.Height / 2f, 0f); var 実数行番号 = 行番号 + (this._曲リスト全体のY軸移動オフセット / 100f); var ノード左上dpx = new Vector3( this._曲リストの基準左上隅座標dpx.X + ((選択ノードである) ? (float)this._選択ノードの表示オフセットdpx.Value : 0f), this._曲リストの基準左上隅座標dpx.Y + (実数行番号 * _ノードの高さdpx), 0f); #region " 背景 " //---------------- グラフィックデバイス.Instance.D2DBatchDraw(dc, () => { if (ノード is BoxNode) { #region " BOXノードの背景 " //---------------- using (var brush = new SolidColorBrush(dc, new Color4(0xffa3647c))) { using (var pathGeometry = new PathGeometry(グラフィックデバイス.Instance.D2DFactory)) { using (var sink = pathGeometry.Open()) { sink.SetFillMode(FillMode.Winding); sink.BeginFigure(new Vector2(ノード左上dpx.X, ノード左上dpx.Y + 8f), FigureBegin.Filled); // 1 var points = new SharpDX.Mathematics.Interop.RawVector2[] { new Vector2(ノード左上dpx.X + 150f, ノード左上dpx.Y + 8f), // 2 new Vector2(ノード左上dpx.X + 170f, ノード左上dpx.Y + 18f), // 3 new Vector2(グラフィックデバイス.Instance.設計画面サイズ.Width, ノード左上dpx.Y + 18f), // 4 new Vector2(グラフィックデバイス.Instance.設計画面サイズ.Width, ノード左上dpx.Y + _ノードの高さdpx), // 5 new Vector2(ノード左上dpx.X, ノード左上dpx.Y + _ノードの高さdpx), // 6 new Vector2(ノード左上dpx.X, ノード左上dpx.Y + 8f), // 1 }; sink.AddLines(points); sink.EndFigure(FigureEnd.Closed); sink.Close(); } dc.FillGeometry(pathGeometry, brush); } } //---------------- #endregion } else if (ノード is BackNode) { #region " BACKノードの背景 " //---------------- using (var brush = new SolidColorBrush(dc, Color4.Black)) { using (var pathGeometry = new PathGeometry(グラフィックデバイス.Instance.D2DFactory)) { using (var sink = pathGeometry.Open()) { sink.SetFillMode(FillMode.Winding); sink.BeginFigure(new Vector2(ノード左上dpx.X, ノード左上dpx.Y + 8f), FigureBegin.Filled); // 1 var points = new SharpDX.Mathematics.Interop.RawVector2[] { new Vector2(ノード左上dpx.X + 150f, ノード左上dpx.Y + 8f), // 2 new Vector2(ノード左上dpx.X + 170f, ノード左上dpx.Y + 18f), // 3 new Vector2(グラフィックデバイス.Instance.設計画面サイズ.Width, ノード左上dpx.Y + 18f), // 4 new Vector2(グラフィックデバイス.Instance.設計画面サイズ.Width, ノード左上dpx.Y + _ノードの高さdpx), // 5 new Vector2(ノード左上dpx.X, ノード左上dpx.Y + _ノードの高さdpx), // 6 new Vector2(ノード左上dpx.X, ノード左上dpx.Y + 8f), // 1 }; sink.AddLines(points); sink.EndFigure(FigureEnd.Closed); sink.Close(); } dc.FillGeometry(pathGeometry, brush); } } //---------------- #endregion } else { #region " 既定の背景(半透明の黒)" //---------------- using (var brush = new SolidColorBrush(dc, new Color4(0f, 0f, 0f, 0.25f))) dc.FillRectangle(new RectangleF(ノード左上dpx.X, ノード左上dpx.Y, グラフィックデバイス.Instance.設計画面サイズ.Width - ノード左上dpx.X, _ノードの高さdpx), brush); //---------------- #endregion } }); //---------------- #endregion #region " サムネイル画像 " //---------------- if (ノード is BoxNode) { #region " BOXノードのサムネイル画像 → 少し小さく表示する(涙 " //---------------- var ノード内サムネイルオフセットdpx = new Vector3(58f, 4f, 0f); var サムネイル表示中央dpx = new Vector3( 画面左上dpx.X + ノード左上dpx.X + (this._サムネイル表示サイズdpx.X / 2f) + ノード内サムネイルオフセットdpx.X, 画面左上dpx.Y - ノード左上dpx.Y - (this._サムネイル表示サイズdpx.Y / 2f) - ノード内サムネイルオフセットdpx.Y, 0f); var 換行列 = Matrix.Scaling(this._サムネイル表示サイズdpx * 0.9f) * // ちょっと小さく Matrix.Translation(サムネイル表示中央dpx - 4f); // ちょっと下へ ノード.進行描画する(dc, 換行列, キャプション表示: false); //---------------- #endregion } else if (ノード is BackNode) { // BACKノードはサムネイル画像なし } else { #region " 既定のサムネイル画像 " //---------------- var ノード内サムネイルオフセットdpx = new Vector3(58f, 4f, 0f); var サムネイル表示中央dpx = new Vector3( 画面左上dpx.X + ノード左上dpx.X + (this._サムネイル表示サイズdpx.X / 2f) + ノード内サムネイルオフセットdpx.X, 画面左上dpx.Y - ノード左上dpx.Y - (this._サムネイル表示サイズdpx.Y / 2f) - ノード内サムネイルオフセットdpx.Y, 0f); var 換行列 = Matrix.Scaling(this._サムネイル表示サイズdpx) * Matrix.Translation(サムネイル表示中央dpx); ノード.進行描画する(dc, 換行列, キャプション表示: false); //---------------- #endregion } //---------------- #endregion #region " タイトル文字列 " //---------------- { var 曲名画像 = (文字列画像)null; // 曲名画像を取得する。未生成なら生成する。 if (!(this._ノードto曲名画像.ContainsKey(ノード))) { 曲名画像 = new 文字列画像() { 表示文字列 = ノード.タイトル, フォント名 = "HGMaruGothicMPRO", // "メイリオ", フォント幅 = FontWeight.Regular, フォントスタイル = FontStyle.Normal, フォントサイズpt = 40f, 描画効果 = 文字列画像.効果.縁取り, 縁のサイズdpx = 6f, 前景色 = Color4.Black, 背景色 = Color4.White, }; 曲名画像.活性化する(); this._ノードto曲名画像.Add(ノード, 曲名画像); } else { 曲名画像 = this._ノードto曲名画像[ノード]; } // 拡大率を計算して描画する。 float 最大幅dpx = グラフィックデバイス.Instance.設計画面サイズ.Width - ノード左上dpx.X - 170f; 曲名画像.描画する( dc, ノード左上dpx.X + 170f, ノード左上dpx.Y + 30f, X方向拡大率: (曲名画像.画像サイズdpx.Width <= 最大幅dpx) ? 1f : 最大幅dpx / 曲名画像.画像サイズdpx.Width); } //---------------- #endregion #region " サブタイトル文字列 " //---------------- if (ノード == App.曲ツリー.フォーカスノード) // フォーカスノードのみ表示する。 { var サブタイトル画像 = (文字列画像)null; // ノードが SetNode なら難易度アンカに応じた MusicNode が対象。 if (ノード is SetNode setnode) { ノード = App.曲ツリー.現在の難易度に応じた曲ノードを返す(setnode); } // サブタイトル画像を取得する。未生成かつ指定があるなら生成する。 if (!(this._ノードtoサブタイトル画像.ContainsKey(ノード))) { if (ノード.サブタイトル.Nullでも空でもない()) { サブタイトル画像 = new 文字列画像() { 表示文字列 = ノード.サブタイトル, フォント名 = "HGMaruGothicMPRO", // "メイリオ", フォント幅 = FontWeight.Regular, フォントスタイル = FontStyle.Normal, フォントサイズpt = 20f, 描画効果 = 文字列画像.効果.縁取り, 縁のサイズdpx = 4f, 前景色 = Color4.Black, 背景色 = Color4.White, }; サブタイトル画像.活性化する(); this._ノードtoサブタイトル画像.Add(ノード, サブタイトル画像); } else { // 指定がない サブタイトル画像 = null; } } else { サブタイトル画像 = this._ノードtoサブタイトル画像[ノード]; } // 拡大率を計算して描画する。 if (null != サブタイトル画像) { float 最大幅dpx = グラフィックデバイス.Instance.設計画面サイズ.Width - ノード左上dpx.X - 170f; サブタイトル画像.描画する( dc, ノード左上dpx.X + 190f, ノード左上dpx.Y + 80f, X方向拡大率: (サブタイトル画像.画像サイズdpx.Width <= 最大幅dpx) ? 1f : 最大幅dpx / サブタイトル画像.画像サイズdpx.Width); } } //---------------- #endregion }