public override void Dispose() { using var _ = new LogBlock(Log.現在のメソッド名); this._白ブラシ.Dispose(); this._黒ブラシ.Dispose(); this._濃いブラシ.Dispose(); this._ふつうのブラシ.Dispose(); this._明るいブラシ.Dispose(); foreach (var s in this._シャッターアニメーション) { s.Dispose(); } this._ロゴボード?.Dispose(); this._ロゴ不透明度?.Dispose(); this._ロゴ.Dispose(); base.Dispose(); }
// 再生、停止 /// <summary> /// 指定した時刻からデコードを開始する。 /// </summary> public void Start(double 再生開始時刻sec) { using var _ = new LogBlock(Log.現在のメソッド名); if (再生開始時刻sec >= this.総演奏時間sec) { return; } this._デコード起動完了通知.Reset(); this._一時停止解除通知.Set(); // (1) デコードタスク起動、デコード開始。 this._デコードタスク = Task.Factory.StartNew( // Task.Factory.StartNew は常に MTAThread this._デコードタスクエントリ, (再生開始時刻sec, this.再生速度), this._デコードキャンセル.Token); // (2) デコードから起動完了通知がくるまでブロック。 this._デコード起動完了通知.Wait(); }
public override void Dispose() { using var _ = new LogBlock(Log.現在のメソッド名); this._斜めレイヤーパラメータ.GeometricMask = null; // 参照してるので先に手放す this._斜めジオメトリマスク.Dispose(); if (null != this._黒幕アニメーション) { foreach (var b in this._黒幕アニメーション) { b.Dispose(); } } this._画面D_アイキャッチ遷移画面2_逆回転中.Dispose(); this._画面BC_アイキャッチ遷移画面1_回転中.Dispose(); this._ロゴ.Dispose(); base.Dispose(); }
// 登録、発声停止、再開 /// <summary> /// 指定したWAV番号にサウンドファイルを登録する。 /// </summary> /// <remarks> /// サウンドの生成に失敗した場合には登録を行わない。 /// </remarks> /// <param name="wav番号">登録する番号。0~1295。すでに登録されている場合は上書き更新される。</param> /// <param name="サウンドファイル">登録するサウンドファイルのパス。</param> public void 登録する(int wav番号, VariablePath サウンドファイル, bool 多重再生する, bool BGMである) { using var _ = new LogBlock(Log.現在のメソッド名); if ((0 > wav番号) || (36 * 36 <= wav番号)) { throw new ArgumentOutOfRangeException($"WAV番号が範囲(0~1295)を超えています。[{wav番号}]"); } if (!(File.Exists(サウンドファイル.数なしパス))) { Log.WARNING($"サウンドファイルが存在しません。[{サウンドファイル.変数付きパス}]"); return; } // 先に ISampleSource を生成する。 var sampleSource = Global.App.WAVキャッシュ.作成する(サウンドファイル); if (sampleSource is null) { Log.WARNING($"サウンドのデコードに失敗しました。[{サウンドファイル.変数付きパス}"); return; } // サウンドを登録する。 if (this._WAV情報リスト.ContainsKey(wav番号)) { this._WAV情報リスト[wav番号].Dispose(); // すでに登録済みなら先に解放する。 } int 多重度 = (多重再生する) ? this._既定の多重度 : 1; this._WAV情報リスト[wav番号] = new WAV情報(wav番号, 多重度, BGMである); this._WAV情報リスト[wav番号].サウンドを生成する(Global.App.サウンドデバイス, sampleSource); Log.Info($"サウンドを読み込みました。[{サウンドファイル.変数付きパス}]"); }
/// <summary> /// アイキャッチのオープンアニメーションを開始する。 /// </summary> public override void オープンする(float 速度倍率 = 1.0f) { using var _ = new LogBlock(Log.現在のメソッド名); double 秒(double v) => (v / 速度倍率); var animation = Global.Animation; double 最も遅い時刻sec = 0.0; foreach (var s in this._シャッターアニメーション) { if (最も遅い時刻sec < s.完全閉じ時刻sec) { 最も遅い時刻sec = s.完全閉じ時刻sec; } } var start = animation.Timer.Time; var end = start + 秒(最も遅い時刻sec); for (int i = 0; i < シャッター枚数; i++) { using var 開閉遷移 = animation.TrasitionLibrary.SmoothStop(maximumDuration: 秒(this._シャッターアニメーション[i].開閉時間sec), finalValue: 0.0); // 終了値: 0.0(完全開き) this._シャッターアニメーション[i].開to閉割合?.Dispose(); this._シャッターアニメーション[i].開to閉割合 = new Variable(animation.Manager, initialValue: 1.0); // 初期値 1.0(完全閉じ) this._シャッターアニメーション[i].ストーリーボード?.Dispose(); this._シャッターアニメーション[i].ストーリーボード = new Storyboard(animation.Manager); this._シャッターアニメーション[i].ストーリーボード.AddTransition(this._シャッターアニメーション[i].開to閉割合, 開閉遷移); this._シャッターアニメーション[i].ストーリーボード.Schedule(end - 秒(this._シャッターアニメーション[i].完全閉じ時刻sec)); // 開始時刻: 完全閉じ時刻 } this._ロゴ不透明度?.Dispose(); this._ロゴ不透明度 = new Variable(animation.Manager, initialValue: 1.0); // 初期値 0.0(完全不透明) using var _不透明度遷移 = animation.TrasitionLibrary.Linear(duration: 秒(0.75), finalValue: 0.0); // 終了値 0.0(完全透明) this._ロゴボード = new Storyboard(animation.Manager); this._ロゴボード.AddTransition(this._ロゴ不透明度, _不透明度遷移); this._ロゴボード.Schedule(start); this.現在のフェーズ = フェーズ.オープン; }
private void _進行描画タスクを終了する() { using var _ = new LogBlock(Log.現在のメソッド名); if (Thread.CurrentThread.ManagedThreadId != this._進行描画タスクのNETスレッドID) { // 進行描画タスクに終了を指示し、完了を待つ。 var msg = new TaskMessage( 宛先: TaskMessage.タスク名.進行描画, 内容: TaskMessage.内容名.終了指示); if (!Global.TaskMessageQueue.Post(msg).Wait(5000)) // 最大5秒待つ { throw new TimeoutException("進行描画タスクの終了がタイムアウトしました。"); } } else { // ハングアップ回避; 念のため。 Log.WARNING("進行描画タスクから呼び出されました。完了通知待ちをスキップします。"); } }
// 進行と描画 private ManualResetEvent _進行描画タスクを起動する() { using var _ = new LogBlock(Log.現在のメソッド名); var 起動完了通知 = new ManualResetEvent(false); var app = this; var hWindow = app.Handle; Task.Run(() => { Log.現在のスレッドに名前をつける("進行描画"); Log.Info("進行描画タスクを起動しました。"); this._進行描画タスクのNETスレッドID = Thread.CurrentThread.ManagedThreadId; Thread.CurrentThread.Priority = ThreadPriority.AboveNormal; 起動完了通知.Set(); this._進行描画のメインループを実行する(app, hWindow); }); return(起動完了通知); }
/// <summary> /// 世代を1つ加算する。 /// </summary> public void 世代を進める() { using var _ = new LogBlock(Log.現在のメソッド名); // 今回の世代では貸与されなかった(=最終貸与世代が現時点の世代ではない)キャッシュデータをすべて破棄する。 var 削除対象リスト = this._キャッシュデータリスト .Where((kvp) => kvp.Value.最終貸与世代 < this.現世代) .Select((kvp) => kvp.Key) .ToArray(); foreach (var key in 削除対象リスト) { this._キャッシュデータリスト[key].Dispose(); this._キャッシュデータリスト.Remove(key); } Log.Info($"{this._キャッシュデータリスト.Count} 個のサウンドのうち、{削除対象リスト.Length} 個を削除しました。"); // 世代番号を1つ加算する。 this.現世代++; }
/// <summary> /// アプリケーションの終了処理を行う。 /// </summary> protected override void OnClosing(CancelEventArgs e) { Log.Header("アプリケーション終了"); using var _ = new LogBlock(Log.現在のメソッド名); // 進行描画タスクのメインループに終了指示を送り、終了するのを待つ。 this._進行描画タスクを終了する(); // システム設定ファイルを保存する。 this.システム設定.保存する(); // 入力デバイスを破棄する。 this.MidiIns.Dispose(); this.GameControllersHID.Dispose(); this.KeyboardHID.Dispose(); // サウンドデバイスとサウンドタイマを破棄する。 this.サウンドタイマ.Dispose(); this.サウンドデバイス.Dispose(); this.WAVキャッシュ?.Dispose(); // WAVキャッシュの破棄は最後に。 // 未初期化状態へ。 this._未初期化 = true; base.OnClosing(e); }
/// <summary> /// デコードを終了する。 /// </summary> public void Stop() { using var _ = new LogBlock(Log.現在のメソッド名); if ((null != this._デコードタスク) && !(this._デコードタスク.IsCompleted)) // デコードタスク起動中? { // (1) デコードタスクにキャンセルを通知。 this._デコードキャンセル.Cancel(); // (2) デコードタスクがキューでブロックしてたら解除する。 this._FrameQueue.Cancel(); // (3) デコードタスクが一時停止中でブロックしてたら解除する。 this._一時停止解除通知.Set(); // (4) デコードタスクが終了するまで待つ。 if (!(this._デコードタスク.Wait(5000))) // 最大5秒 { Log.ERROR($"デコードタスクの終了がタイムアウトしました。"); } this._デコードタスク = null; } }
// オープンとクローズ /// <summary> /// アイキャッチのクローズアニメーションを開始する。 /// </summary> public override void クローズする(float 速度倍率 = 1.0f) { using var _ = new LogBlock(Log.現在のメソッド名); double 秒(double v) => (v / 速度倍率); var animation = Global.Animation; this._アニメーション?.Dispose(); this._アニメーション = new アニメ(animation.Manager); const double 期間sec = 0.4; #region " (1) 背景マスク のアニメーション構築 " //---------------- this._アニメーション.背景_不透明度 = new Variable(animation.Manager, initialValue: 0.0); using (var 透明度の遷移 = animation.TrasitionLibrary.Linear(duration: 秒(期間sec), finalValue: 0.7)) { this._アニメーション.ストーリーボード.AddTransition(this._アニメーション.背景_不透明度, 透明度の遷移); } //---------------- #endregion #region " (2) 黒幕1(左下) のアニメーション構築 " //---------------- this._アニメーション.黒幕1左下_基点位置X = new Variable(animation.Manager, initialValue: -500.0); this._アニメーション.黒幕1左下_回転角rad = new Variable(animation.Manager, initialValue: Math.PI * 0.75); using (var 基点位置Xの遷移1 = animation.TrasitionLibrary.Linear(duration: 秒(期間sec * 0.2), finalValue: 0.0)) using (var 基点位置Xの遷移2 = animation.TrasitionLibrary.Linear(duration: 秒(期間sec * 0.8), finalValue: Global.GraphicResources.設計画面サイズ.Width / 2.0)) using (var 回転角の遷移 = animation.TrasitionLibrary.Linear(duration: 秒(期間sec), finalValue: 0.0)) { this._アニメーション.ストーリーボード.AddTransition(this._アニメーション.黒幕1左下_基点位置X, 基点位置Xの遷移1); this._アニメーション.ストーリーボード.AddTransition(this._アニメーション.黒幕1左下_基点位置X, 基点位置Xの遷移2); this._アニメーション.ストーリーボード.AddTransition(this._アニメーション.黒幕1左下_回転角rad, 回転角の遷移); } //---------------- #endregion #region " (3) 黒幕2(右上) のアニメーション構築 " //---------------- this._アニメーション.黒幕2右上_基点位置X = new Variable(animation.Manager, initialValue: Global.GraphicResources.設計画面サイズ.Width + 500.0); this._アニメーション.黒幕2右上_回転角rad = new Variable(animation.Manager, initialValue: Math.PI * 0.75f); using (var 基点位置Xの遷移1 = animation.TrasitionLibrary.Linear(duration: 秒(期間sec * 0.2), finalValue: Global.GraphicResources.設計画面サイズ.Width)) using (var 基点位置Xの遷移2 = animation.TrasitionLibrary.Linear(duration: 秒(期間sec * 0.8), finalValue: Global.GraphicResources.設計画面サイズ.Width / 2.0)) using (var 回転角の遷移 = animation.TrasitionLibrary.Linear(duration: 秒(期間sec), finalValue: 0.0)) { this._アニメーション.ストーリーボード.AddTransition(this._アニメーション.黒幕2右上_基点位置X, 基点位置Xの遷移1); this._アニメーション.ストーリーボード.AddTransition(this._アニメーション.黒幕2右上_基点位置X, 基点位置Xの遷移2); this._アニメーション.ストーリーボード.AddTransition(this._アニメーション.黒幕2右上_回転角rad, 回転角の遷移); } //---------------- #endregion #region " (4) ロゴ のアニメーション構築 " //---------------- this._アニメーション.ロゴ_位置X = new Variable(animation.Manager, initialValue: 1222.0 - 150.0); this._アニメーション.ロゴ_不透明度 = new Variable(animation.Manager, initialValue: 0.0); using (var 位置Xの遷移 = animation.TrasitionLibrary.AccelerateDecelerate(duration: 秒(期間sec), finalValue: 1222.0, accelerationRatio: 0.1, decelerationRatio: 0.9)) using (var 透明度の遷移 = animation.TrasitionLibrary.Linear(duration: 秒(期間sec), finalValue: 1.0)) { this._アニメーション.ストーリーボード.AddTransition(this._アニメーション.ロゴ_位置X, 位置Xの遷移); this._アニメーション.ストーリーボード.AddTransition(this._アニメーション.ロゴ_不透明度, 透明度の遷移); } //---------------- #endregion using (var 時間稼ぎ = animation.TrasitionLibrary.Constant(duration: 秒(0.5))) this._アニメーション.ストーリーボード.AddTransition(this._アニメーション.ロゴ_位置X, 時間稼ぎ); // 今すぐ開始。 this._アニメーション.ストーリーボード.Schedule(animation.Timer.Time); this.現在のフェーズ = フェーズ.クローズ; }
// 生成と終了 public シャッター() { using var _ = new LogBlock(Log.現在のメソッド名); this._ロゴ = new 画像(@"$(Images)\TitleLogo.png"); var dc = Global.既定のD2D1DeviceContext; this._明るいブラシ = new SolidColorBrush(dc, new Color4(83f / 255f, 210f / 255f, 255f / 255f, 1f)); this._ふつうのブラシ = new SolidColorBrush(dc, new Color4(46f / 255f, 117f / 255f, 182f / 255f, 1f)); this._濃いブラシ = new SolidColorBrush(dc, new Color4(0f / 255f, 32f / 255f, 96f / 255f, 1f)); this._黒ブラシ = new SolidColorBrush(dc, Color4.Black); this._白ブラシ = new SolidColorBrush(dc, Color4.White); this._シャッターアニメーション = new シャッター情報[シャッター枚数] { #region " *** " //---------------- new シャッター情報() // 1 { ブラシ = this._明るいブラシ, 矩形サイズ = new Size2F(910f, 908f), 角度rad = (float)Math.PI / 4f, 閉じ中心位置 = new Vector2(0f, 1080f), 開き中心位置 = new Vector2(0f - 450, 1080f + 450f), 完全開き時刻sec = 0.0, 開閉時間sec = 0.2, }, new シャッター情報() // 2 { ブラシ = this._濃いブラシ, 矩形サイズ = new Size2F(1000f, 992f), 角度rad = (float)Math.PI / 4f, 閉じ中心位置 = new Vector2(1920f, 0f), 開き中心位置 = new Vector2(1920f + 500f, 0f - 500f), 完全開き時刻sec = 0.03, 開閉時間sec = 0.2, }, new シャッター情報() // 3 { ブラシ = this._黒ブラシ, 矩形サイズ = new Size2F(915f, 911f), 角度rad = (float)Math.PI / -4f, 閉じ中心位置 = new Vector2(0f, 0f), 開き中心位置 = new Vector2(0f - 450f, 0f - 450f), 完全開き時刻sec = 0.075, 開閉時間sec = 0.2, }, new シャッター情報() // 4 { ブラシ = this._ふつうのブラシ, 矩形サイズ = new Size2F(884, 885f), 角度rad = (float)Math.PI / -4f, 閉じ中心位置 = new Vector2(1920f, 1080f), 開き中心位置 = new Vector2(1920f + 450f, 1080f + 450f), 完全開き時刻sec = 0.06, 開閉時間sec = 0.2, }, new シャッター情報() // 5 { ブラシ = this._濃いブラシ, 矩形サイズ = new Size2F(370f, 740f), 角度rad = (float)0f, 閉じ中心位置 = new Vector2(104f + 185f, 541f), 開き中心位置 = new Vector2(104f + 185f - 500f, 541f), 完全開き時刻sec = 0.16, 開閉時間sec = 0.2, }, new シャッター情報() // 6 { ブラシ = this._黒ブラシ, 矩形サイズ = new Size2F(280f, 560f), 角度rad = (float)0f, 閉じ中心位置 = new Vector2(1519 + 140f, 570f), 開き中心位置 = new Vector2(1519 + 140f + 400f, 570f), 完全開き時刻sec = 0.2, 開閉時間sec = 0.2, }, new シャッター情報() // 7 { ブラシ = this._明るいブラシ, 矩形サイズ = new Size2F(780f, 788f), 角度rad = (float)Math.PI / 4f, 閉じ中心位置 = new Vector2(1521f, 1080f), 開き中心位置 = new Vector2(1521f + 390f, 1080f + 390f), 完全開き時刻sec = 0.2, 開閉時間sec = 0.2, }, new シャッター情報() // 8 { ブラシ = this._黒ブラシ, 矩形サイズ = new Size2F(1114f, 495f), 角度rad = (float)Math.PI / 4f, 閉じ中心位置 = new Vector2(1236f, 178f), 開き中心位置 = new Vector2(1236f + 400f, 178f - 400f), 完全開き時刻sec = 0.23, 開閉時間sec = 0.2, }, new シャッター情報() // 9 { ブラシ = this._黒ブラシ, 矩形サイズ = new Size2F(652f, 312f), 角度rad = (float)0f, 閉じ中心位置 = new Vector2(479f + 323f, 1080f), 開き中心位置 = new Vector2(479f + 323f, 1080f + 160f), 完全開き時刻sec = 0.3, 開閉時間sec = 0.2, }, new シャッター情報() // 10 { ブラシ = this._ふつうのブラシ, 矩形サイズ = new Size2F(412f, 288f), 角度rad = (float)0f, 閉じ中心位置 = new Vector2(666f, 0f), 開き中心位置 = new Vector2(666f, 0f - 200f), 完全開き時刻sec = 0.33, 開閉時間sec = 0.2, }, new シャッター情報() // 11 { ブラシ = this._黒ブラシ, 矩形サイズ = new Size2F(630f, 630f), 角度rad = (float)Math.PI / 4f, 閉じ中心位置 = new Vector2(460f, 930f), 開き中心位置 = new Vector2(460f - 330f, 930f + 330f), 完全開き時刻sec = 0.36, 開閉時間sec = 0.2, }, new シャッター情報() // 12 { ブラシ = this._明るいブラシ, 矩形サイズ = new Size2F(875f, 884f), 角度rad = (float)Math.PI / -4f, 閉じ中心位置 = new Vector2(461f, 138f), 開き中心位置 = new Vector2(461f - 438f, 138f - 438f), 完全開き時刻sec = 0.36, 開閉時間sec = 0.2, }, new シャッター情報() // 13 { ブラシ = this._濃いブラシ, 矩形サイズ = new Size2F(460f, 690f), 角度rad = (float)0f, 閉じ中心位置 = new Vector2(915f + 230f, 253f + 325f), 開き中心位置 = new Vector2(915f + 230f + 480f, 253f + 325f), 完全開き時刻sec = 0.4, 開閉時間sec = 0.2, }, new シャッター情報() // 14 { ブラシ = this._ふつうのブラシ, 矩形サイズ = new Size2F(340f, 620f), 角度rad = (float)0f, 閉じ中心位置 = new Vector2(614f + 150f, 620f), 開き中心位置 = new Vector2(614f + 150f - 670f, 620f), 完全開き時刻sec = 0.40, 開閉時間sec = 0.2, }, //---------------- #endregion }; //for( int i = 0; i < シャッター枚数; i++ ) // this._シャッター情報[ i ].開to閉割合 = new Variable( gd.Animation.Manager, initialValue: 0.0 ); //this._ロゴ不透明度 = new Variable( gd.Animation.Manager, initialValue: 0.0 ); // // --> クローズかオープンかで初期値が変わるので、ここでは設定しない。 this.現在のフェーズ = フェーズ.未定; }
// 生成と終了 public システムサウンド() { using var _ = new LogBlock(Log.現在のメソッド名); this._種別toサウンドマップ = new Dictionary <システムサウンド種別, (ISampleSource source, PolySound sound)>(); }
/// <summary> /// アイキャッチのオープンアニメーションを開始する。 /// </summary> public override void オープンする(float 速度倍率 = 1.0f) { using var _ = new LogBlock(Log.現在のメソッド名); double 秒(double v) => (v / 速度倍率); var animation = Global.Animation; this.現在のフェーズ = フェーズ.オープン; if (null != this._黒幕アニメーション) { foreach (var b in this._黒幕アニメーション) { b.Dispose(); } } this._黒幕アニメーション = new 黒幕[2] { // 上&左 new 黒幕() { 中心位置X = new Variable(animation.Manager, initialValue: 0.0 - 200.0), // オープン初期位置、以下同 中心位置Y = new Variable(animation.Manager, initialValue: 1080.0 / 2.0), 回転角rad = new Variable(animation.Manager, initialValue: Math.PI * 1.75), 太さ = new Variable(animation.Manager, initialValue: 800.0), 透明度 = new Variable(animation.Manager, initialValue: 1.0), ストーリーボード = new Storyboard(animation.Manager), }, // 下&右 new 黒幕() { 中心位置X = new Variable(animation.Manager, initialValue: 1920.0 + 200.0), 中心位置Y = new Variable(animation.Manager, initialValue: 1080.0 / 2.0), 回転角rad = new Variable(animation.Manager, initialValue: Math.PI * 1.75), 太さ = new Variable(animation.Manager, initialValue: 800.0), 透明度 = new Variable(animation.Manager, initialValue: 1.0), ストーリーボード = new Storyboard(animation.Manager), }, }; this._クローズ割合?.Dispose(); this._クローズ割合 = new Variable(animation.Manager, initialValue: 3.0); // 3.0 からスタート #region " ストーリーボードの構築(1) 上→左の黒幕, クローズ割合(便乗) " //---------------- var 幕 = this._黒幕アニメーション[0]; // シーン3 細くなりつつ画面中央へ移動。 using (var 中心位置Xの遷移 = animation.TrasitionLibrary.AccelerateDecelerate(duration: 秒(_シーン3期間), finalValue: 1920.0 / 2.0, accelerationRatio: 0.9, decelerationRatio: 0.1)) using (var 中心位置Yの遷移 = animation.TrasitionLibrary.Constant(duration: 秒(_シーン3期間))) using (var 回転radの遷移 = animation.TrasitionLibrary.Constant(duration: 秒(_シーン3期間 - 0.08))) using (var 太さの遷移 = animation.TrasitionLibrary.AccelerateDecelerate(duration: 秒(_シーン3期間), finalValue: 100.0, accelerationRatio: 0.9, decelerationRatio: 0.1)) using (var 透明度の遷移1 = animation.TrasitionLibrary.AccelerateDecelerate(duration: 秒(_シーン3期間 * 0.75), finalValue: 0.9, accelerationRatio: 0.9, decelerationRatio: 0.1)) using (var 透明度の遷移2 = animation.TrasitionLibrary.AccelerateDecelerate(duration: 秒(_シーン3期間 * 0.25), finalValue: 0.5, accelerationRatio: 0.9, decelerationRatio: 0.1)) { 幕.ストーリーボード.AddTransition(幕.中心位置X, 中心位置Xの遷移); 幕.ストーリーボード.AddTransition(幕.中心位置Y, 中心位置Yの遷移); 幕.ストーリーボード.AddTransition(幕.回転角rad, 回転radの遷移); 幕.ストーリーボード.AddTransition(幕.太さ, 太さの遷移); 幕.ストーリーボード.AddTransition(幕.透明度, 透明度の遷移1); 幕.ストーリーボード.AddTransition(幕.透明度, 透明度の遷移2); // 便乗 using (var クローズ割合の遷移3to2 = animation.TrasitionLibrary.AccelerateDecelerate(duration: 秒(_シーン3期間), finalValue: 2.0, accelerationRatio: 0.9, decelerationRatio: 0.1)) { 幕.ストーリーボード.AddTransition(this._クローズ割合, クローズ割合の遷移3to2); } } // シーン2 -270°回転。 using (var 中心位置Xの遷移 = animation.TrasitionLibrary.Constant(duration: 秒(_シーン2期間))) using (var 中心位置Yの遷移 = animation.TrasitionLibrary.Constant(duration: 秒(_シーン2期間 - 0.18))) using (var 回転radの遷移 = animation.TrasitionLibrary.AccelerateDecelerate(duration: 秒(_シーン2期間), finalValue: 0.0, accelerationRatio: 0.5, decelerationRatio: 0.5)) using (var 太さの遷移 = animation.TrasitionLibrary.Constant(duration: 秒(_シーン2期間 - 0.18))) using (var 透明度の遷移 = animation.TrasitionLibrary.Constant(duration: 秒(_シーン2期間 - 0.18))) { 幕.ストーリーボード.AddTransition(幕.中心位置X, 中心位置Xの遷移); 幕.ストーリーボード.AddTransition(幕.中心位置Y, 中心位置Yの遷移); 幕.ストーリーボード.AddTransition(幕.回転角rad, 回転radの遷移); 幕.ストーリーボード.AddTransition(幕.太さ, 太さの遷移); 幕.ストーリーボード.AddTransition(幕.透明度, 透明度の遷移); // 便乗 using (var クローズ割合の遷移2to1 = animation.TrasitionLibrary.Linear(duration: 秒(_シーン2期間 - 0.18 + 0.07 /*他より長め*/), finalValue: 1.0)) { 幕.ストーリーボード.AddTransition(this._クローズ割合, クローズ割合の遷移2to1); } } // シーン1 太くなりつつ画面上方へ移動。 using (var 中心位置Xの遷移 = animation.TrasitionLibrary.Constant(duration: 秒(_シーン1期間))) using (var 中心位置Yの遷移 = animation.TrasitionLibrary.AccelerateDecelerate(duration: 秒(_シーン1期間), finalValue: 0.0 - 500.0, accelerationRatio: 0.9, decelerationRatio: 0.1)) using (var 回転radの遷移 = animation.TrasitionLibrary.Constant(duration: 秒(_シーン1期間))) using (var 太さの遷移 = animation.TrasitionLibrary.AccelerateDecelerate(duration: 秒(_シーン1期間), finalValue: 1000.0, accelerationRatio: 0.9, decelerationRatio: 0.1)) using (var 透明度の遷移 = animation.TrasitionLibrary.AccelerateDecelerate(duration: 秒(_シーン1期間 * 0.25), finalValue: 1.0, accelerationRatio: 0.9, decelerationRatio: 0.1)) using (var ロゴの不透明度の遷移 = animation.TrasitionLibrary.Discrete(delay: 秒(_シーン3期間 * (1.0 - 0.24)), finalValue: 0.0, hold: (_シーン3期間) / 速度倍率)) { 幕.ストーリーボード.AddTransition(幕.中心位置X, 中心位置Xの遷移); 幕.ストーリーボード.AddTransition(幕.中心位置Y, 中心位置Yの遷移); 幕.ストーリーボード.AddTransition(幕.回転角rad, 回転radの遷移); 幕.ストーリーボード.AddTransition(幕.太さ, 太さの遷移); 幕.ストーリーボード.AddTransition(幕.透明度, 透明度の遷移); // 便乗 using (var クローズ割合の遷移1to0 = animation.TrasitionLibrary.AccelerateDecelerate(duration: 秒(_シーン1期間 - 0.07 /*他より短め*/), finalValue: 0.0, accelerationRatio: 0.9, decelerationRatio: 0.1)) { 幕.ストーリーボード.AddTransition(this._クローズ割合, クローズ割合の遷移1to0); } } //---------------- #endregion #region " ストーリーボードの構築(2) 下&右の黒幕 " //---------------- 幕 = this._黒幕アニメーション[1]; double ずれ = 0.03; // シーン3 細くなりつつ画面中央へ移動。 using (var 中心位置Xの遷移 = animation.TrasitionLibrary.AccelerateDecelerate(duration: 秒(_シーン3期間), finalValue: 1920.0 / 2.0, accelerationRatio: 0.9, decelerationRatio: 0.1)) using (var 中心位置Yの遷移 = animation.TrasitionLibrary.Constant(duration: 秒(_シーン3期間))) using (var 回転radの遷移 = animation.TrasitionLibrary.Constant(duration: 秒(_シーン3期間 - 0.08))) using (var 太さの遷移 = animation.TrasitionLibrary.AccelerateDecelerate(duration: 秒(_シーン3期間), finalValue: 100.0, accelerationRatio: 0.9, decelerationRatio: 0.1)) using (var 透明度の遷移1 = animation.TrasitionLibrary.AccelerateDecelerate(duration: 秒(_シーン3期間 * 0.75), finalValue: 0.9, accelerationRatio: 0.9, decelerationRatio: 0.1)) using (var 透明度の遷移2 = animation.TrasitionLibrary.AccelerateDecelerate(duration: 秒(_シーン3期間 * 0.25), finalValue: 0.5, accelerationRatio: 0.9, decelerationRatio: 0.1)) { 幕.ストーリーボード.AddTransition(幕.中心位置X, 中心位置Xの遷移); 幕.ストーリーボード.AddTransition(幕.中心位置Y, 中心位置Yの遷移); 幕.ストーリーボード.AddTransition(幕.回転角rad, 回転radの遷移); 幕.ストーリーボード.AddTransition(幕.太さ, 太さの遷移); 幕.ストーリーボード.AddTransition(幕.透明度, 透明度の遷移1); 幕.ストーリーボード.AddTransition(幕.透明度, 透明度の遷移2); } // シーン2 -270°回転。 double 期間 = _シーン2期間 + ずれ; using (var 中心位置Xの遷移 = animation.TrasitionLibrary.Constant(duration: 秒(期間))) using (var 中心位置Yの遷移 = animation.TrasitionLibrary.Constant(duration: 秒(期間 - 0.18))) using (var 回転radの遷移 = animation.TrasitionLibrary.AccelerateDecelerate(duration: 秒(期間), finalValue: 0.0, accelerationRatio: 0.5, decelerationRatio: 0.5)) using (var 太さの遷移 = animation.TrasitionLibrary.Constant(duration: 秒(期間 - 0.18))) using (var 透明度の遷移 = animation.TrasitionLibrary.Constant(duration: 秒(期間 - 0.18))) { 幕.ストーリーボード.AddTransition(幕.中心位置X, 中心位置Xの遷移); 幕.ストーリーボード.AddTransition(幕.中心位置Y, 中心位置Yの遷移); 幕.ストーリーボード.AddTransition(幕.回転角rad, 回転radの遷移); 幕.ストーリーボード.AddTransition(幕.太さ, 太さの遷移); 幕.ストーリーボード.AddTransition(幕.透明度, 透明度の遷移); } // シーン1 太くなりつつ画面下方へ移動。 期間 = _シーン1期間 - ずれ; using (var 中心位置Xの遷移 = animation.TrasitionLibrary.Constant(duration: 秒(期間))) using (var 中心位置Yの遷移 = animation.TrasitionLibrary.AccelerateDecelerate(duration: 秒(期間), finalValue: 1080.0 + 500.0, accelerationRatio: 0.9, decelerationRatio: 0.1)) using (var 回転radの遷移 = animation.TrasitionLibrary.Constant(duration: 秒(期間))) using (var 太さの遷移 = animation.TrasitionLibrary.AccelerateDecelerate(duration: 秒(期間), finalValue: 1000.0, accelerationRatio: 0.9, decelerationRatio: 0.1)) using (var 透明度の遷移 = animation.TrasitionLibrary.AccelerateDecelerate(duration: 秒(期間 * 0.25), finalValue: 1.0, accelerationRatio: 0.9, decelerationRatio: 0.1)) { 幕.ストーリーボード.AddTransition(幕.中心位置X, 中心位置Xの遷移); 幕.ストーリーボード.AddTransition(幕.中心位置Y, 中心位置Yの遷移); 幕.ストーリーボード.AddTransition(幕.回転角rad, 回転radの遷移); 幕.ストーリーボード.AddTransition(幕.太さ, 太さの遷移); 幕.ストーリーボード.AddTransition(幕.透明度, 透明度の遷移); } //---------------- #endregion // 今すぐ開始。 var start = animation.Timer.Time; foreach (var bs in this._黒幕アニメーション) { bs.ストーリーボード.Schedule(start); } this._初めての進行描画 = true; }
public CacheStore() { using var _ = new LogBlock(Log.現在のメソッド名); this._キャッシュデータリスト = new Dictionary <string, キャッシュ情報 <T> >(); }
/// <summary> /// ユーザDBファイルを最新版に更新する。 /// </summary> /// <remarks> /// v012 移行にバージョンアップする場合は、RecordDB.sqlite3 の生成も行う。 /// </remarks> public static void 最新版にバージョンアップする() { using var _ = new LogBlock(Log.現在のメソッド名); var userdbPath = new VariablePath(@"$(AppData)\UserDB.sqlite3"); var userYamls = Directory.EnumerateFiles( path: Folder.フォルダ変数の内容を返す("AppData"), searchPattern: @"User_*.yaml", searchOption: SearchOption.TopDirectoryOnly); if (0 < userYamls.Count()) { #region " (A) User_*.yaml が存在している " //---------------- // それらを最新版にバージョンアップする。 foreach (var userYaml in userYamls) { _Yamlを最新版にバージョンアップする(userYaml); } //---------------- #endregion } else if (File.Exists(userdbPath.数なしパス)) { #region " (B) User_*.yaml が存在せず UserDB.sqlite3 が存在している " //---------------- // Records レコードは、UserDB(v12)からRecordDBに分離された。 // ・UserDB v011 までは、UserDB の Records テーブルに格納されている。RecordDB.Records テーブルのレコードのバージョンは v001~v006(全部同一)。 // ・UserDB v012 以降は、UserDB から独立して、RecordDB.Records テーブルに格納される。Recordsのレコードのバージョンは v007。 var Users = new List <UserConfig>(); int userdb_version; #region " Users テーブルを最新版にして読み込む。" //---------------- using (var userdb = new SQLiteDB(userdbPath.数なしパス)) { userdb_version = (int)userdb.UserVersion; using var idsQuery = new SqliteCommand("SELECT * FROM Users", userdb.Connection); var ids = idsQuery.ExecuteReader(); while (ids.Read()) { Users.Add(new UserConfig(ids)); } } //---------------- #endregion #region " Users テーブルを User_*.yaml に出力する。" //---------------- foreach (var user in Users) { user.保存する(); } //---------------- #endregion #region " RecordDB.sqlite3 がなければ新規作成する。" //---------------- if (!File.Exists(RecordDB.RecordDBPath.数なしパス)) { using var recorddb = new RecordDB(); // ファイルがなければ新規作成される using var cmd = new SqliteCommand($"CREATE TABLE Records { old.RecordDBRecord.v007_RecordDBRecord.ColumnList}", recorddb.Connection); cmd.ExecuteNonQuery(); recorddb.UserVersion = old.RecordDBRecord.v007_RecordDBRecord.VERSION; Log.Info($"RecordDB(v007) を生成しました。"); } //---------------- #endregion if (12 > userdb_version) { #region " UserDB.Rcords テーブルを読み込み、RecordDB.Records テーブルへ出力する。" //---------------- using var userdb = new SQLiteDB(userdbPath.数なしパス); using var recorddb = new RecordDB(); foreach (var user in Users) { using var recordsQuery = new SqliteCommand($"SELECT * FROM Records WHERE Id = @UserId", userdb.Connection); recordsQuery.Parameters.Add(new SqliteParameter("@UserId", user.Id)); var records = recordsQuery.ExecuteReader(); while (records.Read()) { var record = new old.RecordDBRecord.v007_RecordDBRecord(records); // 読み込んで record.InsertTo(recorddb); // 書き込む } } //---------------- #endregion } //---------------- #endregion } else { #region " (C) User_*.yamlも UserDB.sqlite3 も存在しない " //---------------- #region " 新規に User_*.yaml を生成する。" //---------------- var autoPlayer = new UserConfig() { Id = "AutoPlayer", Name = "AutoPlayer", AutoPlay_LeftCymbal = 1, AutoPlay_HiHat = 1, AutoPlay_LeftPedal = 1, AutoPlay_Snare = 1, AutoPlay_Bass = 1, AutoPlay_HighTom = 1, AutoPlay_LowTom = 1, AutoPlay_FloorTom = 1, AutoPlay_RightCymbal = 1, // 他は既定値 }; autoPlayer.保存する(); var guest = new UserConfig() { Id = "Guest", Name = "Guest", // 他は既定値 }; guest.保存する(); //---------------- #endregion #region " 新規に RecordDB.sqlite3 を生成する。" //---------------- var recorddbPath = new VariablePath(@"$(AppData)\RecordDB.sqlite3"); // 念のため if (File.Exists(recorddbPath.数なしパス)) { File.Delete(recorddbPath.数なしパス); } using var recorddb = new SQLiteDB(recorddbPath.数なしパス); // ファイルがなければ新規生成される。 using var cmd = new SqliteCommand(RecordDBRecord.GetCreateTableSQL(), recorddb.Connection); cmd.ExecuteNonQuery(); recorddb.UserVersion = RecordDBRecord.VERSION; Log.Info($"RecordDB を生成しました。"); //---------------- #endregion //---------------- #endregion } }
/// <summary> /// アプリケーションの起動処理を行う。 /// </summary> protected override void OnLoad(EventArgs e) { // ※ このメソッドは GUI スレッドで実行されるので、後回しにできる初期化処理は進行描画タスクに回して、 // なるべく早くこのメソッドを抜けること。 Log.Header("アプリケーション起動"); using var _ = new LogBlock(Log.現在のメソッド名); // フォームを設定する。 this.Text = $"DTXMania2 Release {int.Parse( Application.ProductVersion.Split( '.' ).ElementAt( 0 ) ):000}"; this.ClientSize = new Size(1024, 576); this.Icon = Properties.Resources.DTXMania2; this.ScreenMode = new ScreenMode(this); Global.App = this; Global.Handle = this.Handle; // サウンドデバイスとサウンドタイマを初期化する。これらは入力デバイスで使用されるので先に初期化する。 this.サウンドデバイス = new SoundDevice(CSCore.CoreAudioAPI.AudioClientShareMode.Shared); // マスタ音量(小:0~1:大)... 0.5を超えるとだいたいWASAPI共有モードのリミッターに抑制されるようになる // ※サウンドデバイスの音量プロパティはコンストラクタの実行後でないと set できないので、初期化子にはしないこと。(した場合の挙動は不安定) this.サウンドデバイス.音量 = 0.5f; this.サウンドタイマ = new SoundTimer(this.サウンドデバイス); // 入力デバイスを初期化する。これらは GUI スレッドで行う必要がある。 this.KeyboardHID = new KeyboardHID(this.サウンドタイマ); this.GameControllersHID = new GameControllersHID(this.Handle, this.サウンドタイマ); this.MidiIns = new MidiIns(this.サウンドタイマ); // システム設定ファイルを読み込む。 SystemConfig.最新版にバージョンアップする(); this.システム設定 = SystemConfig.読み込む(); this._システム設定をもとにリソース関連のフォルダ変数を更新する(); // メインループを別スレッドで開始する。 if (!this._進行描画タスクを起動する().WaitOne(5000)) { throw new TimeoutException("進行描画タスクの起動処理がタイムアウトしました。"); } // 初期化完了。(進行描画タスクの起動後に) this._未初期化 = false; // 全画面モードが設定されているならここで全画面に切り替える。 if (this.システム設定.全画面モードである) { this.ScreenMode.ToFullscreenMode(); } base.OnLoad(e); }
public static UserConfig 読み込む(string userId) { using var _ = new LogBlock(Log.現在のメソッド名); var path = new VariablePath(@$ "$(AppData)\User_{userId}.yaml");
public void Dispose() { using var _ = new LogBlock(Log.現在のメソッド名); }
public virtual void Dispose() { using var _ = new LogBlock(Log.現在のメソッド名); this._すべて解放する(); }
// 生成と終了 public MediaFoundationFileVideoSource(VariablePath ファイルパス, double 再生速度 = 1.0) { using var _ = new LogBlock(Log.現在のメソッド名); this.再生速度 = Math.Max(0.01, Math.Min(10.0, 再生速度)); #region " フレームキューを生成。" //---------------- // キューサイズは3フレームとする。 this._FrameQueue = new BlockingQueue <VideoFrame>(3); //---------------- #endregion #region " ファイルから SourceReaderEx を生成する。" //---------------- using (var ビデオ属性 = new MediaAttributes()) { // DXVAに対応しているGPUの場合には、それをデコードに利用するよう指定する。 ビデオ属性.Set(SourceReaderAttributeKeys.D3DManager, Global.MFDXGIDeviceManager); // 追加のビデオプロセッシングを有効にする。 ビデオ属性.Set(SourceReaderAttributeKeys.EnableAdvancedVideoProcessing, true); // 真偽値が bool だったり // 追加のビデオプロセッシングを有効にしたら、こちらは無効に。 ビデオ属性.Set(SinkWriterAttributeKeys.ReadwriteDisableConverters, 0); // int だったり // 属性を使って、SourceReaderEx を生成。 using var sourceReader = new SourceReader(ファイルパス.数なしパス, ビデオ属性); // パスは URI 扱い this._SourceReaderEx = sourceReader.QueryInterface <SourceReaderEx>(); } // 最初のビデオストリームだけを選択。 this._SourceReaderEx.SetStreamSelection(SourceReaderIndex.AllStreams, false); this._SourceReaderEx.SetStreamSelection(SourceReaderIndex.FirstVideoStream, true); //---------------- #endregion #region " ビデオの長さを取得する。" //---------------- this.総演奏時間sec = (long)((this._SourceReaderEx.GetPresentationAttribute(SourceReaderIndex.MediaSource, PresentationDescriptionAttributeKeys.Duration) / this.再生速度) / 10_000_000.0); //---------------- #endregion #region " デコーダを選択し、完全メディアタイプを取得する。" //---------------- // 部分メディアタイプを設定する。 using (var 部分MediaType = new MediaType()) { // フォーマットは ARGB32 で固定とする。(SourceReaderEx を使わない場合、H264 では ARGB32 が選べないので注意。) 部分MediaType.Set(MediaTypeAttributeKeys.MajorType, MediaTypeGuids.Video); 部分MediaType.Set(MediaTypeAttributeKeys.Subtype, VideoFormatGuids.Argb32); // 部分メディアタイプを SourceReaderEx にセットする。SourceReaderEx は、必要なデコーダをロードするだろう。 this._SourceReaderEx.SetCurrentMediaType(SourceReaderIndex.FirstVideoStream, 部分MediaType); } // 完成されたメディアタイプを取得する。 this._MediaType = this._SourceReaderEx.GetCurrentMediaType(SourceReaderIndex.FirstVideoStream); //---------------- #endregion #region " ビデオのフレームサイズを取得する。(動画の途中でのサイズ変更は考慮しない。)" //---------------- long packedFrameSize = this._MediaType.Get(MediaTypeAttributeKeys.FrameSize); this.フレームサイズ = new Size2F((packedFrameSize >> 32) & 0xFFFFFFFF, (packedFrameSize) & 0xFFFFFFFF); //---------------- #endregion this._デコードキャンセル = new CancellationTokenSource(); this._デコード起動完了通知 = new ManualResetEventSlim(false); this._一時停止解除通知 = new ManualResetEventSlim(true); }
/// <summary> /// デコードを一時停止する。 /// </summary> public void Pause() { using var _ = new LogBlock(Log.現在のメソッド名); this._一時停止解除通知.Reset(); }
// 生成と終了 /// <summary> /// 各入力デバイスを初期化する。 /// このコンストラクタは、GUI スレッドから呼び出すこと。 /// </summary> /// <param name="hWindow">ウィンドウハンドル。</param> /// <param name="soundTimer">サウンドタイマ。入力値のタイムスタンプの取得に使用される。</param> /// <param name="最大入力履歴数">入力履歴を使用する場合、その履歴の最大記憶数。</param> public ドラム入力(IntPtr hWindow, SoundTimer soundTimer, int 最大入力履歴数 = 32) { using var _ = new LogBlock(Log.現在のメソッド名); this.ポーリング結果 = new List <ドラム入力イベント>(); this.Keyboard = new KeyboardHID(soundTimer); this.GameControllers = new GameControllersHID(hWindow, soundTimer); this.MidiIns = new MidiIns(soundTimer); this._最大入力履歴数 = 最大入力履歴数; this._入力履歴 = new List <ドラム入力イベント>(this._最大入力履歴数); #region " MIDI入力デバイスの可変IDへの対応を行う。" //---------------- if (0 < this.MidiIns.DeviceName.Count) { var config = Global.App.システム設定; var デバイスリスト = new Dictionary <int, string>(); // <デバイスID, デバイス名> #region " (1) 先に列挙された実際のデバイスに合わせて、デバイスリスト(配列番号がデバイス番号)を作成する。" //---------------- for (int i = 0; i < this.MidiIns.DeviceName.Count; i++) { デバイスリスト.Add(i, this.MidiIns.DeviceName[i]); } //---------------- #endregion #region " (2) キーバインディングのデバイスリストとマージして、新しいデバイスリストを作成する。" //---------------- foreach (var kvp in config.MIDIデバイス番号toデバイス名) { var キーバインディング側のデバイス名 = kvp.Value; if (デバイスリスト.ContainsValue(キーバインディング側のデバイス名)) { // (A) 今回も存在しているデバイスなら、何もしない。 } else { // (B) 今回は存在していないデバイスなら、末尾(=未使用ID)に登録する。 デバイスリスト.Add(デバイスリスト.Count, キーバインディング側のデバイス名); } } //---------------- #endregion #region " (3) キーバインディングのデバイスから新しいデバイスへ、キーのIDを付け直す。" //---------------- var 中間バッファ = new Dictionary <SystemConfig.IdKey, ドラム入力種別>(); foreach (var kvp in config.MIDItoドラム) { var キーのデバイスID = kvp.Key.deviceId; // キーバインディングのデバイス番号 から、デバイスリストのデバイス番号 へ付け替える。 if (config.MIDIデバイス番号toデバイス名.TryGetValue(キーのデバイスID, out string?キーのデバイス名)) { キーのデバイスID = デバイスリスト.First((kvp2) => (kvp2.Value == キーのデバイス名)).Key; // マージしたので、必ず存在する。 } 中間バッファ.Add(new SystemConfig.IdKey(キーのデバイスID, kvp.Key.key), kvp.Value); // デバイスID以外は変更なし。 } config.MIDItoドラム.Clear(); for (int i = 0; i < 中間バッファ.Count; i++) { var kvp = 中間バッファ.ElementAt(i); config.MIDItoドラム.Add(new SystemConfig.IdKey(kvp.Key.deviceId, kvp.Key.key), kvp.Value); } //---------------- #endregion #region " (4) 新しいデバイスリストをキーバインディングに格納して、保存する。" //---------------- config.MIDIデバイス番号toデバイス名.Clear(); for (int i = 0; i < デバイスリスト.Count; i++) { config.MIDIデバイス番号toデバイス名.Add(i, デバイスリスト[i]); } config.保存する(); //---------------- #endregion } else { // 列挙されたMIDI入力デバイスがまったくないなら、キーバインディングは何もいじらない。 } //---------------- #endregion }
public virtual void Dispose() { using var _ = new LogBlock(Log.現在のメソッド名); this._Spinner画像.Dispose(); }
/// <summary> /// デコードを再開する。 /// <see cref="Pause"/>で停止しているときのみ有効。 /// </summary> public void Resume() { using var _ = new LogBlock(Log.現在のメソッド名); this._一時停止解除通知.Set(); // 解除 }
public static void 最新版にバージョンアップする() { using var _ = new LogBlock(Log.現在のメソッド名); var path = new VariablePath(@"$(AppData)\Configuration.yaml"); int version = 0; if (!File.Exists(path.数なしパス)) { return; } #region " YAML階層のルートノード 'Version' を検索し、バージョン値を取得する。" //---------------- { var yamlText = File.ReadAllText(path.数なしパス); var yamlStream = new YamlStream(); yamlStream.Load(new StringReader(yamlText)); var rootMapping = (YamlMappingNode)yamlStream.Documents[0].RootNode; var versionNode = new YamlScalarNode("Version"); if (rootMapping.Children.ContainsKey(versionNode)) { var versionValue = rootMapping.Children[versionNode] as YamlScalarNode; version = int.Parse(versionValue?.Value ?? "1"); // 取得 } } //---------------- #endregion while (version < SystemConfig.VERSION) { switch (version) { case 1: { break; // 存在しない } case 2: { #region " 2 → 3 " //---------------- var v2 = old.SystemConfig.v002_システム設定.読み込む(path); var v3 = new old.SystemConfig.v003_システム設定(v2); v3.保存する(path); version = v3.Version; break; //---------------- #endregion } case 3: { #region " 3 → 4 " //---------------- var v3 = old.SystemConfig.v003_システム設定.読み込む(path); var v4 = new old.SystemConfig.v004_SystemConfig(v3); v4.保存する(); version = v4.Version; break; //---------------- #endregion } case 4: { #region " 4 → 5 " //---------------- var v4 = old.SystemConfig.v004_SystemConfig.読み込む(path); var v5 = new old.SystemConfig.v005_SystemConfig(v4); v5.保存する(); version = v5.Version; break; //---------------- #endregion } case 5: { #region " 5 → 6 " //---------------- var v5 = old.SystemConfig.v005_SystemConfig.読み込む(path); var v6 = new old.SystemConfig.v006_SystemConfig(v5); v6.保存する(); version = v6.Version; break; //---------------- #endregion } case 6: { #region " 6 → 最新版 " //---------------- var v6 = old.SystemConfig.v006_SystemConfig.読み込む(path); var v7 = new SystemConfig(v6); v7.保存する(); version = v7.Version; break; //---------------- #endregion } } } }
// 生成と終了 public ドラムサウンド() { using var _ = new LogBlock(Log.現在のメソッド名); this._チップtoコンテキスト = new Dictionary <(SSTF.チップ種別 chipType, int サブチップID), ドラムサウンドコンテキスト>(); }
public static void 最新版にバージョンアップする() { using var _ = new LogBlock(Log.現在のメソッド名); // Records レコードは、UserDB(v12)からRecordDBに分離された。 // ・UserDB v011 までは、UserDB の Records テーブルに格納されている。RecordDB.Records テーブルのレコードのバージョンは v001~v006(全部同一)。 // ・UserDB v012 以降は、UserDB から独立して、RecordDB.Records テーブルに格納される。Recordsのレコードのバージョンは v007。 if (File.Exists(RecordDBPath.数なしパス)) { #region " (A) RecordDB.sqlite3 が存在している → 最新版にバージョンアップ。" //---------------- using var recorddb = new RecordDB(); int version = (int)recorddb.UserVersion; while (version < RecordDBRecord.VERSION) { // RecordDB は v007 から。 switch (version) { case 0: // 念のため(あったら無限ループになるため) { #region " 0 → 最新版 " //---------------- // テーブルを新規に作る。 foreach (var query in new[] { "PRAGMA foreign_keys = OFF", RecordDBRecord.GetCreateTableSQL(), "PRAGMA foreign_keys = ON" }) { using var cmd = new SqliteCommand(query, recorddb.Connection); cmd.ExecuteNonQuery(); } version = RecordDBRecord.VERSION; recorddb.UserVersion = version; Log.Info($"RecordDB をバージョン {version} を作成しました。"); break; //---------------- #endregion } case 7: { #region " 7 → 8 " //---------------- // テーブルを作り直す。REAL値が既にずれてるので、データ移行はしない。 foreach (var query in new[] { "PRAGMA foreign_keys = OFF", "DROP TABLE Records", $"CREATE TABLE Records {old.RecordDBRecord.v008_RecordDBRecord.ColumnList}", "PRAGMA foreign_keys = ON" }) { using var cmd = new SqliteCommand(query, recorddb.Connection); cmd.ExecuteNonQuery(); } version = old.RecordDBRecord.v008_RecordDBRecord.VERSION; recorddb.UserVersion = version; Log.Info($"RecordDB をバージョン {version} に更新しました。データ移行はしません。"); break; //---------------- #endregion } case 8: { #region " 8 → 最新版 " //---------------- // テーブルを作り直す。今までの成績は消失する。 foreach (var query in new[] { "PRAGMA foreign_keys = OFF", "DROP TABLE Records", RecordDBRecord.GetCreateTableSQL(), "PRAGMA foreign_keys = ON" }) { using var cmd = new SqliteCommand(query, recorddb.Connection); cmd.ExecuteNonQuery(); } version = RecordDBRecord.VERSION; recorddb.UserVersion = version; Log.Info($"RecordDB をバージョン {version} に更新しました。データ移行はしません。"); break; //---------------- #endregion } } } //---------------- #endregion } else { #region " (B) RecordDB.sqlite3 が存在しない → 何もしない " //---------------- // UserDB 側の Update で RecordDB.sqlite3 が生成されるのを待つ。 //---------------- #endregion } }
public void すべて生成する(SoundDevice device) { using var _ = new LogBlock(Log.現在のメソッド名); this._すべて解放する(); lock (this._Sound利用権) { // SSTの既定のサウンドを、subChipId = 0 としてプリセット登録する。 var soundList = new List <(SSTF.チップ種別 type, VariablePath path)>() { (SSTF.チップ種別.LeftCrash, @"$(DrumSounds)\LeftCrash.wav"), (SSTF.チップ種別.Ride, @"$(DrumSounds)\Ride.wav"), (SSTF.チップ種別.Ride_Cup, @"$(DrumSounds)\RideCup.wav"), (SSTF.チップ種別.China, @"$(DrumSounds)\China.wav"), (SSTF.チップ種別.Splash, @"$(DrumSounds)\Splash.wav"), (SSTF.チップ種別.HiHat_Open, @"$(DrumSounds)\HiHatOpen.wav"), (SSTF.チップ種別.HiHat_HalfOpen, @"$(DrumSounds)\HiHatHalfOpen.wav"), (SSTF.チップ種別.HiHat_Close, @"$(DrumSounds)\HiHatClose.wav"), (SSTF.チップ種別.HiHat_Foot, @"$(DrumSounds)\HiHatFoot.wav"), (SSTF.チップ種別.Snare, @"$(DrumSounds)\Snare.wav"), (SSTF.チップ種別.Snare_OpenRim, @"$(DrumSounds)\SnareOpenRim.wav"), (SSTF.チップ種別.Snare_ClosedRim, @"$(DrumSounds)\SnareClosedRim.wav"), (SSTF.チップ種別.Snare_Ghost, @"$(DrumSounds)\SnareGhost.wav"), (SSTF.チップ種別.Bass, @"$(DrumSounds)\Bass.wav"), (SSTF.チップ種別.Tom1, @"$(DrumSounds)\Tom1.wav"), (SSTF.チップ種別.Tom1_Rim, @"$(DrumSounds)\Tom1Rim.wav"), (SSTF.チップ種別.Tom2, @"$(DrumSounds)\Tom2.wav"), (SSTF.チップ種別.Tom2_Rim, @"$(DrumSounds)\Tom2Rim.wav"), (SSTF.チップ種別.Tom3, @"$(DrumSounds)\Tom3.wav"), (SSTF.チップ種別.Tom3_Rim, @"$(DrumSounds)\Tom3Rim.wav"), (SSTF.チップ種別.RightCrash, @"$(DrumSounds)\RightCrash.wav"), (SSTF.チップ種別.LeftCymbal_Mute, @"$(DrumSounds)\LeftCymbalMute.wav"), (SSTF.チップ種別.RightCymbal_Mute, @"$(DrumSounds)\RightCymbalMute.wav"), }; foreach (var sound in soundList) { var path = new VariablePath(Folder.カルチャを考慮した絶対パスを返す(sound.path.数なしパス)); if (!File.Exists(sound.path.数なしパス)) { Log.ERROR($"サウンドファイルが存在しません。[{path.変数付きパス}]"); continue; } // サウンドファイルを読み込んでデコードする。 var sampleSource = SampleSourceFactory.Create(device, path.数なしパス, 1.0); // ドラムサウンドは常に 1.0 if (sampleSource is null) { Log.ERROR($"サウンドの生成に失敗しました。[{path.変数付きパス}]"); continue; } // コンテキストを作成する。 var context = new ドラムサウンドコンテキスト(sampleSource, ドラムサウンド.多重度); // 多重度分のサウンドを生成する。 for (int i = 0; i < context.Sounds.Length; i++) { context.Sounds[i] = new Sound(device, context.SampleSource); } // コンテキストを辞書に追加する。 if (this._チップtoコンテキスト.ContainsKey((sound.type, 0))) { // すでに辞書に存在してるなら、解放してから削除する。 this._チップtoコンテキスト[(sound.type, 0)].Dispose();
public static void 最新版にバージョンアップする() { using var _ = new LogBlock(Log.現在のメソッド名); using var db = new ScoreDB(); int version = (int)db.UserVersion; // v007 から、SognDB.sqlite3 が ScoreDB.sqlire3 に改名された。 var songdbPath = new VariablePath(@"$(AppData)\SongDB.sqlite3"); using var songdb = File.Exists(songdbPath.数なしパス) ? new SQLiteDB(songdbPath.数なしパス) : null; // なければ null int songdb_version = (int)(songdb?.UserVersion ?? -1); // なければ負数 while (version < ScoreDBRecord.VERSION) { switch (version) { case 0: { #region " 0 → 最新版 " //---------------- // ScoreDB.sqlite3 に最新版のテーブルを新規に作成する。 foreach (var query in new[] { "PRAGMA foreign_keys = OFF", ScoreDBRecord.GetCreateTableSQL(), "PRAGMA foreign_keys = ON", }) { using var cmd = new SqliteCommand(query, db.Connection); cmd.ExecuteNonQuery(); } if (songdb is null) // SongDB.sqlite3 がある? { version = ScoreDBRecord.VERSION; db.UserVersion = version; break; } // SongDB.sqlite3 が存在するので、データ移行する。 switch (songdb_version) { case 0: case 1: case 2: case 3: case 4: case 5: // 何もしない。1~5 については、REAL 型の数値がすでにずれているため、データ移行しない。 break; case 6: #region " 6 → 最新版 " //---------------- { // ScoreDB 側に、最新バージョンのテーブルを作成する。 foreach (var query in new[] { "PRAGMA foreign_keys = OFF", ScoreDBRecord.GetCreateTableSQL(), }) { using var cmd = new SqliteCommand(query, db.Connection); cmd.ExecuteNonQuery(); } // v006 のレコードを読み込み、v007 テーブルに出力する。DBが違うので注意。 using (var cmdv007Begin = new SqliteCommand("BEGIN", db.Connection)) cmdv007Begin.ExecuteNonQuery(); using var cmdv006query = new SqliteCommand("SELECT * FROM Songs", songdb.Connection); var v006result = cmdv006query.ExecuteReader(); while (v006result.Read()) { var v006rc = new old.SongDBRecord.v006_SongDBRecord(v006result); var v007rc = new ScoreDBRecord() { ScorePath = v006rc.Path, // 以下変更なし。 Title = v006rc.Title, LastWriteTime = v006rc.LastWriteTime, Level = v006rc.Level, MinBPM = v006rc.MinBPM, MaxBPM = v006rc.MaxBPM, TotalNotes_LeftCymbal = v006rc.TotalNotes_LeftCymbal, TotalNotes_HiHat = v006rc.TotalNotes_HiHat, TotalNotes_LeftPedal = v006rc.TotalNotes_LeftPedal, TotalNotes_Snare = v006rc.TotalNotes_Snare, TotalNotes_Bass = v006rc.TotalNotes_Bass, TotalNotes_HighTom = v006rc.TotalNotes_HighTom, TotalNotes_LowTom = v006rc.TotalNotes_LowTom, TotalNotes_FloorTom = v006rc.TotalNotes_FloorTom, TotalNotes_RightCymbal = v006rc.TotalNotes_RightCymbal, PreImage = v006rc.PreImage, Artist = v006rc.Artist, PreSound = v006rc.PreSound, BGMAdjust = v006rc.BGMAdjust, }; v007rc.ReplaceTo(db); } using (var cmdv007End = new SqliteCommand("END", db.Connection)) cmdv007End.ExecuteNonQuery(); using (var cmdKeysOn = new SqliteCommand("PRAGMA foreign_keys = ON", db.Connection)) cmdKeysOn.ExecuteNonQuery(); version = ScoreDBRecord.VERSION; db.UserVersion = version; Log.Info($"ScoreDB をバージョン {version} に更新しました。"); } //---------------- #endregion break; } break; //---------------- #endregion } case 1: case 2: case 3: case 4: case 5: { #region " 1~5 → 6(BreakingChange)" //---------------- // テーブルを作り直す。REAL値が既にずれてるので、データ移行はしない。 foreach (var query in new[] { "PRAGMA foreign_keys = OFF", "DROP TABLE Songs", $"CREATE TABLE Songs {old.SongDBRecord.v006_SongDBRecord.ColumnList}", "PRAGMA foreign_keys = ON", }) { using var cmd = new SqliteCommand(query, db.Connection); cmd.ExecuteNonQuery(); } version = old.SongDBRecord.v006_SongDBRecord.VERSION; db.UserVersion = version; Log.Info($"SongDB をバージョン {version} に更新しました。"); break; //---------------- #endregion } } } }