2023-07-17に更新

2D RPG 制作ツールを作ろうぜ(^~^)?

読了目安:88分

📅 2023-06-25 はじめに

ramen-tabero-futsu2.png
「 2D RPG 制作ツールを作ろうぜ?」

kifuwarabe-futsu.png
「 なんで お父んが そんなこと しなければならないのか?
働けだぜ」

ohkina-hiyoko-futsu2.png
「 思いついたら やるんでしょ。
そこらへんの 凡人と同じよ」

ramen-tabero-futsu2.png
「 👇 それより 作業用BGM かけようぜ? 気分を盛り上げないとな」

💿 Rockman ロックマン 11 [OST] Full Album

ohkina-hiyoko-futsu2.png
「 それは作業用BGMではなく、違法アップロード動画なのでは?」

202306__photo__24--Rockman11.jpg

ramen-tabero-futsu2.png
「 👆 サイドPCを Ubuntu に差し替えたんで Steam を久しぶりに動かしてみたら、動いたんで驚いたぜ」

kifuwarabe-futsu.png
「 えっ? RPG制作ツールを作るのに 作業用BGMが ロックマン11 でいいのかだぜ??」

MAUI を調べろだぜ

ramen-tabero-futsu2.png
「 👇 企画と アーキテクチャーを 長々と 説明しても あれなんで……
MAUI を調べようぜ?」

📖 .NET MAUI (環境構築からHallo, World!~Windowsアプリ編~)

kifuwarabe-futsu.png
「 プラン全部 飛ばしたな。もう作業か」

ohkina-hiyoko-futsu2.png
「 あんたのお父ん ノー・プランよ。
ウォーター・フォール・モデルの下流工程の 実装 という狭い範囲でしか仕事できないんだから。
あと 事務と経理」

kifuwarabe-futsu.png
「 それって 羨ましがられるらしいぜ。 いーな、コードばかりやってて、と」

ramen-tabero-futsu2.png
「 なんか 知らん間に Windows の 開発者モード というのが オフ にされているらしく、
これを オン にして ビルド」

202306_maui_24-1920--hello-world.png

ramen-tabero-futsu2.png
「 👆 これが MAUI を実行した画面か~。 なんなんだろうな これ?」

kifuwarabe-futsu.png
「 何も分からん。 ロードマップもない」

ramen-tabero-futsu2.png
「 Click me を押したら ボタンを押した回数が出てくるぜ」

ohkina-hiyoko-futsu2.png
「 こっから ツールを組み立てていくの、気が遠くなるわね~」

ramen-tabero-futsu2.png
「 タイトル画面なんか作らずに メニューがさっさと出てきたら 良くね?」

kifuwarabe-futsu.png
「 お父んがよく選ぶのは 家系二郎ラーメン、 塩ラーメン、 レモンサワー」

ramen-tabero-futsu2.png
「 今日は ネギ・ラーメン にしようぜ?」

ohkina-hiyoko-futsu2.png
「 メニューって、そのメニューなの?」

202306_maui_24-1939--negiramen.png

👆 2D-RPG-Negiramen

kifuwarabe-futsu.png
「 👆 リポジトリ―は 作っておいたぜ」

ohkina-hiyoko-futsu2.png
「 ネギ・ラーメンは リポジトリ―の名前じゃなくない?」

202306_maui_24-1941--title image.png

使用フォント: 📖 たぬき油性マジック

ramen-tabero-futsu2.png
「 👆 こんな感じの ファースト・ビュー でどうだぜ?」

kifuwarabe-futsu.png
「 縦スクロール・バーは 付けておいてくれだぜ」

ohkina-hiyoko-futsu2.png
「 いいのか よくないのか 分かんないから さっさと作って 動かしてみましょう!」

ramen-tabero-futsu2.png
「 👇 アラートが出てきたぜ。ここ読めだって」

📖 Build your first app

ramen-tabero-futsu2.png
「 わたしが やりたいことを 説明してくれるのではなく、
マイクロソフトが 説明したいことを 説明してくるので つらいぜ」

ohkina-hiyoko-futsu2.png
「 画面にボタンを置きなさいよ」

ramen-tabero-futsu2.png
「 👇 どこを読めばいいのか 分からない、ドキュメントとの戦いだぜ」

📖 Customize the app shell

202306_maui_24-2022--title-menu.png

ramen-tabero-futsu2.png
「 👆 様々な概念が分からなかったが作った、とりあえず これで」

ohkina-hiyoko-futsu2.png
「 じゃあ とりあえず マップを作る画面に進みなさいよ」

ramen-tabero-futsu2.png
「 ??」

ramen-tabero-futsu2.png
「 画面遷移って どうやって やるんだ……??」

kifuwarabe-futsu.png
「 👇 これでも読めだぜ」

📖 .NET MAUI (いろんな画面遷移)

ramen-tabero-futsu2.png
「 うーん?」

202306_maui_24-2042--app-shell-o2o0.png

ramen-tabero-futsu2.png
「 👆 AppShell.xml というのを 何か設定しないといけない?」

202306_maui_24-2051--create-map-page-view.png

ramen-tabero-futsu2.png
「 👆 とりあえず 画面遷移は できたぜ」

kifuwarabe-futsu.png
「 どうやって HOMEに戻るんだぜ?」

ohkina-hiyoko-futsu2.png
「 パンくずリスト が有ったらいいんじゃない?」

ramen-tabero-futsu2.png
「 👇 パンくずリストのような機能は用意されているのではなく、自力で作らないといけないらしいぜ」

📖 .NET Maui Tabs with Breadcrumb Navigation

202306_maui_24-2114--breadcrumb-list.png

ramen-tabero-futsu2.png
「 👆 作り方 分からんので とりあえず ボタンとラベルで」

ohkina-hiyoko-futsu2.png
「 じゃあ次は 戦闘を作る画面に進みなさいよ」

202306_maui_24-2123--create-battle-view-page.png

ramen-tabero-futsu2.png
「 👆 同様だぜ」

kifuwarabe-futsu.png
「 じゃあ 残りも 以下同様で やってくれだぜ」

ramen-tabero-futsu2.png
「 つら」

202306_maui_24-2302--xaml-o2o0.png

ramen-tabero-futsu2.png
「 👆 .xaml ファイル増えてきて 邪魔なんだけど、置き場フォルダーは どう作るのが ベストプラクティス なんだぜ?」

kifuwarabe-futsu.png
「 👇 調べろだぜ」

📖 MAUI(WinUI3)でMVVMを超単純にやる

ramen-tabero-futsu2.png
「 👇 Qiita の素人記事読むぐらいだったら 公式読むぜ」

📖 Microsoft > Upgrade your app with MVVM concepts

202306_maui_24-2318--views-o2o0.png

ramen-tabero-futsu2.png
「 👆 こうすりゃいいのか」

kifuwarabe-futsu.png
「 MainPage.xaml も 📂 Views フォルダーに入れろだぜ」

エクスプローラーが要るんじゃないか?

kifuwarabe-futsu.png
「 お父ん。
プレイヤー・キャラクター編集画面に入る前に、
どのプレイヤー・キャラクターを編集するのか 選択する画面が 要るんじゃないか?」

ramen-tabero-futsu2.png
「 あっ、そうか!
ほとんどの データ編集ページで リストが要るぜ!」

ohkina-hiyoko-futsu2.png
「 リストでいいの?
テーブルじゃなくて いいの?」

ramen-tabero-futsu2.png
「 じゃあ エクスプローラー だ。
MAUI にそんなコントロール あるかな?」

kifuwarabe-futsu.png
「 👇 お父ん。コレクション・ビューと、テーブル・ビューを調べてみてくれだぜ」

📖 .NET MAUI (UIコントロール)

ramen-tabero-futsu2.png
「 だから 素人が書いた記事なんか 読まねーっつーの」

📖 Microsoft > CollectionView

ramen-tabero-futsu2.png
「 👆 なんか知らんが ListView より かっこいいのが CollectionView らしいぜ」

ohkina-hiyoko-futsu2.png
「 考えるの止めるの わらう」

📖 Microsoft > TableView

ramen-tabero-futsu2.png
「 👆 コレクション・ビューを使うべきか、テーブル・ビューを使うべきの判断方法が分からん」

kifuwarabe-futsu.png
「 ページネーション(Pagination;ページ割り)の機能は付いているのかだぜ?」

ramen-tabero-futsu2.png
「 調べたいことが 出てこないのが マイクロソフトの ドキュメントなんだぜ」

ohkina-hiyoko-futsu2.png
「 マイクロソフトの Bing の人工知能に利いても MAUI がなんだか分かってないし」

ramen-tabero-futsu2.png
「 じゃあ、ページネーションも 自力実装することにしよう」

kifuwarabe-futsu.png
「 そうであるなら、クリテリア(Criteria;判断基準)が必要だぜ。
どのような規則に従って整列しているか、
表示されているデータは 何件目~何件目までのデータか、
表示されているのは 何ページ目か、
昇順か逆順か、
フィルタリングされているか」

ramen-tabero-futsu2.png
「 無いものを 自力実装するのが プログラマーだぜ。
必要だったら 片っ端から 実装していけばいいんだぜ」

ohkina-hiyoko-futsu2.png
「 迷ったら テーブル・ビューと コレクション・ビューの両方実装すりゃいいのよ」

ramen-tabero-futsu2.png
「 ぬぎぎぎぎ!」

202306_maui_25-0041--home.png

202306_maui_25-0042--map-explorer.png

202306_maui_25-0043--create-map.png

ramen-tabero-futsu2.png
「 👆 こういう風に 途中に 検索ページを1枚 挟めばいいんだろ?」

kifuwarabe-futsu.png
「 デザインを分かってないエンジニアが作りがちな検索画面だぜ」

ramen-tabero-futsu2.png
「 ぬぎぎぎぎ!」

ohkina-hiyoko-futsu2.png
「 動いているところを見ないと よく分かんないから、
明日は 動くところを作ってみましょう」

ramen-tabero-futsu2.png
「 ライセンスが オープンソースの 2D RPGの素材 なんも 持ってねー ぬぎぎぎぎぎ!」

kifuwarabe-futsu.png
「 あっ! ゲームとして利用するならフリーだが、素材集を ツールに同梱して そのまま再配布することを許可している素材が無いのか!

ohkina-hiyoko-futsu2.png
「 当然よねえ」

Unity プロジェクトを作ろうぜ?

ramen-tabero-futsu2.png
「 まあ 無いものは無いで 変数x とでも置いておいて 解けるところから先に解くのが 数学だぜ」

kifuwarabe-futsu.png
「 それを問題の先送りと言う」

202306_maui_25-0418--unity-project-o2o0.png

ramen-tabero-futsu2.png
「 👆 テンプレートは 2D を選び、プロジェクト名は Negiramen Practice にして
プロジェクトを作成しようぜ?」

ohkina-hiyoko-futsu2.png
「 ネギラーメンでは、それが何だか 分かんなくない?
検索のサジェスチョンも汚すし」

kifuwarabe-futsu.png
「 聞き慣れてくれば イカしてくるぜ」

202306_maui_25-0427--2D-o2o0.png

ramen-tabero-futsu2.png
「 なんか最初から いろんなものが入っている……、ちょっと見てみるか……」

202306_maui_25-0432--2D-Editor.png

ramen-tabero-futsu2.png
「 👆 多分 エディターなんだと思うんだが、この1つ1つを調べて行くか」

kifuwarabe-futsu.png
「 👇 お父んが作らなくても、すでに いいものがあるのでは?」

📖 TileMapEditorはいいぞ!

ramen-tabero-futsu2.png
「 オープンソースだけで やりたいぜ」

202306_maui_25-0449--OverwriteProjectToUnity-o2o0.png

ramen-tabero-futsu2.png
「 👆 ちょっと ボタンを追加しよう」

ramen-tabero-futsu2.png
「 👇 それで……、テキスト・ボックスって どうやって作るんだ? 調べるか……」

📖 Microsoft > 入力

ramen-tabero-futsu2.png
「 Entry というタグがあるのか」

202306_maui_25-0500--OverwriteProjectToUnityPage.png

ramen-tabero-futsu2.png
「 👆 それで こういうページ作るだろ。
ディレクトリー・パスを入れて ボタンを押すと……」

202306_maui_25-0540--Folders-o2o0.png

ramen-tabero-futsu2.png
「 👆 Unity プロジェクトへ フォルダーや ファイルを送り付けるという算段だぜ」

ohkina-hiyoko-futsu2.png
「 Unity の外部で ゲーム・オブジェクトを作れるの?
Unity の外部で プレファブは作れるの?」

ramen-tabero-futsu2.png
「 Unity に そういう API があるか? ということだな。
調べてみようぜ?」

kifuwarabe-futsu.png
「 そんなことを しようという人が少ないのか 記事が見当たらないな」

設定の保存を作れだぜ

ohkina-hiyoko-futsu2.png
「 毎回 📂 Assets フォルダーへのパスを入れるのが 面倒なんだけど?」

ramen-tabero-futsu2.png
「 ユーザー・データとして保存したいよな。
最近流行りのファイル形式は何だぜ?」

kifuwarabe-futsu.png
「 👇 TOML 1.0 はどうだぜ?」

📖 公式 > toml

ramen-tabero-futsu2.png
「 👇 Tomlyn を NuGET で入れてみるか」

📖 Tomlyn

MVVM

ramen-tabero-futsu2.png
「 あれっ?」

202306_maui_25-1459--text-box-default-o2o0.png

ramen-tabero-futsu2.png
「 このテキスト・ボックスの初期値って どうやって 入れるんだぜ?」

kifuwarabe-futsu.png
「 👇 お父んが さっき読んでいた記事に書いてあるだろ。 MVVM のところを読み直せだぜ」

📖 Microsoft > Upgrade your app with MVVM concepts

202306_maui_25-1508--MVVM.png

ramen-tabero-futsu2.png
「 👆 とりあえず 📂 Views 、 📂 ViewModels 、 📂 Models の3フォルダーを揃えよう」

202306_maui_25-1518--model-o2o0.png

ramen-tabero-futsu2.png
「 👆 なんだか分からないが Model は ただのオブジェクトだろ。イミュータブルに作ったった」

ramen-tabero-futsu2.png
「 👇 ViewModel は なんか複雑だな 説明を よく読も」

📖 Create the About viewmodel

202306_maui_25-1613--viewModel-o2o0.png

ramen-tabero-futsu2.png
「 👆 ViewModel は Model と 変更通知プロパティ を紐づければいいんだろ?」

kifuwarabe-futsu.png
「 ビュー・モデルのデフォルト・コンストラクターは public 修飾にする必要があるぜ」

202306_maui_25-1627--View-o2o0.png

ramen-tabero-futsu2.png
「 👆 View は ここまで書き足したぜ」

ohkina-hiyoko-futsu2.png
「 ボタンは コマンドで書き直す必要があるんじゃない?」

202306_maui_25-1646--Command-o2o0.png

ramen-tabero-futsu2.png
「 👆 ViewModel に コマンドを取り付け。
ビュー・モデルは MVVMアーキテクチャーの中で 雑用とか、アシスタント・ディレクターの役割を担当するんだな」

202306_maui_25-1657--View-o2o0.png

ramen-tabero-futsu2.png
「 👆 View も更新。
イベントハンドラを消し、コマンドを追加」

ユーザー・データをどこに保存するか?

kifuwarabe-futsu.png
「 👇 いろいろなフォルダーに ユーザー・データは保存できるが、どこにするんだぜ?」

📖 特殊ディレクトリのパスを取得する

ramen-tabero-futsu2.png
「 ユースケースによる。
2D RPG を開発するような アクターは、
いつも 同じ部屋で 同じ1台のパソコンを使って 1人で開発している、という状況設定を押し付けることにしようぜ?」

ohkina-hiyoko-futsu2.png
「 それ以上のものを要求するユーザーは ネギラーメン ではなく
もっと 金出して 高級な開発ツールを使えばいいのよ」

kifuwarabe-futsu.png
「 そりゃそうだぜ」

ramen-tabero-futsu2.png
「 じゃあ LocalApplicationData だな」

ramen-tabero-futsu2.png
「 あれっ?」

  C:
  └── 📂 Users
    └── 📂 {ユーザー名}
      └── 📂 AppData
        └── 📂 Local
👉         └── 📂 Muzudho
            └── 📂 2D RPG Negiramen

ramen-tabero-futsu2.png
「 👆 他人のローカルPCに わたしの名前のフォルダーが ポコポコできるの 嫌なんだが……」

ohkina-hiyoko-futsu2.png
「 屋号、 サークル名、 ホームページ名など いろいろあるけど」

ramen-tabero-futsu2.png
「 仕事で金取ってないし 屋号もおかしいしな」

kifuwarabe-futsu.png
「 サークル名が 一番良いのでは?」

  C:
  └── 📂 Users
    └── 📂 {ユーザー名}
      └── 📂 AppData
        └── 📂 Local
👉         └── 📂 Doujin Circle Grayscale
            └── 📂 2D RPG Negiramen

ramen-tabero-futsu2.png
「 👆 Grayscale だけだと 何だか分からないので、
かなり長いけど Doujin Circle Grayscale にしよう」

ohkina-hiyoko-futsu2.png
「 ひねりのない 名前にするからよ」

ramen-tabero-futsu2.png
「 👇 あれっ! MAUI には AppData 下の LocalFolder にアクセスする正式な方法が無い!」

📖 設定情報とデータの保存 (3/5)

kifuwarabe-futsu.png
「 マルチプラットフォームだから Windows のフォルダーにアクセスするのが ナンセンスなんじゃないか?」

ramen-tabero-futsu2.png
「 あっ、そうか~!」

ohkina-hiyoko-futsu2.png
「 MAUI は他の手段を用意しているのかしら? 調べなさい」

ramen-tabero-futsu2.png
「 👇 知らんことばっかりなら 調べればいいだけだぜ」

📖 File system helpers

                string mainDir = FileSystem.Current.AppDataDirectory;
                // Example: `C:\Users\むずでょ\AppData\Local\Packages\1802ca7b-559d-489e-8a13-f02ac4d27fcc_9zz4h110yvjzm\LocalState`

ramen-tabero-futsu2.png
「 👆 UUID を含んだ文字の羅列になるらしい」

kifuwarabe-futsu.png
「 それは ネギラーメンを何回実行しても同じディレクトリー名になるのかだぜ?」

string mainDir = FileSystem.Current.AppDataDirectory;
// Example 1回目: `C:\Users\むずでょ\AppData\Local\Packages\1802ca7b-559d-489e-8a13-f02ac4d27fcc_9zz4h110yvjzm\LocalState`
// Example 2回目: `C:\Users\むずでょ\AppData\Local\Packages\1802ca7b-559d-489e-8a13-f02ac4d27fcc_9zz4h110yvjzm\LocalState`

ramen-tabero-futsu2.png
「 👆 同じだぜ」

ohkina-hiyoko-futsu2.png
「 今どき 合理的な解決方法 してんのねー」

202306_maui_25-1954--save-config-file.png

ramen-tabero-futsu2.png
「 👆 設定ファイルの保存の仕方は 覚え直した……。
やり方ぜんぜん変わってた……」

kifuwarabe-futsu.png
「 次は そのファイルを読み取る方法を 覚え直せだぜ」

TOML形式ファイルを読み取ろうぜ?

ramen-tabero-futsu2.png
「 👇 もう1回 Tomlyn の調べ直し」

📖 Tomlyn > Documentation

202306_maui_25-2024--load-toml.png

ramen-tabero-futsu2.png
「 👆 これで Toml も読み込めるぜ」

202306_maui_25-2026--memory-o2o0.png

ramen-tabero-futsu2.png
「 👆 前に入力した内容も フォームが覚えてくれるようになったから 楽になったぜ」

ohkina-hiyoko-futsu2.png
「 先送りにしていた 変数x は どうすんの?」

ramen-tabero-futsu2.png
「 絵を描くツールも Windows Paint と、 GIMP しかないしな……
少し ネットで調べる」

ramen-tabero-futsu2.png
「 👇 特許が取られてるかどうか 分からん」

📖 WOLF Editor 公式 > 【マップチップ素材はどういう風に作ればいいの?】

ramen-tabero-futsu2.png
「 👇 ゲームの特許なんか調べてられん。 ページ開いて出てくるの、こんなんだぜ?」

📖 特開2007-244536

kifuwarabe-futsu.png
「 じゃあ 訴えられて死ねだぜ」

ramen-tabero-futsu2.png

真理は 避けられず
真実は 踏み込んだ者にしか見えず
真相は 勝手なものである」

ohkina-hiyoko-futsu2.png
「 ゲーム業界に首を突っ込みたかったら 死にましょう。
生きて帰るな。代わりに 徹底的に世界を破壊しなさい」

ramen-tabero-futsu2.png
「 WOLF EDITOR のドキュメントが整理されているので、それ読む」

ramen-tabero-futsu2.png
「 ピクセル・アートを描くのに 良い無料のツールって どんなのだぜ?」

kifuwarabe-futsu.png
「 有料のフォトショップしか 選択肢 無いのに……」

ramen-tabero-futsu2.png
「 👇 こんなサイトがあった。後で調べよう」

📖 www.pixilart.com

ramen-tabero-futsu2.png
「 マップ・タイルは 16 x 16 ピクセル・サイズが単位のようだぜ」

ohkina-hiyoko-futsu2.png
「 それを どれぐらいのサイズのキャンバスの中に 敷き詰めんの?」

kifuwarabe-futsu.png
「 マルチ・プラットフォームなのだから、答えはないぜ」

ramen-tabero-futsu2.png
「 Nintendo Switch は、 1080 x 720 だそうだぜ。
これを 参考に試算しよう」

📖 Nintendo > Switch > Technical Specs

kifuwarabe-futsu.png
「 タイル数で言うと、 67.5 x 45 枚だな。スクリーン上に 3037.5 枚のタイルがあるぜ」

ramen-tabero-futsu2.png
「 一層で?」

ohkina-hiyoko-futsu2.png
「 オブジェクト数が 多い気がするけど、 RPG なら大丈夫なのかなあ?」

マップ・エディターの画面デザイン

202306_maui_26-0312--map-editor.png

ramen-tabero-futsu2.png
「 👆 マップ・エディターって こんなレイアウトで いいのかだぜ?」

kifuwarabe-futsu.png
「 違うんじゃないか?」

202306_maui_26-0318--map-editor-2.png

kifuwarabe-futsu.png
「 👆 描画ツールが いくつかあるんだぜ」

ramen-tabero-futsu2.png
「 描画ツールって どんなけ あるんだぜ?」

202306_maui_26-0318--map-editor-3.png

kifuwarabe-futsu.png
「 👆 分からん。これぐらいから 始めればどうか?」

ohkina-hiyoko-futsu2.png
「 境界線ペンの仕様が はっきり分かんないかしら?」

ramen-tabero-futsu2.png
「 オート・タイルか。 説明が よく分かんないんだよな」

202306_maui_26-0358--auto-tile-4.png

kifuwarabe-futsu.png
「 👆 お父んに 分かりやすいように まとめたぜ。
空間充填問題も セル・オートマトンも 好きだろ」

ramen-tabero-futsu2.png
「 うわっ 二ム計算みたいなの 出てきた」

ohkina-hiyoko-futsu2.png
「 あー、はいはい、分かりました」

202306_maui_26-0504--auto-tile-5.png

ohkina-hiyoko-futsu2.png
「 👆 こんな役割なのよ」

ramen-tabero-futsu2.png
「 接続時だけでなく、切断時の再計算も大変そうだ」

202306_maui_26-0529--auto-tile-7.png

ramen-tabero-futsu2.png
「 👆 でも オート・タイルの仕様は 理解したな」

📅 2023-06-26 素材が何もない

ramen-tabero-futsu2.png
「 👇 pixelart.com の使い方を練習する」

📖 www.pixilart.com

202306_maui_26-1940--adventure-field.png

ramen-tabero-futsu2.png
「 👆 あれっ? 64 x 64 pixel のつもりで描いたのに でかいな……」

ohkina-hiyoko-futsu2.png
「 1216 x 1216 pixel あるわよ?」

ramen-tabero-futsu2.png
「 じゃあ 使えないなあ」

202306_maui_26-1944--adventure-field.png

ramen-tabero-futsu2.png
「 👆 Save じゃなく、 Download すればいいのか」

ramen-tabero-futsu2.png
「 じゃあ これを最初のマップタイルとして MAUI の画面に表示してみようぜ?」

初期設定

202306_maui_26-2031--startup-config.png

ramen-tabero-futsu2.png
「 👆 初期設定として これだけ入力してくれないと つらい」

ohkina-hiyoko-futsu2.png
「 ほとんどの人は ディレクトリー・パスも入力できず 投げるんじゃないの?」

kifuwarabe-futsu.png
「 ファースト・ビューで ユーザーが入力できるのは、
自分の名前と メール・アドレスぐらいだぜ」

ramen-tabero-futsu2.png
「 じゃあ ファースト・ビューのボタンを クリックするところまでは
設定無しで 行けるようにしよう。
そこで何か ボタンを押したら 初期設定画面へ」

202306_maui_27-0412--startup-configuration-page.png

ramen-tabero-futsu2.png
「 👆 パンくずリストで どう表現したらいいんだぜ?」

ohkina-hiyoko-futsu2.png
「 サイト・マップのツリー構造を崩したくないから、
モーダル・ダイアログ・ボックス的に ページ遷移せず出てくる サブ・ウィンドウみたいにできないの?」

ramen-tabero-futsu2.png
「 やり方分からん。調査だな」

📅 2023-06-27 モーダル・ダイアログボックスを作れるかだぜ?

ramen-tabero-futsu2.png
「 👇 マイクロソフトのドキュメントって、スクリーンショットを使った説明が 圧倒的に足りないよな」

📖 .NET MAUI ウィンドウ

kifuwarabe-futsu.png
「 👇 じゃあ まず 普通のサブ・ウィンドウを出して、閉じるところまで やってくれだぜ」

📖 Opening a new window in MAUI

    /// <summary>
    /// [ウィンドウ表示テスト]ボタン押下時
    /// </summary>
    /// <param name="sender">このイベントを呼び出したコントロール</param>
    /// <param name="e">この発生イベントの制御変数</param>
    private void TestShowWindowButton_Clicked(object sender, EventArgs e)
    {
        var secondWindow = new Window
        {
            Page = new StartupConfigurationPage
            {
                // ...
            },
            Width = 1200,
            Height = 400,
        };

        Application.Current.OpenWindow(secondWindow);
    }

ramen-tabero-futsu2.png
「 👆 これで ウィンドウは ポップアップされるけど、もっと簡単な書き方無いかなあ?」

    /// <summary>
    /// [ウィンドウ表示テスト]ボタン押下時
    /// </summary>
    /// <param name="sender">このイベントを呼び出したコントロール</param>
    /// <param name="e">この発生イベントの制御変数</param>
    async void TestShowWindowButton_Clicked(object sender, EventArgs e)
    {
        await Navigation.PushAsync(new StartupConfigurationPage());
    }

ramen-tabero-futsu2.png
「 👆 こう書くと 同じウィンドウで ページだけ スライドする演出付きで 切り替わるぜ」

ohkina-hiyoko-futsu2.png
「 戻るボタンも 付いてるし、こっちの方が かっこいいわよ」

ramen-tabero-futsu2.png
「 ウィンドウを閉じるボタンは、どう書くんだぜ?」

kifuwarabe-futsu.png
「 👇 Navigation.PopAsync(); じゃないのかだぜ?」

📖 .NET MAUI (いろんな画面遷移)

ramen-tabero-futsu2.png
「 ContentPage クラスを継承したコード・ビハインド には Navigation 書けるけど、
ViewModel のプロパティーである Command にはどこから Navigation 持ってくるんだぜ?」

kifuwarabe-futsu.png
「 👇 Backwards Navigation があるんじゃないか?
await Shell.Current.GoToAsync(".."); を試せだぜ」

📖 Backwards navigation

ramen-tabero-futsu2.png
「 おー、戻れたぜ」

ohkina-hiyoko-futsu2.png
「 戻ったはいいけど、次の画面に進みたかったんだけど」

ramen-tabero-futsu2.png
「 グローバル変数で 進みたい画面を覚えさせとくかー」

ramen-tabero-futsu2.png
「 構成設定の要求を ページ間に挟むのは でけた」

タイル・マップを Unity の Assets フォルダー下へコピーしろだぜ

202306_maui_27-2147--tile-map.png

ramen-tabero-futsu2.png
「 👆 この画像を Unity の Assets フォルダーへコピーしたいけど……」

ramen-tabero-futsu2.png
「 この画像のファイル・パスって どうやって指すんだぜ?
カレント・ディレクトリー どこよ?」

ohkina-hiyoko-futsu2.png
「 指せるからこその Resources ディレクトリーなんじゃないの?
Special Directory に無いの?」

📖 Windowsの既定のイメージ ディレクトリ

ramen-tabero-futsu2.png
「 Application.ImageDirectory を調べてみるかだぜ」

ramen-tabero-futsu2.png
「 XAML の中にしか書けないらしい」

📅 2023-06-28 初期素材をどこに置くんだぜ?

ramen-tabero-futsu2.png
「 👇 ワーキング・ディレクトリーの設定方法を調べた方がいいのでは?」

📖 How to change the Current Working Directory of Maui Blazor App

kifuwarabe-futsu.png
「 まず AppDomain.CurrentDomain.BaseDirectory が何を出力するか 調べてみてくれだぜ」

202306_maui_27-2252--base-directory-o2o0.png

ramen-tabero-futsu2.png
「 👆 bin ディレクトリーの方を向いていて、 Resources フォルダーなんか見にこないぜ」

ohkina-hiyoko-futsu2.png
「 じゃあ マップ・タイル画像は ネギラーメンの実行ファイルとは別に 配ったらいいんじゃないの?」

ramen-tabero-futsu2.png
「 Git Hub にでも置いとけば 拾っていくかな?」

202306_maui_27-2304--working-directory-o2o0.png

ramen-tabero-futsu2.png
「 👆 とりあえず ここに置いておくぜ」

202306_maui_28-0814--configuration.png

ramen-tabero-futsu2.png
「 👆 さらに調整」

ohkina-hiyoko-futsu2.png
「 ツクラーは こんな設定 できないから RMUは 全部入りのパッケージで売るのよ」

kifuwarabe-futsu.png
「 ソフトを自分で選んで インストールして 設定するような
パソコンの正しい使い方をしたくないのが、 ツクラーだぜ

ramen-tabero-futsu2.png
「 ネギラーメンは ツクラーの思想とは おさらばだぜ。
ネギラーメンは ただの食材を ユニティーにコピーする トッピング・ソフト だぜ」

コピーしろだぜ

202306_maui_28-1929--Duplicator.png

ramen-tabero-futsu2.png
「 👆 さらに調整。
ハードコーディングしてしまったが、ただの Copy だぜ」

タイルを選ばせろだぜ

ohkina-hiyoko-futsu2.png
「 タイル・パレットを作ってみましょう。
この画像を MAUI に表示して、草原、砂漠、岩、海を クリックできるようにしましょう」

ramen-tabero-futsu2.png
「 👇 このポップアップというやつは 画面上に 画像が浮くやつじゃないか?
試してみようぜ?」

📖 マイクロソフト > ポップアップ
📖 Microsoft > Popup

202306_maui_28-2053--CommunityToolkit-Maui-o2o0.png

ramen-tabero-futsu2.png
「 👆 なんの説明も無いが、このパッケージが要るのでは?」

ramen-tabero-futsu2.png
「 👇 全然 ビルド通らないなあ。調べるか」

📖 .NET MAUI Community Toolkit Popup PopupHandler is incompatible

202306_maui_28-2108--MauiProgram-o2o0.png

ramen-tabero-futsu2.png
「 👆 こんなん書く必要があるのかだぜ、分からんって」

202306_maui_28-2117--Popup.png

ramen-tabero-futsu2.png
「 👆 思ってるのと違って モーダル・ダイアログボックスみたいなのが 出てきたぜ」

ohkina-hiyoko-futsu2.png
「 画面の真ん中じゃなくて、ボタンをクリックしたマウスの近くに 出せないの?」

ramen-tabero-futsu2.png
「 分からん」

kifuwarabe-futsu.png
「 ポップアップではなく、サブ・ウィンドウにしろだぜ」

ramen-tabero-futsu2.png
「 くそっ」

202306_maui_28-2132--SubWindow.png

ramen-tabero-futsu2.png
「 👆 サブ・ウィンドウを出すのは 前にやったんで」

ohkina-hiyoko-futsu2.png
「 そこに タイルの画像を表示しましょう!」

202306_maui_28-2144--Image-o2o0.png

ramen-tabero-futsu2.png
「 👆 こんな風に 絶対パス書いたら 画像出てくるかな?」

kifuwarabe-futsu.png
「 さっさと 試せだぜ」

202306_maui_28-2147--Image.png

ramen-tabero-futsu2.png
「 👆 出たけど 画像サイズが さっぱり……」

kifuwarabe-futsu.png
「 そのサイズを ぴったり 合わせてくれだぜ」

202306_maui_28-2230--WidthHeight-o2o0.png

ramen-tabero-futsu2.png
「 👆 ウィトス(WIdth;横幅)と ハイト(Height;縦幅)を 指定すればいいのか」

ohkina-hiyoko-futsu2.png
「 なんか変なデバッグ用のツールバーと被ってるから 真ん中らへんに表示しましょう!」

202306_maui_28-2236--Grid.png

ramen-tabero-futsu2.png
「 👆 グリッドを使って真ん中へ」

kifuwarabe-futsu.png
「 画像にマウスカーソルを合わせたら、枠が出るようにしてみてくれだぜ」

ramen-tabero-futsu2.png
「 オン・マウス・オーバー みたいなイベントハンドラが無いか 探してみるかだぜ」

📖 Mouse hover detection in .NET MAUI

ohkina-hiyoko-futsu2.png
「 MAUI は、スマホのようなタッチ・デバイスで使われることを想定していて、
デスクトップのようなマウス操作は 想定していないそうよ」

ramen-tabero-futsu2.png
「 クソじゃないか」

kifuwarabe-futsu.png
「 マウス・カーソルの位置を取得できないか、調べてみてくれだぜ」

📅 2023-06-29 マウス・キャプチャーしてくれだぜ

ramen-tabero-futsu2.png
「 👇 マウス・キャプチャー自体 どうやるんだぜ?」

📖 How to capture global touch events in MAUI app

ohkina-hiyoko-futsu2.png
「 MAUI には マウス・キャプチャーは無いのよ」

ramen-tabero-futsu2.png
「 じゃあ Windows プログラミングかだぜ?」

kifuwarabe-futsu.png
「 👇 その前に ジェスチャーを調べてくれだぜ」

📖 Recognize a tap gesture

202306_maui_29-0642--Gesture.png

ramen-tabero-futsu2.png
「 👆 なんか いっぱいある。
この PointerGestureRecognizer とか それっぽくないかだぜ?
👇 調べるか」

📖 Recognize a pointer gesture

コマンドに引数をよこせだぜ

ramen-tabero-futsu2.png
「 あれっ? どうやって コマンドに引数を渡すんだぜ?」

kifuwarabe-futsu.png
「 👇 調べろだぜ」

📖 Microsoft > Commanding

ramen-tabero-futsu2.png
「 👆 WPF みたいなものんか?」

202306_maui_29-0709--MouseCapture-o2o0.png

ramen-tabero-futsu2.png
「 👆 反応はしてるから、後は 引数を取りたいぜ。
もう少し調べるか」

📖 Microsoft > PointerGestureRecognizer.PointerMovedCommandParameter Property

ramen-tabero-futsu2.png
「 👆 パラメーターも コマンドなんだ」

ramen-tabero-futsu2.png
「 いや、取れない」

ramen-tabero-futsu2.png
「 👇 何か無いか」

📖 .NET MAUI Custom control with command and parameters

202306_maui_29-0738--Command-o2o0.png

ramen-tabero-futsu2.png
「 👆 このコマンドから、何か引数にアクセスできないか?」

ohkina-hiyoko-futsu2.png
「 コマンドは 実行することしか できないわねえ」

ramen-tabero-futsu2.png
「 じゃあ コマンドを使っちゃいけないんだ」

202306_maui_29-0759--Code-Behind-o2o0.png

ramen-tabero-futsu2.png
「 👆 コード・ビハインド を使うと 画像上の座標を取ることはできるが……」

kifuwarabe-futsu.png
「 コード・ビハインドと ビュー・モデルと 何の関係があるんだぜ?」

ramen-tabero-futsu2.png
「 👇 WPFの依存関係プロパティみたいなものがないか 調べてみるぜ」

📖 How to use DependencyProperty in Maui?

📖 Microsoft > Bindable properties

📖 How can I bind a property to a view model in MAUI?

202306_maui_29-0821--BindContext-o2o0.png

ramen-tabero-futsu2.png
「 👆 コード・ビハインドから、ビューにバインドされてる ビュー・モデル 取れた……。
WPF の DataContext と同じ考えだ」

ohkina-hiyoko-futsu2.png
「 簡単ねえ」

202306_maui_29-0831--Method-o2o0.png

202306_maui_29-0826--CoordinateOnTheImage-o2o0.png

ramen-tabero-futsu2.png
「 画像上の座標 取れた……」

kifuwarabe-futsu.png
「 それを いったん ウィンドウ上の座標に変換して、
32 x 32 pixels サイズのタイルを囲む枠を 置いてくれだぜ」

ramen-tabero-futsu2.png
「 👇 調べるか……」

📖 How to get MAUI UI element absolute coordinates

202306_maui_29-1936--CoordinateOnTheWindow-o2o0.png

ramen-tabero-futsu2.png
「 👆 画像の座標は取れるのか。だったら それ使えばいいんじゃ……」

ramen-tabero-futsu2.png
「 じゃあ 次は 枠を描こうぜ。
MAUI の画面上に 矩形を描く命令 あるかだぜ?」

kifuwarabe-futsu.png
「 👇 これを読めだぜ」

📖 Draw a rectangle

ramen-tabero-futsu2.png
「 👆 canvas って どっから出てきたんだぜ?
👇 調べるか」

📖 .net MAUI: how to draw on canvas

202306_maui_29-2135--CursorOnTile.png

ramen-tabero-futsu2.png
「 👆 赤い枠は出せたけど、位置調整が大変だ」

ramen-tabero-futsu2.png
「 マウスカーソルは 1ピクセルずつ動いて欲しいけど、
赤い枠は 32ピクセルずつ 動いて欲しい」

kifuwarabe-futsu.png
「 じゃあ グリッド が要るんだ」

ramen-tabero-futsu2.png
「 センタリングされていて、座標計算が めんどくさい」

ohkina-hiyoko-futsu2.png
「 左上が基準で いいんじゃない?」

ramen-tabero-futsu2.png
「 👇 なんで Alignment じゃなくて Options って名前なんだ?」

📖 .NET MAUI コントロールの配置と配置

202306_maui_29-2155--Cursor.png

ramen-tabero-futsu2.png
「 👆 例えば こんな感じ?」

ohkina-hiyoko-futsu2.png
「 それっぽく なったわねえ」

入力透過

ramen-tabero-futsu2.png
「 タイル・マップを クリックしたいのに、
その上のカーソルが 邪魔なんだが」

kifuwarabe-futsu.png
「 👇 入力透過を使えだぜ」

📖 VisualElement.InputTransparent プロパティ

ramen-tabero-futsu2.png
「 よし、それでイケてるぜ」

マウス・クリックした座標から、カーソルの位置を算出しろだぜ

ohkina-hiyoko-futsu2.png
「 隣の砂漠をクリックしたら、タイル・カーソルがそこを指すようにしなさいよ」

202306_maui_29-2332--CursorCoord.png

ramen-tabero-futsu2.png
「 👆 グリッドが 32ピクセル固定で ハードコーディングして いけたぜ」

ohkina-hiyoko-futsu2.png
「 じゃあ そのタイルを マップ・エディター で使いたいけど、
マップ・エディターが まだ無いのよねえ」

kifuwarabe-futsu.png
「 じゃあ 明日から マップ・エディター だな」

📅 2023-06-30 ツール・アイコンが欲しいぜ

ramen-tabero-futsu2.png
「 👇 ペンのアイコンの絵を描くぜ」

📖 www.pixilart.com

kifuwarabe-futsu.png
「 無くていいのに……」

ramen-tabero-futsu2.png
「 気分が出る!」

202306_maui_30-1905--tool-box.png

ramen-tabero-futsu2.png
「 👆 pixilart.com のツールに グリッドのサイズ指定が無いから 枠線 引いてしまう」

ohkina-hiyoko-futsu2.png
「 どの画像の 何個目のタイルを表示するのか 名前で指定できるようにしたくない?」

tool_box.pen

ohkina-hiyoko-futsu2.png
「 👆 カテゴリー名と、そのメンバーを ドット・シンタックスで指定して」

crop_image("tool_box.png", 0, 0, 32, 32)

ohkina-hiyoko-futsu2.png
「 👆 画像のロードまで やってくれるような」

kifuwarabe-futsu.png
「 じゃあ CSV形式で記録したらどうだぜ?」

code           , file        ,  x,  y, width, height, comment
tool_box.pen   , tool_box.png,  0,  0,    32,     32, ペン
tool_box.eraser, tool_box.png, 32,  0,    32,     32, 消しゴム
tool_box.bucket, tool_box.png,  0, 32,    32,     32, 塗りつぶし
code                  , file               ,  x,  y, width, height, comment
adventure_field.grass , adventure_field.png,  0,  0,    32,     32, 草原
adventure_field.desert, adventure_field.png, 32,  0,    32,     32, 砂漠
adventure_field.rock  , adventure_field.png,  0, 32,    32,     32, 岩
adventure_field.sea   , adventure_field.png, 32, 32,    32,     32, 海

kifuwarabe-futsu.png
「 👆 例は こうだぜ」

  例: C:\Users\むずでょ\Documents\GitHub\2D-RPG-Negiramen
  └── 📂 Workspace
    ├── 📂 Assets
    │  ├── 📂 CSV
👉   │  │  └── 📄 tiles.csv
    │  └── 📂 Image
    │    └── 📄 tool_box.png
    └── 📂 For Unity Assets
      ├── 📂 CSV
👉     │  └── 📄 tiles.csv
      └── 📂 Images
        └── 📂 Tile Set
          └── 📄 adventure_field.png

ramen-tabero-futsu2.png
「 👆 ツール・ボックスのアイコン・ファイルの置き場所は
ネギラーメンの 📄 Workspace/Assets/CSV/tiles.csv でいいかな?」

kifuwarabe-futsu.png
「 他のフォルダーも けっこう いじるんだな」

ohkina-hiyoko-futsu2.png
「 その tiles.csv を作るエディターが欲しいわよね」

ramen-tabero-futsu2.png
「 タイル・パレット編集画面、みたいなやつかだぜ」

kifuwarabe-futsu.png
「 どんな画面レイアウトだぜ?」

タイル・パレット編集画面を作ろうぜ?

202306_maui_30-2021--tile-palette-editor-2.png

ramen-tabero-futsu2.png
「 👆 コメントを入力することを考えると、横に広く使いたいしな」

202306_maui_30-2200--tile-palette-editor.png

ramen-tabero-futsu2.png
「 👆 こんな雰囲気で どうだぜ?」

kifuwarabe-futsu.png
「 配色が ROCKMAN だな」

ohkina-hiyoko-futsu2.png
「 グリッドを引きなさいよ」

ramen-tabero-futsu2.png
「 グリッド引くなら ループ文を使うのが鉄板だと思うが
MAUIで ループ文があるのか 分からん……」

📖 MAUI equivalent to CSS background-repeat: repeat;

ramen-tabero-futsu2.png
「 👆 Webみたいに 背景画像をタイルにしてリピートできるなら グリッドが作れるかと思ったが
それも無いみたいだし」

ramen-tabero-futsu2.png
「 動的に XAML の要素を追加・削除する方法も分からん」

ohkina-hiyoko-futsu2.png
「 透明なキャンバスに 罫線引いて タイル・マップの上に 覆い被せりゃいいんじゃないの?」

ramen-tabero-futsu2.png
「 それで行くか」

パンくずリストと、タイトル

202306_maui_30-2305--tile-palette-editor-o2o0.png

ramen-tabero-futsu2.png
「 👆 パンくずリスト付けたら もっさり したんだが、
ヘッダーと パンくずリスト を1つに まとめる方法 無い?」

ohkina-hiyoko-futsu2.png
「 タイトルバーに見えるところ、自動で付くのよねえ」

kifuwarabe-futsu.png
「 👇 ナビゲーションじゃないか? 調べてみろだぜ」

📖 Microsoft > NavigationPage

ramen-tabero-futsu2.png
「 👇 ソースの中には いじれそうなものは無かった。もっと探そう」

📖 How to customize the navigation title view of MAUI ContentPage

202306_maui_30-2323--title-view-o2o0.png

ramen-tabero-futsu2.png
「 👆 初期状態は こう書いてるのと 多分 おんなじらしい。
これをベースに改造してみようぜ?」

202306_maui_30-2331--title-view-o2o0.png

ramen-tabero-futsu2.png
「 👆 パンくずリストと ページ・タイトルを 同じ行に まとめたぜ」

ohkina-hiyoko-futsu2.png
「 スマホの画面には タイトル・バーが無いから、ページの中に作るのね」

kifuwarabe-futsu.png
「 PCは クローム(※)が付くんだな」

※クローム … ウィンドウの枠。タイトルバーなどを含む

グリッドの線、引こうぜ?

202307_maui_01-0007--grid.png

ramen-tabero-futsu2.png
「 👆 ひとまず ハードコーディングで 半透明の赤い色で グリッドを置いてみたが どうだろうか?」

ohkina-hiyoko-futsu2.png
「 まずは いいんじゃないの?」

kifuwarabe-futsu.png
「 元画像の 横幅、縦幅も 表示してくれだぜ」

202307_maui_01-0035--tile-palette-editor.png

ramen-tabero-futsu2.png
「 👆 さらに細かく調整」

ohkina-hiyoko-futsu2.png
「 タイル画像が大きかったとき、スクロールできんの?」

ramen-tabero-futsu2.png
「 この画面は ハリボテ なんで……。
動きを付ける段階になったら 調べるぜ」

kifuwarabe-futsu.png
「 タイルIdを表示してくれだぜ」

画像サイズを調べようぜ?

ramen-tabero-futsu2.png
「 その前に 1枚の画像にタイルが 100枚ぐらいなのか、 1000枚ぐらいなのか、 10000枚ぐらいなのか、
規模を知りたいぜ」

📖 WOLF RPG エディター(ウディタ)でゲームを作る3 ~マップチップとオートタイルを増やす~

ramen-tabero-futsu2.png
「 👆 素材集の中を覗いてみないと 分からんな……」

📖 画像・音声素材データ集

ramen-tabero-futsu2.png
「 👆 あれっ、思ってたより小さい……
横 332 × 縦 772 かだぜ?」

kifuwarabe-futsu.png
「 なんだ その 中途半端な数は?」

ramen-tabero-futsu2.png
「 あれっ? 枠が付いてある…… これは使用例のスクリーンショットか。
横 256 x 縦 608 のものもあるぜ」

kifuwarabe-futsu.png
「 なんだ その 中途半端な数は?」

ramen-tabero-futsu2.png
「 横 256 x 縦 544 のものもあるぜ」

ohkina-hiyoko-futsu2.png
「 決まってないのでは?」

ramen-tabero-futsu2.png
「 横はニゴロ(256)のようだぜ」

kifuwarabe-futsu.png
「 じゃあ 縦長 になるんだ。ポートレートだ」

ramen-tabero-futsu2.png
「 1つのタイル・サイズは 32x32 を最小として、
64x64 とか 96x64 とか 自由気ままに配置されているぜ!」

ohkina-hiyoko-futsu2.png
「 608 は 32 で割り切れるわねえ。19よ」

kifuwarabe-futsu.png
「 素数だ」

ramen-tabero-futsu2.png
「 どういうシステムなんだ」

ramen-tabero-futsu2.png
「 じゃあ分かった、 256 × 608 を画面に表示してみようぜ?
👇 画像を作るぜ」

📖 www.pixilart.com

map-tile-format-8x19.png

202307_maui_01-0118--scroll-view.png

ramen-tabero-futsu2.png
「 👆 ハリボテだが スクロールバーは 付けれるぜ」

kifuwarabe-futsu.png
「 お父んの思想と ウルフエディターの素材作成勢とで 相性が悪いの わらう」

ohkina-hiyoko-futsu2.png
「 意匠は 相容れない方が 著作権を差別化できて有利なのよ」

ramen-tabero-futsu2.png
「 明日は このハリボテに 動きを付けていこうぜ?」

📅 2023-07-01 ページに引数を渡すにはどうやるんだぜ?

[http://www.example.com/index.html?name=banana](http://www.example.com/index.html?name=banana)
                                 ^^^^^^^^^^^^

ramen-tabero-futsu2.png
「 👆 Web系なら URLの後ろに クエリー文字列を付けることができるが、
MAUI で画面遷移時に何かデータを渡すには どうやるんだぜ?」

kifuwarabe-futsu.png
「 👇 調べろだぜ」

📖 MAUI:画面遷移時のデータの受け渡し

202307_maui_01-1936--parameters-o2o0.png

ramen-tabero-futsu2.png
「 👆 parameters で オブジェクトを渡せそうだな。
渡した先での 受け取り方も 調べるかだぜ」

202307_maui_01-2017--property-o2o0.png

ramen-tabero-futsu2.png
「 👆 ビューモデルに フィールドがあるとして……」

202307_maui_01-2020--parameters-o2o0.png

ramen-tabero-futsu2.png
「 👆 フィールド名を使って、オブジェクトを渡せるみたいだな」

PNG 形式画像ファイルのサイズを取得してくれだぜ

kifuwarabe-futsu.png
「 PNG 形式画像ファイルのサイズを取得してくれだぜ」

ramen-tabero-futsu2.png
「 あれっ? やり方が分からん……
👇 調べるか……」

📖 [C#]PNGの幅,高さのみをファイルから高速に取得する方法について
📖 【C#】PNG画像サイズの取得方法

ramen-tabero-futsu2.png
「 👆 渡せるものと、渡せないものとがある。
調べるか……」

202307_maui_02-2156--query-parameter-on-class-o2o0.png

ramen-tabero-futsu2.png
「 👆 QueryParameter アトリビュート(属性)をクラスに1個1個すべて書くのが確実らしい」

kifuwarabe-futsu.png
「 MVVM 実装してるだけで 1日 終わりそうだ」

ohkina-hiyoko-futsu2.png
「 画面は 手戻り無しで 1発で作らないと 時間が 厳しそうねえ」

kifuwarabe-futsu.png
「 要らん画面 作ったら 1日は無駄になるな」

202307_maui_02-2215--on-property-changed-o2o0.png

ramen-tabero-futsu2.png
「 👆 変更通知プロパティの手順の順序を 間違えると 画面に出てこないから 正確にやるぜ」

202307_maui_02-2155--query-parameter-o2o0.png

ramen-tabero-futsu2.png
「 👆 画像サイズに 動きを付けたぜ」

kifuwarabe-futsu.png
「 全部に動きを付けてくれだぜ」

ramen-tabero-futsu2.png
「 つら」

GraphicsView はどうやってリフレッシュするんだぜ?

202307_maui_02-2236--graphics-view.png

ramen-tabero-futsu2.png
「 👆 グリッドは GraphicsView を使ってプログラム的に描画しているが、
これは どうやって再描画するんだぜ?」

kifuwarabe-futsu.png
「 👇 調べろだぜ」

📖 Microsoft > GraphicsView

ramen-tabero-futsu2.png
「 👆 graphicsView.Invalidate(); を呼び出せばいいのか。やってみるかだぜ」

ramen-tabero-futsu2.png
「 ビューモデルから どうやって graphicsView にアクセスするんだぜ?」

📖 Binding from view to GraphicsView property in .NET MAUI
📖 How to databind imageview with drawable in viewmodel?
📖 .NET MAUI: Dynamic behaviour of graphic elements when using MVVM

ramen-tabero-futsu2.png
「 👆 同じ悩みを持ってるやつらが 見つからんなあ」

ohkina-hiyoko-futsu2.png
「 Drawable に変更通知プロパティを 仕掛けられないの?」

202307_maui_01-2259--tile-set-grid.png

ramen-tabero-futsu2.png
「 👆 ビュー・モデルから IDrawable 実装インスタンスの Draw をコールする方法も分からん」

kifuwarabe-futsu.png
「 ビュー・モデルから ビューに アクセスできないのかだぜ?」

ramen-tabero-futsu2.png
「 調べてみるか」

ramen-tabero-futsu2.png
「 ビュー・モデルは 変更通知プロパティ をビューに仕込んで連携できるだけだな」

ohkina-hiyoko-futsu2.png
「 ビュー・モデルの方から ビューのキャンバスを変更できないと グリッド・サイズを更新できなくない?」

202307_maui_01-2311--contentPage-resource-o2o0.png

ramen-tabero-futsu2.png
「 👆 リソースに 引数を渡す方法って ある?」

kifuwarabe-futsu.png
「 👇 調べろだぜ」

📖 Resource dictionaries

ohkina-hiyoko-futsu2.png
「 リソースは スタティックなんじゃない?」

ramen-tabero-futsu2.png
「 じゃあ GraphicsView を使って グリッドを描画するのが そもそも間違ってる?」

kifuwarabe-futsu.png
「 そうなのでは」

ramen-tabero-futsu2.png
「 伸縮自在なラインを 固定長で1000本ぐらい 画面に持たせた方がいいのかだぜ?」

202307_maui_01-2324--graphics-view-o2o0.png

ramen-tabero-futsu2.png
「 👆 GraphicsView の横幅、縦幅は バインディングできるから、
ビューモデルから 縦幅、横幅の変更通知を送ったら IDrawing 実装インスタンスの Draw メソッドを呼び出してくれないかな?」

kifuwarabe-futsu.png
「 試せだぜ」

202307_maui_01-2347--dirtyRect-o2o0.png

ramen-tabero-futsu2.png
「 👆 なんらかのタイミングで Draw メソッドの dirtyRect 引数に矩形が入っているから、
あとは ビュー・モデルから 任意のタイミングで Draw をコールできれば うまくいきそうだが」

202307_maui_01-2356--onPageOpen.png

ramen-tabero-futsu2.png
「 👆 画面を出した初回は 画像サイズが分かってるんで グリッドも合わせられるぜ」

ohkina-hiyoko-futsu2.png
「 グリッド・サイズは途中からも 変えたいのよ」

202307_maui_02-0042--hack-o2o0.png

ramen-tabero-futsu2.png
「 👆 グリッドの横幅が変更されたタイミングで
グリッドの画像サイズの横幅を 1px 伸ばしたったら、再描画が呼び出されるけど」

ohkina-hiyoko-futsu2.png
「 イケてないわねえ」

kifuwarabe-futsu.png
「 再描画が呼び出されるトリガーのうち、もっとも無難なものって何だぜ? タグの変更トリガーとか無いのかだぜ?」

ohkina-hiyoko-futsu2.png
「 タグだって 変えられたくないわよ」

トリック・コード

202307_maui_02-0122--trick-code.png

ramen-tabero-futsu2.png
「 👆 今回のプログラミングで最初のトリック・コードだぜ。
画像の横幅が偶数のときは 横幅を1伸ばし、
画像の横幅が奇数のときは 横幅を1縮めて 無限に振動させるぜ」

kifuwarabe-futsu.png
「 わらう」

ohkina-hiyoko-futsu2.png
「 グリッドのサイズを変えるたびに
グリッドの右端が 1px飛び出たり 元に戻ったりするんだけど」

ramen-tabero-futsu2.png
「 トリックがバレないように修正する」

202307_maui_02-0147--cancel-code-o2o0.png

ramen-tabero-futsu2.png
「 👆 トリック・コードのせいで 割り食って おかしくなっている箇所は
キャンセル・コードを書いて おかしなものを 隠すぜ」

kifuwarabe-futsu.png
「 不毛な戦い わらう」

ohkina-hiyoko-futsu2.png
「 トリック・コードなんか書くからよ」

202307_maui_02-0150--grid-size.png

ramen-tabero-futsu2.png
「 グリッド・サイズを変えれるようになった。今日はここまでだぜ」

kifuwarabe-futsu.png
「 MVVMの実装 時間かかるんだな、作る画面は 最低限の数で済むように 全体を考えないとな」

📅 2023-07-02 タイル・パレット編集ページを作っていこうぜ?

202307_maui_02-1431--grid-point-o2o0.png

ramen-tabero-futsu2.png
「 👆 グリッドの全体も ずらせるようにしたので、 位相 にも対応だぜ」

ohkina-hiyoko-futsu2.png
「 スクロールとかねえ」

kifuwarabe-futsu.png
「 線形代数の変換の王様、アフィン変換にも対応しろだぜ」

ramen-tabero-futsu2.png
「 開発時間足りない。次へ」

202307_maui_02-2156--grid.png

ramen-tabero-futsu2.png
「 👆 カーソルが グリッドに 吸着するようになったぜ」

kifuwarabe-futsu.png
「 これだけで 日曜日が終わろうとしている。時間がかかるな」

ohkina-hiyoko-futsu2.png
「 下側の タイル 0 0 0 0 のとこに カーソルの位置を表示しなさいよ」

202307_maui_02-2225--cursor-position-o2o0.png

ramen-tabero-futsu2.png
「 👆 はい」

kifuwarabe-futsu.png
「 お父ん。グリッド1ます の たて に 50000 と入れたら強制終了したぜ?」

202307_maui_02-2229--size-over-o2o0.png

ramen-tabero-futsu2.png
「 👆 確かに。あのグリッド、ただの縦線じゃなくて 画像だからな」

ohkina-hiyoko-futsu2.png
「 テキスト・ボックスに バリデーション(妥当性検証)を入れなさいよ」

バリデーションを入れようぜ?

ramen-tabero-futsu2.png
「 👇 何もかも やり方が分からん。覚え直しだ。 調べるか……」

📖 Microsoft > Validation

ramen-tabero-futsu2.png
「 👆 説明の通りコードを書いても IValidity のところで コンパイル・エラーになるの 分けわからんな」

ramen-tabero-futsu2.png
「 この記事が クソ だということを伝えるボタンが無いぜ」

ohkina-hiyoko-futsu2.png
「 👇 文字数のチェックはできるみたいよ?」

📖 TextValidationBehavior

ramen-tabero-futsu2.png
「 もっと まともな方法を調べるぜ」

📖 RequiredStringValidationBehavior
📖 NumericValidationBehavior

ramen-tabero-futsu2.png
「 👆 NumericValidationBehavior を調べてみるか」

202307_maui_02-2335--validation-o2o0.png

ramen-tabero-futsu2.png
「 👆 下ごしらえは XAML だけで終わるの 簡単だな」

ramen-tabero-futsu2.png
「 1辺の上限が 16384 じゃなくて、
面積の上限が 16384 か?
ルート2 したら 128 で小さすぎないか?」

kifuwarabe-futsu.png
「 10000 x 10000 にしても動いているぜ?」

ramen-tabero-futsu2.png
「 なんか限界 攻めたくないな。
グラフィック・カードの性能に依存するのかも知らん。
とりあえず 上限は 8192 にしよう!」

ohkina-hiyoko-futsu2.png
「 2 の 13乗に 意義を感じないわね」

202307_maui_02-2338--validation-o2o0.png

ramen-tabero-futsu2.png
「 👆 じゃあ 無難な 上限 2048 にして、
文句があるやつがでてきたときに 拡張用の設定ファイルを用意しようぜ?」 

kifuwarabe-futsu.png
「 設定できるんなら それでいいよな」

202307_maui_02-2328--validation-o2o0.png

ramen-tabero-futsu2.png
「 👆 あれっ? 色が変わるだけで 入力できてしまう?」

ohkina-hiyoko-futsu2.png
「 入力を拒絶しなきゃ、意味なくない?」

kifuwarabe-futsu.png
「 ビュー・モデルの方で 2048 以上を入力したら 2048 として扱うような処理がいるかもしれないな」

kifuwarabe-futsu.png
「 あっ、 0 を入れても フリーズしたぜ」

ramen-tabero-futsu2.png
「 明日は バリデーション を みっちり やるぜ」

📅 2023-07-03 バリデーションを入れようぜ?

  C:
  └── 📂 Users
    └── 📂 むずでょ
      └── 📂 AppData
        └── 📂 Local
          └── 📂 Packages
            └── 📂 1802ca7b-559d-489e-8a13-f02ac4d27fcc_9zz4h110yvjzm
              └── 📂 LocalState
                ├── 📄 configuration.toml
👉               └── 📄 settings.toml

ramen-tabero-futsu2.png
「 👆 settings.toml ファイルを作って、そこに グリッドのタイル・サイズの一辺の上限は 2048 だという設定を
書いておこうぜ?」

kifuwarabe-futsu.png
「 両端に太さが 2px のグリッドの線があるから、1px ずつ食み出るとして 2048 から 2px 引いて 2046 にすべきだと思うが」

ohkina-hiyoko-futsu2.png
「 上限値の理由に 意義がないのよ」

ramen-tabero-futsu2.png
「 じゃあ 2046 !」

[tile]

# 一辺が 2048 ピクセルのキャンバスを想定し、両端に太さが 2px のグリッドの線があって 1px ずつ食み出るから 2px 引いて 2046
max_width = 2_046
max_height = 2_046

ramen-tabero-futsu2.png
「 👆 1辺が 2048 ピクセルのタイルを作りたいやつは 設定を変えろ」

202307_maui_03-2111--validation-o2o0.png

ramen-tabero-futsu2.png
「 👆 バリデーションというのは ビューの色を変えるぐらいしか機能がないので、
ビューモデルでは 単に リミット・チェックを入れた」

ohkina-hiyoko-futsu2.png
「 入力された値は(弾かず)とりあえず受け取る、という思想なのね」

kifuwarabe-futsu.png
「 入力を受け取らないフラグ 無いのかなあ? もっと探してみろだぜ」

ramen-tabero-futsu2.png
「 疲れたんで とりあえず 次へ」

マウス・ドラッグに対応しろだぜ

kifuwarabe-futsu.png
「 お父ん。マウス・ドラッグして タイルを連続選択できないのかだぜ?」

ramen-tabero-futsu2.png
「 作ってない機能は 存在しないぜ」

kifuwarabe-futsu.png
「 作れ」

ramen-tabero-futsu2.png
「 ドラッグ アンド ドロップなのかな?
プレス アンド リリースじゃないかな?」

ohkina-hiyoko-futsu2.png
「 ドラッグ アンド ドロップって、
ファイルをつかんで アプリケーションの領域に落とすやつを言うのよ。
タイルの連続選択は プレス・アンド・リリース じゃないかなあ?」

ramen-tabero-futsu2.png
「 今は タップした時点で カーソルの位置が決まっているが、
リリースした時点で カーソルの位置を決めた方がいいのかだぜ?」

ohkina-hiyoko-futsu2.png
「 もっさりしない?」

kifuwarabe-futsu.png
「 操作感は 統一的になると思うが」

ramen-tabero-futsu2.png
「 タップしたジェスチャーは 捕捉できるが、
リリースしたというジェスチャーは どうやって捕捉するのかな?
調べるか」

📖 スワイプ ジェスチャを認識する

ramen-tabero-futsu2.png
「 👆 スワイプは 向きだけかあ」

📖 ドラッグ アンド ドロップ ジェスチャを認識する

ramen-tabero-futsu2.png
「 👆 ドラッグ アンド ドロップは ファイルを落とすやつだしな」

📖 ポインター ジェスチャを認識する

ramen-tabero-futsu2.png
「 👆 ポインター・ジェスチャーには 入りと 出があるのか。これを調べてみるか」

ramen-tabero-futsu2.png
「 エンターは 画像と重なったところで、
エグジットは 画像の外と重なったところか。
マウス・ボタン押下とか、マウス・ボタン・リリースではないんだ」

kifuwarabe-futsu.png
「 タップは マウス・ボタン押下と マウス・ボタン・リリースのペアか?」

ramen-tabero-futsu2.png
「 そうだぜ。
それも マウスを移動させずに マウス・ボタン押下と マウス・ボタン・リリースを
行わなければいけないぜ」

ohkina-hiyoko-futsu2.png
「 じゃあ タップは 従来の クリック に対応してるんだ」

kifuwarabe-futsu.png
「 マウス・ボタン押下と、 マウス・ボタン・リリースを 別々に捕捉する方法を探せだぜ」

ramen-tabero-futsu2.png
「 MAUI には無いようだぜ」

ohkina-hiyoko-futsu2.png
「 マウス・ダウンと マウス・アップを検知する 何らかの方法はあるのかしら?」

ramen-tabero-futsu2.png
「 タップで始まり、タップで終わるのでいいだろ」

kifuwarabe-futsu.png
「 ペン・タブレットで 必要になりそうな機能が MAUI に無いなんて
理解できないが お父んは そのような 理不尽や 意味不明を 越えていくのに長けているのだろう」

202307_maui_04-0113--tile-cursor-size.png

ramen-tabero-futsu2.png
「 👆 カンペキは無いものだぜ。タイルの連続選択できあがり」

📅 2023-07-04 タイルを登録できるようにしろだぜ

kifuwarabe-futsu.png
「 タイルは 名前で管理するのか? Idで管理するのか?」

ramen-tabero-futsu2.png
「 現代は UUID が流行ってて URL は わけの分からない数字、文字の羅列になってしまったが、
UUID が真のIdなら URL 無くして UUID にすればいいものの、
そうならないのは 名前 からイメージできる姿があるからだぜ」

ohkina-hiyoko-futsu2.png
「 名前は アスキー文字にすんの?
ユニコードにすんの?」

ramen-tabero-futsu2.png
「 こんな ネギラーメンで ユニコードが使えない環境のことを 本気で考えなくていいだろ。
ユニコードでいいんじゃないか?」

kifuwarabe-futsu.png
「 文字数は?」

ramen-tabero-futsu2.png
「 本気で考えなくていいだろ。 64文字でいいんじゃないか?」

ohkina-hiyoko-futsu2.png
「 1~4バイトのユニコード文字が 64個であることの意義は?」

ramen-tabero-futsu2.png
「 無いけど……」

kifuwarabe-futsu.png
「 ツクラーが タイルに名前を付けようと思ったときの 文字数の分布は?」

ramen-tabero-futsu2.png
「 データは無いけど……」

📖 Tiledによるタイルマップの作成とオブジェクトデータの取得を行う!:Cocos Creator
Tiled Cocos Creator

ramen-tabero-futsu2.png
「 👆 誰も タイルに名前なんか 付けないのでは?」

ohkina-hiyoko-futsu2.png
「 アマゾンの商品名の長さは?」

📖 KRAFT Macaroni & Cheese Easy Mac Cups (12 x 2.05 oz cups)クラフト マカロニチーズ イージーカップ 12パック 海外直送

ramen-tabero-futsu2.png
「 👆 適当にクリックしたが 英語表記、日本語表記をつなげて 重さや個数、海外直送まで入っているぜ」

ohkina-hiyoko-futsu2.png
「 ざっくり 100文字にしたら?」

ramen-tabero-futsu2.png
「 そうするか……」

kifuwarabe-futsu.png
「 すると みんな タイル名に 検索のための情報を 詰め込みだすのでは?」

ramen-tabero-futsu2.png
「 名前とは別に タグを付けれるようにするかだぜ?」

ohkina-hiyoko-futsu2.png
「 1つのタイルに タグは何個付けれて、1つのタグの長さは何文字までなの?」

ramen-tabero-futsu2.png
「 これは再帰的な話しで、1つのタグに たくさんの検索の情報を詰め込みだす……」

kifuwarabe-futsu.png
「 タイル名を付けるの めんどくさくなって タイル1タイル2タイル3 みたいな名前を付けるやつが
蔓延したらどうする?」

ramen-tabero-futsu2.png
「 連番付けられるぐらいだったら、 Id は こっちで採番してやるかだぜ」

ohkina-hiyoko-futsu2.png
「 1つのタイル・セットに、何枚のタイルがあんの?」

ramen-tabero-futsu2.png
「 データは持ってない」

kifuwarabe-futsu.png
「 Id だけ必須にして、それは自動で採番して、
100文字のテキスト・フィールドに 半角カンマ区切りで タグを自由入力させたらどうだぜ?」

ramen-tabero-futsu2.png
「 49個のアルファベットを タグで登録するやつがいて うざいかもしれない」

ohkina-hiyoko-futsu2.png
「 タグも 日本語で入力されたり、英語で入力されたり、表記揺れしたりするんじゃない?」

ramen-tabero-futsu2.png
「 じゃあ カテゴリー・ツリーを予め こっちで定義して そのノードを選ばせる方式にして、
それ以外に 固有名詞 を自由に入れれる欄を置けばどうか?」

ohkina-hiyoko-futsu2.png
「 Id欄と、100文字のコメント欄の2つにしましょう!
検索のための仕組みは 後回しで」

202307_maui_04-2122--save-button-o2o0.png

ramen-tabero-futsu2.png
「 👆 こんな感じで いいのかだぜ?」

ohkina-hiyoko-futsu2.png
「 動かしてみないと分かんないから それで 作ってみましょう」

  C:\Users\むずでょ\Documents\Unity Projects\Negiramen Practice\
  └── 📂 Assets
    └── 📂 Doujin Circle Negiramen
      └── 📂 Negiramen Quest
        └── 📂 Auto Generated
          └── 📂 Data
            └── 📂 CSV
              └── 📂 Tile Set
👉               └── 📄 map-tile-format-8x19.csv

ramen-tabero-futsu2.png
「 👆 ファイルは ここに置いとくぜ?」

Id, Left, Top, Width, Height, Comment
 1,   96,  64,    64,     64, 草原

ramen-tabero-futsu2.png
「 👆 保存内容は こんな感じで いいかだぜ?」

ohkina-hiyoko-futsu2.png
「 とりあえず それで」

ramen-tabero-futsu2.png
「 クエリー・パラーメーターで ビュー・モデルへ CSVファイルへのパスを渡したつもりなんだが、
コード・ビハインドの Load 時には ビュー・モデルに CSVファイルへのパスが入ってないな」

📖 .Net Maui/XAML QueryParameter is NULL in the viewmodel Constructor but usable in XAML, how do I access it in the viewmodel?

ramen-tabero-futsu2.png
「 👆 書かれてる通りにやってるんだが……、あっ、スペルミスだ!」

202307_maui_05-0125--add-button.png

ramen-tabero-futsu2.png
「 👆 とりあえず ハリボテ で、1行追加 できるようにしたぜ」

kifuwarabe-futsu.png
「 コメントの文字数のバリデーション、
Idの自動採番、
既に追加されているタイルは コメントを表示、ボタンのラベルも[追加]から[上書]へ変更、
削除ボタンの実装、
CSVを固定レイアウトではなく、列名を見るように変更、
CSVのダブルクォーテーションのエスケープ、
少なくとも これらは 残っているな」

ramen-tabero-futsu2.png
「 気の遠くなる話しだぜ」

ohkina-hiyoko-futsu2.png
「 じゃあ 睡眠へ切り替えよ。寝ろ」

📅 2023-07-05 マウス操作が分かりづらいの何とかしろ

ramen-tabero-futsu2.png
「 MAUI がタップ操作にUIを寄せていて、マウスダウン、マウスアップ が検知できないの クソなんだが」

ohkina-hiyoko-futsu2.png
「 最初の1回目のタップで あんたが枠を出すから、これでいいんだと思っちゃって
そしたら もう1回 タップしなくちゃいけないって分かって 分かりづらってなるのよ」

kifuwarabe-futsu.png
「 選択が未確定の間は カーソルが アニメーションしたらどうだぜ?」

ramen-tabero-futsu2.png
「 画面が チカチカ 動くのは オフィス・ソフトの分野では 非常識だぜ」

ohkina-hiyoko-futsu2.png
「 半透明な枠なら どうよ?」

202307_maui_05-2005--selecting.png

ramen-tabero-futsu2.png
「 👆 これぐらい はっきりと分かるぐらい 半透明にしてみるか」

Idを自動採番しろ

kifuwarabe-futsu.png
「 CSVファイルの中で1番大きなIdより 1 だけ大きいのが 新しいIdだろ。
お父ん。実装しろ」

ramen-tabero-futsu2.png
「 スキャンするのは カッコ悪いから 行が追加されたタイミングで 最大のIdを常に更新するかだぜ」

202307_maui_05-2124--tile-id-o2o0.png

ramen-tabero-futsu2.png
「 👆 Idは 増えるようにしたぜ」

登録されているタイルは表示しろ

kifuwarabe-futsu.png
「 登録されているタイルは 表示してくれだぜ」

ramen-tabero-futsu2.png
「 タイルが 1000個 登録されていたら、
画面上には タイル 1000個 のスプライトを 表示しないと いけないのかだぜ?」

ohkina-hiyoko-futsu2.png
「 画面を開いたときと、
タイルを追加・削除したときに キャンバスを描きなおせばよくない?」

ramen-tabero-futsu2.png
「 じゃあ 実際のタイル画像とは別に、
ワーキング(Working;作業中)なタイル画像を 内部的に持っておけばいいかな」

202307_maui_05-2139--tile-image-o2o0.png

ramen-tabero-futsu2.png
「 👆 Source に内部メモリーを指定できるのかだぜ?」

ohkina-hiyoko-futsu2.png
「 外部ファイルで十分なんじゃないの?」

ramen-tabero-futsu2.png
「 作業中の画像は、
ネギラーメンのワーキング・スペース、
ユーザーの AppData、
ユニティの Assetsフォルダー、
どこに置くのがベスト・プラクティスだぜ?」

ohkina-hiyoko-futsu2.png
「 ユニティの Assets フォルダーには 資産じゃないものは 置きたくないわねえ」

kifuwarabe-futsu.png
「 ユーザーの AppData に ゴミを置きたくないぜ」

ramen-tabero-futsu2.png
「 じゃあ ネギラーメンのワーキング・スペースかだぜ」

ohkina-hiyoko-futsu2.png
「 ネギラーメンを2重起動しなければ 問題ないんじゃない?」

  例: C:\Users\むずでょ\Documents\GitHub\2D-RPG-Negiramen
  └── 📂 Workspace
    ├── 📂 Assets
    ├── 📂 For Unity Assets
    └── 📂 Temporary
      └── 📂 Images
👉       └── 📄 working_tile_set_canvas.png

ramen-tabero-futsu2.png
「 👆 こんな感じで テンポラリー(Temporary;一時的な)フォルダーを切ろうかな?」

第2の構成ファイル

kifuwarabe-futsu.png
「 ファイル・パスは ハード・コーディングするのか?」

ramen-tabero-futsu2.png
「 いーや。ソース・コードの中に設定が書かれているのは メンテナンス 時の選択肢を狭めて良くない。
外部ファイルで全部 指定できるようにしたいぜ」

  例: C:\Users\むずでょ\Documents\GitHub\2D-RPG-Negiramen
  └── 📂 Workspace
👉   └── 📄 configuration_2nd.toml

ramen-tabero-futsu2.png
「 👆 第2の構成ファイルだから、こんな感じでどうだぜ?」

ohkina-hiyoko-futsu2.png
「 じゃあ とりあえず それで」

[paths]

# ネギラーメン・ワークスペースの作業中のタイル・セット・キャンバスPNG画像ファイルへのパス
working_tile_set_canvas = "{negiramen_workspace_folder}/Temporary/Images/working_tile_set_canvas.png"

ramen-tabero-futsu2.png
「 👆 ファイルの中身は こんな感じでどうだぜ?」

kifuwarabe-futsu.png
「 とりあえず それで」

202307_maui_05-2254--configuration-1st-o2o0.png

ramen-tabero-futsu2.png
「 👆 厳密に行くなら 構成ファイルに この1行を書き足しておきたいぜ」

kifuwarabe-futsu.png
「 そのファイル・パスは MAUI から編集できるようにするのかだぜ?」

ramen-tabero-futsu2.png
「 非表示でいいだろ、こんな細かいの」

ohkina-hiyoko-futsu2.png
「 ユーザーが そのファイルに辿りつけなくない?」

ramen-tabero-futsu2.png
「 AppData は 隠しフォルダー なんで」

kifuwarabe-futsu.png
「 じゃあ ネギラーメンを開発する お父ん や、
ネギラーメンを改造する人だけが 知ってればいいんだ」

ohkina-hiyoko-futsu2.png
「 configuration_2nd.toml は 隠さなくていいの?」

ramen-tabero-futsu2.png
「 どこに 何が置いてあるかの 目録になるんで」

ohkina-hiyoko-futsu2.png
「 configuration_2nd.toml って名前だったら、じゃあ configuration_1st.toml は どこにあるんだ?
って探さない?」

ramen-tabero-futsu2.png
「 ぐぬぬぬぬ」

  例: C:\Users\むずでょ\Documents\GitHub\2D-RPG-Negiramen
  └── 📂 Workspace
👉   └── 📄 user_configuration.toml

ramen-tabero-futsu2.png
「 👆 user_configuration.toml にしよう!」

設定ファイルの中で変数展開

202307_maui_06-0051--path-expand-variables-o2o0.png

ramen-tabero-futsu2.png
「 👆 設定ファイルの中で変数が使える仕組みを 簡易実装したところで 今日はここまでだぜ」

ohkina-hiyoko-futsu2.png
「 最初に作っとかないと あとで困るやつだし、
本筋の作業が進んでないけど いっか~」

kifuwarabe-futsu.png
「 なかなか 前に進まないな……」

📅 2023-07-06 タイル・パレット編集画面へタイル・セット画像ファイルへのパスを渡せだぜ

kifuwarabe-futsu.png
「 お父ん、タイル・セット画像へのファイル・パスをハードコーディングしてるだろ。
まず これを クエリー・パラメーターに置き換えて、
画面遷移元から タイル・セット画像へのファイル・パスを受け取る形にしろだぜ」

ramen-tabero-futsu2.png
「 わかったぜ」

(カタ カタ カタ カタ ……)

ramen-tabero-futsu2.png
「 でけたぜ」

kifuwarabe-futsu.png
「 次はその タイル・セット画像へのファイル・パスを読込んで、
そして
C:/Users/むずでょ/Documents/GitHub/2D-RPG-Negiramen/Workspace/Temporary/Images/working_tile_set_canvas.png へ出力しろだぜ」

ramen-tabero-futsu2.png
「 やってみるぜ」

(カタ カタ カタ カタ ……)

ramen-tabero-futsu2.png
「 👇 C# なら ImageIO 使えばいいのかだぜ?」

📖 画像ファイルを読み込み、Imageオブジェクトを作成する

using System.Drawing.Image;

ramen-tabero-futsu2.png
「 👆 MAUI に System.Drawing.Image 無い」

ohkina-hiyoko-futsu2.png
「 マルチプラットフォーム化で 使えなくしているパッケージなのでしょう」

ramen-tabero-futsu2.png
「 👇 現代では こっち読むのか。インターネット上の大量の記事が 無駄になったかも知れないなあ」

📖 Microsoft > Image(コントロール)
📖 Microsoft > イメージ(メモリー)

        Assembly assembly = GetType().GetTypeInfo().Assembly;
        using (Stream stream = assembly.GetManifestResourceStream("GraphicsViewDemos.Resources.Images.dotnet_bot.png"))
        {
            image = new W2DImageLoadingService().FromStream(stream);
        }

ramen-tabero-futsu2.png
「 👆 リソース・フォルダーの中の画像を取得する方法が 書いてるな。
今回は逆に 任意のディレクトリーの画像のメモリー・ストリームを取らないといけない」

📖 Microsoft > Bundled files

public async Task<string> ReadTextFile(string filePath)
{
    using Stream fileStream = await FileSystem.Current.OpenAppPackageFileAsync(filePath);
    using StreamReader reader = new StreamReader(fileStream);

    return await reader.ReadToEndAsync();
}

ramen-tabero-futsu2.png
「 👆 このテキスト・ファイルの例を、画像に書き換えられないか?」

using Microsoft.Maui.Graphics.Win2D;

ramen-tabero-futsu2.png
「 👆 このネームスペースが存在しないんだが?」

ohkina-hiyoko-futsu2.png
「 NuGet で取ってくるんじゃないの?」

202307_maui_06-2358--graphics.png

ramen-tabero-futsu2.png
「 👆 これかな?」

kifuwarabe-futsu.png
「 それはインストール済みだぜ」

202307_maui_07-0001--platform-error.png

ramen-tabero-futsu2.png
「 👆 じゃあ このエラーは何だぜ?」

ohkina-hiyoko-futsu2.png
「 プリプロセッサ・ディレクティブを使って Windowsと Macを分ける必要があるんじゃないの?」

#if IOS || ANDROID || MACCATALYST
using Microsoft.Maui.Graphics.Platform;
#elif WINDOWS
using Microsoft.Maui.Graphics.Win2D;
#endif

// ... 中略 ...

#if IOS || ANDROID || MACCATALYST
                // PlatformImage isn't currently supported on Windows.
                TheGraphics.IImage image = PlatformImage.FromStream(inputFileStream);
#elif WINDOWS
                TheGraphics.IImage image = new W2DImageLoadingService().FromStream(inputFileStream);
#endif

ramen-tabero-futsu2.png
「 👆 プラットフォームの違いを メソッドが隠蔽してくれたらいいのに……」

        //
        // タイル・セット・キャンバス画像の読込
        //
        var task = Task.Run(() =>
        {
            try
            {
                // 読込元(ウィンドウズ・ローカルPC)
                using (Stream inputFileStream = System.IO.File.OpenRead(tileSetImageFilePathAsStr))
                {
#if IOS || ANDROID || MACCATALYST
                    // PlatformImage isn't currently supported on Windows.
                    TheGraphics.IImage image = PlatformImage.FromStream(inputFileStream);
#elif WINDOWS
                    TheGraphics.IImage image = new W2DImageLoadingService().FromStream(inputFileStream);
#endif

                    //
                    // 作業中のタイル・セット・キャンバス画像の保存
                    //
                    if (image != null)
                    {
                        // 書出先(ウィンドウズ・ローカルPC)
                        using (Stream outputFileStream = System.IO.File.Open(workingTileSetCanvasImagefilePathAsStr, FileMode.OpenOrCreate))
                        {
                            image.Save(outputFileStream);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                // TODO エラー対応どうする?
            }
        });

ramen-tabero-futsu2.png
「 👆 MAUI から Windowsのフォルダーにアクセスできるけど、
マルチ・プラットフォームというメリットが無くなってしまうよな」

kifuwarabe-futsu.png
「 じゃあ Windows の利便性を失わせるかだぜ?」

ohkina-hiyoko-futsu2.png
「 ユーザーに AppData フォルダー下を いじらせるのは
隠しフォルダーの意義を失うわよ」

ramen-tabero-futsu2.png
「 じゃあ Windows依存で進めるか~」

202307_maui_07-0050--write-image.png

ramen-tabero-futsu2.png
「 👆 PNG画像の書出しまで でけたぜ」

kifuwarabe-futsu.png
「 今は タイル・セット画像の方を MAUI に表示してるだろ。
それを止めて、こっちの 作業中のタイル・セット画像の方を MAUI に表示してくれだぜ」

ramen-tabero-futsu2.png
「 分かったぜ」

(カタ カタ カタ カタ ……)

ramen-tabero-futsu2.png
「 その差し替えも終わったぜ」

ohkina-hiyoko-futsu2.png
「 すでに登録済みのタイルは 半透明の青色で塗りつぶしておくと、
残作業が見えやすくなるんじゃない?」

ramen-tabero-futsu2.png
「 やってみるぜ」

Microsoft.Maui.Graphics.IImage

Microsoft.Maui.Graphics.ICanvas

ramen-tabero-futsu2.png
「 👆 あれっ? 描画ができるのは IImage じゃなくて、 ICanvas の方だぜ?」

kifuwarabe-futsu.png
「 IImage を ICanvas に変換する方法がないか、調べろだぜ」

ramen-tabero-futsu2.png
「 ググっても出てこないから デバッグライトするぜ。
IImage の実体は W2DImage らしいんだが、これも探しても出てこない」

ohkina-hiyoko-futsu2.png
「 Windowsの2Dイメージなんじゃないの?」

kifuwarabe-futsu.png
「 タイル・カーソルと同じように IDrawable を実装したクラスを作って、
XAML の GraphicView 要素の Drawable 属性で指定したらどうだぜ?」

ramen-tabero-futsu2.png
「 あっ、そうか!」

ramen-tabero-futsu2.png
「 IDrawable を実装したクラスと、ビュー・モデルが連携できないの
グローバル変数での連携が大変だぜ、どうにかならないの?」

kifuwarabe-futsu.png
「 👇 BindableObject というのが あるそうだぜ」

📖 In .NET MAUI, how do I pass variables to a GraphicsView.Drawable in a ContentView
📖 How to pass variable data into .NET MAUI GraphicsView canvas

ramen-tabero-futsu2.png
「 覚えてみるかだぜ」

📅 2023-07-07 IdをBASE64にしようぜ?

ramen-tabero-futsu2.png
「 Id を BASE64 にしようぜ?」

ohkina-hiyoko-futsu2.png
「 メリットは?」

ramen-tabero-futsu2.png
「 人は 整数を見ると 1から順にソートしたくなる。
BASE64 なら ソートしようとは思わない。
Idをソートしようとする悲しい人類を救うことができる」

ohkina-hiyoko-futsu2.png
「 エビデンスは?」

ramen-tabero-futsu2.png
「 無い。本番環境で実験だぜ」

kifuwarabe-futsu.png
「 やってみろだぜ」

ramen-tabero-futsu2.png
「 👇 Convert クラスを使ってみるか」

📖 Convert.ToBase64String メソッド
📖 Converting string to byte array in C#
202307_maui_07-1848--id-base64-o2o0.png

ramen-tabero-futsu2.png
「 👆 Idを BASE64にしたぜ」

kifuwarabe-futsu.png
「 わらう」

ohkina-hiyoko-futsu2.png
「 👇 桁数が気になるわね。
1MQ== だけど、 1000MTAwMA== よ?」

📖 データ変換ツール

ramen-tabero-futsu2.png
「 3桁ぐらいの文字なら 4桁ぐらいに変換されて気にならないが、
4桁ぐらいの文字は 8桁ぐらいに変換されて メモリ効率は 2倍になって 悪くなるな。
だいたい、 1.3倍ぐらい メモリ効率は悪くなるぜ」

ohkina-hiyoko-futsu2.png
「 メモリ効率が1.3倍に悪くなることと引き換えに
悲しい人類がIdをソートしようとすることを防ごうと言うのね」

202307_maui_07-1856--id1000-base64-o2o0.png

ramen-tabero-futsu2.png
「 👆 Idが1000に達したとき、BASE64にすると 改行されてしまうのは 悪しと見るか、
コーナーケースに合わせるとキリがないので これで良しと見るか」

kifuwarabe-futsu.png
「 1000枚もタイルが含まれる タイル・セット画像を 利用するやつ、
そんなとこ 気にするでもなく ハードワーカーだろ」

ohkina-hiyoko-futsu2.png
「 999枚もタイルが含まれない タイル・セット画像を 利用する人にとっては、
無駄なスペースが 空いていることの方が きにするでしょう」

ramen-tabero-futsu2.png
「 あっ、Id をマウスで選択できね。気になるな……。
選択可能なテキストで、かつ入力ができない リード・オンリーな設定できるかな……?」

202307_maui_07-1909--readonly-o2o0.png

ramen-tabero-futsu2.png
「 👆 でけた。
フォント・サイズは きっかり スタイルで決まっているようで 任意サイズにはできなかったので
Entry 要素を広げたぜ」

ohkina-hiyoko-futsu2.png
「 ラベルの Idコメント の間に パディング 入れられないの?」

202307_maui_07-1914--padding-o2o0.png

ramen-tabero-futsu2.png
「 👆 入れれるぜ」

ohkina-hiyoko-futsu2.png
「 良くなった。ラベルの文字は 隣のセルと くっつかないようにしましょう」

202307_maui_07-1920--tileId-o2o0.png

ramen-tabero-futsu2.png
「 👆 Id だけだと オーラル・コミュニケーションで困るだろうから
タイルId と書いといてやろう」

ohkina-hiyoko-futsu2.png
「 そのIdって、 ひだり、うえ、よこ、たて から一意に決まらないの?」

ramen-tabero-futsu2.png
「 例えば 128,32,96,32 を BASE64に変換擦ると MTI4LDMyLDk2LDMy だぜ。
これだったら ベクターを2つ 覚えておいた方がマシかも」

kifuwarabe-futsu.png
「 情報で構成されている Id なんて、イケてないぜ。それは暗号だぜ」

ramen-tabero-futsu2.png
「 あくまで 表示に BASE64 を使っているだけで、内部的には 整数なんで」

ohkina-hiyoko-futsu2.png
「 このタイルIdは、プロジェクトの中で一意なの?
それとも タイル・セット画像ファイルの中で一意なの?」

ramen-tabero-futsu2.png
「 凝り出すと UUID に行きついてしまう。
タイル・セット画像ファイルの中での ローカルなIdだぜ」

ohkina-hiyoko-futsu2.png
「 じゃあ タイルIdには タイル・セット画像ファイルのIdも 表示しないと
本当のタイルIdにはならないんじゃない?」

ramen-tabero-futsu2.png
「 タイル・セット画像ファイルに Idを振ることが難しい。
プロジェクトの中での ローカルなIdなら 振れるだろうけど、
そのIdは 別のプロジェクトへ使い回せない」

ohkina-hiyoko-futsu2.png
「 プロジェクトに UUID 振ればいいんじゃないの?」

ramen-tabero-futsu2.png
「 ブランチして 開発が平行したら ノー・コントロール になってしまう」

kifuwarabe-futsu.png
「 じゃあ なんで タイルId なんか採番するんだぜ?
ファイル名、ひだり、うえ、よこ、たて が本当のIdなんじゃないのかだぜ?」

ramen-tabero-futsu2.png
「 あるファイル内の中だけで使える、
ひだり、うえ、よこ、たて の情報を 3桁程度の整数に集約するのが タイルId だぜ」

ohkina-hiyoko-futsu2.png
「 その情報を ユーザーに提示する理由は?」

ramen-tabero-futsu2.png
「 タイル1タイル2 のような タイル名 を ユーザーに入力させないこと、
12 のような 連番 を ユーザーに入力させないこと、
これらの代替が タイルId だぜ」

ohkina-hiyoko-futsu2.png
「 意義はあるんだ」

kifuwarabe-futsu.png
「 しかし それは Id の働きを持っていないのでは?
何かと言えば コード なのでは?」

ramen-tabero-futsu2.png
「 内部的には Id なんだが、表示上は コード だな。
じゃあ オーラル・コミュニケーションを考えて ラベルを変えるかだぜ」

202307_maui_07-1955--tile-code-o2o0.png

ramen-tabero-futsu2.png
「 👆 確かに タイル・コード にすると しっくりしたな」

kifuwarabe-futsu.png
「 しかし そもそも BASE64 は、 オーラル・コミュニケーション には向いていないのでは?」

ramen-tabero-futsu2.png
「 諫言だぜ」

ohkina-hiyoko-futsu2.png
「 じゃあ BASE64の 64文字に対して Apple とか、 Banana とか
プロナウンサブル(Pronounceable;発音可能)な単語を当てたらどう?」

ramen-tabero-futsu2.png
「 インターナショナル(International;国際的)に通用するフォニックス(Phonics;発音)ってある?」

kifuwarabe-futsu.png
「 軍事か通信、航空あたりを調べれば 何か規格があるのでは?」

ramen-tabero-futsu2.png
「 調べるか~」

ramen-tabero-futsu2.png
「 👇 ナトー のがあったぜ」

📖 NATOフォネティックコード

kifuwarabe-futsu.png
「 はっきり 西側に寄り添うの わらう」

ramen-tabero-futsu2.png
「 大文字と小文字は 区別しないのか~」

ohkina-hiyoko-futsu2.png
「 英語のフォネティックコードが人名なんで、大文字にかこつけて 大文字は英語にしたらいいんじゃないの?」

ramen-tabero-futsu2.png
「 じゃあそれで。作ってみるか~」

ramen-tabero-futsu2.png
「 大文字も 小文字も X-ray になるんだが」

ohkina-hiyoko-futsu2.png
「 違う所から 持ってきなさい」

BASE64  英単語       読み
------  ---------   -------
A   Alice       アリス
B   Boart       ボート
C   Castle      キャッスル
D   Drink       ドリンク
E   Elf         エルフ
F   Forest      フォレスト
G   Gold        ゴールド
H   Hotel       ホテル
I   Island      アイランド
J   John        ジョン
K   King        キング
L   Level       レベル
M   Madam       マダム
N   News        ニュース
O   Ork         オーク
P   Pond        ポンド
Q   Queen       クイーン
R   Room        ルーム
S   Soup        スープ
T   Talk        トーク
U   Uncle       アンクル
V   Video       ビデオ
W   Wolf        ウルフ
X   Xmas        クリスマス
Y   Yogurt      ヨーグルト
Z   Zebra       ゼブラ
a   and         アンド
b   big         ビッグ
c   clean       クリーン
d   damage      ダメージ
e   evil        イーブル
f   fake        フェイク
g   get         ゲット
h   hit         ヒット
i   ice         アイス
j   jump        ジャンプ
k   kick        キック
l   love        ラブ
m   magic       マジック
n   no          ノー
o   oily        オイリー
p   poison      ポイズン
q   quiz        クイズ
r   rain        レイン
s   solty       ソルティー
t   trendy      トレンディー
u   up          アップ
v   victory     ビクトリー
w   wind        ウィンド
x   xrated      エックスレーテド
y   your        ユワ
z   zenith      ゼニス
0   0           (数字)
1   1           (数字)
2   2           (数字)
3   3           (数字)
4   4           (数字)
5   5           (数字)
6   6           (数字)
7   7           (数字)
8   8           (数字)
9   9           (数字)
+   +           (プラス)
/   /           (スラッシュ)
=   =           (イコール)

ramen-tabero-futsu2.png
「 👆 ゲームに出てきそうな 短い英単語を 持ってきたぜ」

kifuwarabe-futsu.png
「 趣向を変えたんだな」

ramen-tabero-futsu2.png
「 単語の先頭だけ切り取れば BASE64 に戻るぜ」

ohkina-hiyoko-futsu2.png
「 動かしてみましょう」

202307_maui_08-0017--madam-get-o2o0.png

ramen-tabero-futsu2.png
「 Madam get = = になるぜ」

ohkina-hiyoko-futsu2.png
「 BASE64 より さらに 6倍近く 長くならない?」

ramen-tabero-futsu2.png
「 なりそう」

ohkina-hiyoko-futsu2.png
「 Id 1000 で試しなさい」

202307_maui_08-0025--long-code.png

ramen-tabero-futsu2.png
「 👆 今の3倍ぐらいの長さにすれば 入りそう」

kifuwarabe-futsu.png
「 ユーザーは 何だこれは? と思わないだろうか?」

ohkina-hiyoko-futsu2.png
「 思う」

ohkina-hiyoko-futsu2.png
「 あと、 BASE64 は、文字列連結しないのであれば 桁のプレースホルダーの = は省いていいそうよ」

ramen-tabero-futsu2.png
「 ちょっと考えるぜ」

202307_maui_08-0057--memory-o2o0.png

ramen-tabero-futsu2.png
「 👆 欄外に書いたぜ」

kifuwarabe-futsu.png
「 ぜったい なんのこっちゃ なんだよなあ」

ohkina-hiyoko-futsu2.png
「 それがタイルの名前としての働きを持つと 認識できないのよね」

ramen-tabero-futsu2.png
「 名前 という文化は廃止だぜ」

kifuwarabe-futsu.png
「 ディーエックス」

202307_maui_08-0123--name-o2o0.png

ramen-tabero-futsu2.png
「 👆 どうしても 名前を書きたいやつは コメント欄に書け、と親切に 書いておくぜ」

ohkina-hiyoko-futsu2.png
「 (任意) も付けておいた方がよくない?」

kifuwarabe-futsu.png
「 任意 の意味が分からん人も いるそうだぜ」

ramen-tabero-futsu2.png
「 あんまり 書きすぎると デザインの敗北……」

📅 2023-07-08 タイルを選択したら、照会しろだぜ

kifuwarabe-futsu.png
「 タイル・パレット上で 範囲選択したら、
そのタイルは すでに登録済みか、まだ登録されていないか、判定しろだぜ」

ramen-tabero-futsu2.png
「 わかったぜ」

(カタ カタ カタ カタ)

ramen-tabero-futsu2.png
「 前のトリック・コードは 奇数回実行すると働くが、偶数回実行すると働かないというバグを踏んだので
対応中」

ohkina-hiyoko-futsu2.png
「 トリックなんかに頼るからよ」

202307_maui_08-2329--read-file-o2o0.png

ramen-tabero-futsu2.png
「 👆 登録したタイルの情報を 読み込むようにしたが、
全体的に動きが 怪しいので 調整中だぜ」

202307_maui_09-0047--tile-form-display-o2o0.png

ramen-tabero-futsu2.png
「 👆 タイル・コードと コメントの入出力は 動きが付いたぜ」

kifuwarabe-futsu.png
「 もう寝ろ」

📅 (2023-07-09 sun)タイルが登録されているとき、ボタンのラベルを追加から上書へ変更してくれだぜ

ramen-tabero-futsu2.png
「 日曜日は 昼まで寝た」

kifuwarabe-futsu.png
「 タイルが登録されているとき、ボタンのラベルを追加から上書へ変更してくれだぜ」

ramen-tabero-futsu2.png
「 分かったぜ」

202307_maui_09-1257--adds-button-label--o2o0.png

ramen-tabero-futsu2.png
「 👆 タイルが登録されているときは、ボタンのラベルを 上書 に変えるようにしたぜ」

国際化

ohkina-hiyoko-futsu2.png
「 その 上書 を、 Overwrite にしても ボタンの中に収まるの?」

ramen-tabero-futsu2.png
「 多言語化か……。試してみるぜ」

202307_maui_09-1342--overwrite-o2o0.png

ramen-tabero-futsu2.png
「 👆 収まらないぜ」

ohkina-hiyoko-futsu2.png
「 じゃあ このアプリは 国際化に耐えられないわよ」

ramen-tabero-futsu2.png
「 横幅が長い……。 海外人、どんな UI 使ってるんだぜ?」

kifuwarabe-futsu.png
「 日本人が ビューにたくさん項目を詰めるの こだわるの、
チャイニーズ・キャラクター文化だからなのかな?」

ohkina-hiyoko-futsu2.png
「 欧米の アイコン が、漢字相当なんじゃない?」

ramen-tabero-futsu2.png
「 じゃあ、アイコンか 漢字かを選べるようにしたらいいのか……?」

kifuwarabe-futsu.png
「 👇 ガイドラインを読めだぜ」

📖 Microsoft > Visual Studio のイメージとアイコン

ramen-tabero-futsu2.png
「 👆 欲しいアイコンが無いし、似たようなアイコンばっかり いっぱいある」

202307_maui_09-1401--edit.png

ramen-tabero-futsu2.png
「 👆 ペンが無難だと思う」

202307_maui_09-1403--resources.png

ramen-tabero-futsu2.png
「 👆 しかし MAUI にも最初から ちょびっとだけ リソースが入ってるな」

ohkina-hiyoko-futsu2.png
「 MAUI 用のリソース集も どっかで配られてんじゃないの?」

ramen-tabero-futsu2.png
「 👇 フォントでやるのが いいのか~?」

📖 .NET MAUI アプリ アイコンを変更する

📖 .NET MAUIで、Emoji(絵文字)やIcon(アイコン)を打とう

📖 Segoe Fluent Icons font

📖 Google Fonts > Material Symbols And Icons

ramen-tabero-futsu2.png
「 👇 ボタンに アイコン・フォントを表示させるのは どうやるんだぜ? 画像の方法はあるが」

📖 [.NET MAUI][Button] ボタンにイメージを表示する

ramen-tabero-futsu2.png
「 👇 画像も 文字も アイコン・フォントも 方法を統一してくれたらいいのに……」

📖 Font Icons in Shell Tabs not showing

202307_maui_09-1424--mojibake-o2o0.png

ramen-tabero-futsu2.png
「 👆 あれっ? 文字化けだ。 Windows 11 には Segoe Fluent Icons フォントは最初から入ってると 読んだが……」

kifuwarabe-futsu.png
「 お父んのPC、 Windows 10」

ohkina-hiyoko-futsu2.png
「 マルチ・デバイスのプログラミングが ホストOSに依存したら 悪いんじゃない?」

ramen-tabero-futsu2.png
「 👇 どこから Segoe Fluent Icons フォントを入手するんだぜ?」

📖 Microsoft > fluentui-system-icons

ramen-tabero-futsu2.png
「 👇 情報ではなく、フォントが欲しい」

📖 Microsoft > Segoe UI font family

ohkina-hiyoko-futsu2.png
「 👇 ずっと前から シーゴーは Windows に入っているみたいだけど」

📖 Wikipedia > Segoe

ohkina-hiyoko-futsu2.png
「 👇 シーゴーは 日本語フォントではない、という話しもあるわね」

📖 Segoe UIフォントは日本語フォントなのか

ramen-tabero-futsu2.png
「 日本語の設定のまま シーゴー を使えないのかだぜ?」

202307_maui_09-1501--image-o2o0.png

ramen-tabero-futsu2.png
「 👆 フォントのような不確定要素を使うのは諦め、ビジュアル・スタジオ2022イメージ・ライブラリーから
ザムルを取ってくることにするぜ」

📖 Microsoft > リソース ディクショナリのマージ

ramen-tabero-futsu2.png
「 👆 リソース・ディクショナリーとして マージすれば 使えるか?」

202307_maui_09-1517--resource-file.png

ramen-tabero-futsu2.png
「 👆 リソース・ディクショナリーの書き方を忘れたので 調べるぜ」

202307_maui_09-1519--resource-dictionary.png

ramen-tabero-futsu2.png
「 👆 あのXMLタグに挟めばいいのか」

202307_maui_09-1521--edit-o2o0.png

ramen-tabero-futsu2.png
「 👆 ビジュアル・スタジオ2022イメージ・ライブラリーの Edit.xaml の Viewbox を、貼り付けるぜ」

kifuwarabe-futsu.png
「 そういう手間が要るんだな」

202307_maui_09-1527--xmlns-o2o0.png

ramen-tabero-futsu2.png
「 👆 ダメだ 仕様が旧い」

ohkina-hiyoko-futsu2.png
「 SVG形式にしたらいいんじゃないの?」

ramen-tabero-futsu2.png
「 👇 SVG は、画像じゃなくて アイコン扱いなのか?」

📖 I can't set a .svg file as a maui app icon

ramen-tabero-futsu2.png
「 📂 Resources/Images フォルダーは 何か特別な管理下にあるみたいで ふつうのフォルダーのようには扱えなさそうだぜ」

kifuwarabe-futsu.png
「 MAUI は、ファイル・パスという概念を 無くしたいのでは?」

ohkina-hiyoko-futsu2.png
「 スマホ・デバイスへの対応のために?」

202307_maui_09-1610--maui-bot.png

ramen-tabero-futsu2.png
「 👆 MAUI の最初に出てきた ロボット、あいつ SVG画像らしい。
あいつは 表示されて、
ペンを ボタンの上に表示できないの、何故だぜ?」

202307_maui_09-1620--svg.png

ramen-tabero-futsu2.png
「 👆 なんで ペン がでかい?
そして SVG なのにラスタライズされてる?」

202307_maui_09-1622--svg-to_v2o0.png

ramen-tabero-futsu2.png
「 👆 さらに なぜ .svg ではなく .png にしないと画像が出てこない?」

kifuwarabe-futsu.png
「 自動で ラスタライズ されているのでは?」

202307_maui_09-1627--directory-o2o0.png

ramen-tabero-futsu2.png
「 👆 フォルダーを切って その中に入れると、パスでアクセスできなくなるのは 何故だぜ?」

kifuwarabe-futsu.png
「 👇 これを読めだぜ」

📖 Add images to a .NET MAUI app project

ramen-tabero-futsu2.png
「 Android アプリがこうしてるから、 MAUI もこうしてる、というような 腰抜けの話しが 書かれているぜ。
クソじゃないか」

ohkina-hiyoko-futsu2.png
「 なんで Android アプリに迎合するのかしら?」

ramen-tabero-futsu2.png
「 Microsoft が腰抜けだからだろ」

kifuwarabe-futsu.png
「 👇 これを読めだぜ」

📖 Images in subfolders not showing up on Windows but do on Android #8628

<ItemGroup>
    <MauiImage Include="Resources/Images/XXXXXXXX/*" />
</ItemGroup>

ramen-tabero-futsu2.png
「 👆 なんか こういうタグをどこかに書くと そのフォルダーがプロジェクトに認識されるらしいぜ」

kifuwarabe-futsu.png
「 それは どこに書くんだぜ?」

202307_maui_09-1717--csproj-o2o0.png

ramen-tabero-futsu2.png
「 ファイルを開けまくって 消去法をしている途中で 2D RPG Negiramen.csproj に それっぽいコードを発見したぜ」

ohkina-hiyoko-futsu2.png
「 書き足してみましょう!」

202307_maui_09-1816--maui-image-o2o0.png

ramen-tabero-futsu2.png
「 👆 \* を、 \**\* に変えると、
直下フォルダーの任意のファイルではなく、
サブフォルダ―も下りて行って任意のファイルを 見てくれるようだぜ」

202307_maui_09-1821--rtf-o2o0.png

ramen-tabero-futsu2.png
「 👆 また、 Android に迎合して、ディレクトリー名、ファイル名に 大文字や空白は使えず、
小文字英字、ハイフン、数字だけを使うようにするぜ」

202307_maui_09-1832--image-o2o0.png

ramen-tabero-futsu2.png
「 👆 そして ディレクトリーは無視されるという クソ仕様により、
ファイル名だけで指定することになるぜ。拡張子は、ファイル名に .png と付いていても XAML には .png と指定するクソ仕様」

ohkina-hiyoko-futsu2.png
「 MAUI は、プラットフォームごとに 異なる画像ファイル形式で用意されても、
XAML には .png と書こうという MAUI の開発者の頭が残念なことに なってるのね~」

kifuwarabe-futsu.png
「 ラスター画像と ベクター画像の特性の違いも理解できないぐらい 知能が下がってるのかだぜ?」

202307_maui_09-1843--rename-o2o0.png

ramen-tabero-futsu2.png
「 👆 ファイル名が被りたくないので プレフィックス(Prefix;接頭辞)を付けるぜ」

kifuwarabe-futsu.png
「 インフラの出来が悪いと 要らんテクニックが使われてしまうな」

ohkina-hiyoko-futsu2.png
「 フォルダー下に、別の命名システムを持ったフォルダーを ぶらさげたいこともあるのに、
それが考慮されていないのは
MAUI の開発者が 開発の現場経験が未熟だろうから 全員クビになっても 不思議ではないわねえ」

202307_maui_09-1852--svg-color-o2o0.png

ramen-tabero-futsu2.png
「 👆 SVG形式画像を PNG形式画像に変換した後のものが ボタンの上に描かれるから、
テキスト・カラーを 白 にしても 白くならないぜ!」

kifuwarabe-futsu.png
「 当然だな」

ramen-tabero-futsu2.png
「 MAUI お前 コンピューター・グラフィックスという 自覚 無いのかだぜ?」

ohkina-hiyoko-futsu2.png
「 MAUI の開発者も いずれ全員 クビになるでしょう」

ramen-tabero-futsu2.png
「 👇 代替策を探さな」

📖 Specify the color of a SVG image in .NET Maui

202307_maui_09-1911--tint-color-o2o0.png

ramen-tabero-futsu2.png
「 👆 TintColor も効果なし」

ohkina-hiyoko-futsu2.png
「 MAUI の出来が悪いんじゃないの? あんまり 期待できないんだから
トリックを使っていくことに なるんじゃない?」

ramen-tabero-futsu2.png
「 じゃあ ツールチップ・ヒント の使い方を調べるか」

202307_maui_09-1939--long-button-o2o0.png

ramen-tabero-futsu2.png
「 👆 ボタンは 横に広く使うように 妥協。
ツールチップ・ヒントも 組み合わせたので、
国際化は 少々横長のボタンと ツールチップ・ヒントで なんとかしてくれだぜ」

ohkina-hiyoko-futsu2.png
「 タイル名、または コメントを自由入力 というメッセージが ダサいから タイル名 だけでよくない?」

202307_maui_09-1954--label-o2o0.png

ramen-tabero-futsu2.png
「 👆 すっきりさせたぜ」

多言語化

kifuwarabe-futsu.png
「 英語版、日本語版と どうやって切り替えるんだぜ?」

ramen-tabero-futsu2.png
「 調べるか……」

📖 .NET MAUI : Write multilingual apps easily

ramen-tabero-futsu2.png
「 👆 Xamarine の方法がそのまま使えるらしいが、それでいいのか もっと調べるか……」

ramen-tabero-futsu2.png
「 👇 昔の Windows のやり方も 冴えてないしなあ」

📖 How to implement .NET MAUI localization

ramen-tabero-futsu2.png
「 👇 この動画の人 センス有るな 調べてみるか」

📺 Localization in .NET MAUI - Adding Multi-Language to Your Apps

ramen-tabero-futsu2.png
「 👇 サンプルまで 用意されてる」

📖 .NET MAUI Localization Sample

202307_maui_09-2032--sample.png

ramen-tabero-futsu2.png
「 👆 サンプルは動くが、どうやって 📂 Languages フォルダーを作ったのか
手順が分からんな」

ramen-tabero-futsu2.png
「 👇 ResXManager は 多言語化の鉄板ソフトなんで インストールしておこうぜ」

📖 ResXManager

ramen-tabero-futsu2.png
「 しかし ResXManager の画面は どこから出すんだぜ?」

202307_maui_09-2054--resource-o2o0.png

ramen-tabero-futsu2.png
「 👆 このリンク クリックしたら 何か出てくるかな?」

202307_maui_09-2056--resx-o2o0.png

ramen-tabero-futsu2.png
「 👆 昔ながらの場所に作られたが、そこじゃなくて
📂 Resources/Languages フォルダ―の下に置いてほしいんだぜ」

202307_maui_09-2114--sample-o2o0.png

ramen-tabero-futsu2.png
「 👆 サンプル見ると、単に ファイルを移動しただけに見えるな……
やってみるか」

202307_maui_09-2121.png

ramen-tabero-futsu2.png
「 👆 自動で ネームスペースも調整してくれるのかな?」

202307_maui_09-2123--AppResources.png

ramen-tabero-futsu2.png
「 👆 ファイル名も Resources から AppResources に変えたろ」

202307_maui_09-2330--Localization.png

ramen-tabero-futsu2.png
「 👆 LocalizationResourceManager クラスを真似して 自分用に設定」

202307_maui_09-2346--init-o2o0.png

ramen-tabero-futsu2.png
「 👆 アプリケーション起動直後に 文化を日本に設定。
わたしが日本語しか確認しないから 日本がデフォルトでいいだろ」

202307_maui_09-2357--translate.png

ramen-tabero-futsu2.png
「 👆 TranslateExtension も真似て作り、自分に合わせて編集」

202307_maui_10-0002--instance-o2o0.png

ramen-tabero-futsu2.png
「 👆 ビューのコード・ビハインド、つまり ContentPage の継承クラスには
ローカライゼーション資源管理へのアクセッサ―を書いておくぜ」

202307_maui_10-0010--layoutTheScreen-o2o0.png

ramen-tabero-futsu2.png
「 👆 とりあえず AppResources.resx へ、 1件だけ 文字列リソースを 記入するぜ」

202307_maui_10-0014--translate-o2o0.png

ramen-tabero-futsu2.png
「 👆 MainPage.xamlxmlns:app="~" を追加し、
Text プロパティへ {app:Translate LayoutTheScreen} と書いてみるぜ」

202307_maui_10-0017--home-o2o0.png

ramen-tabero-futsu2.png
「 👆 実行すると、文字列リソースが 使われているな」

ohkina-hiyoko-futsu2.png
「 カルチャーを変更するドロップダウン・リストみたいなものが欲しいわねえ」

外国語を入力してくれだぜ

kifuwarabe-futsu.png
「 試しに 英語と 中国語のリソースも 作ってみてくれだぜ」

202307_maui_10-0029--resxmanager-o2o0.png

ramen-tabero-futsu2.png
「 👆 ResXManager がインストール済みなのは確認できるんだが、
どこから実行するんだぜ?」

202307_maui_10-0033--tool-resxmanager-o2o0.png

ramen-tabero-futsu2.png
「 👆 あっ、いた!」

202307_maui_10-0036--open-resxmanager.png

ramen-tabero-futsu2.png
「 👆 ここまでくると あとは わかる」

202307_maui_10-0040--neutral-language-o2o0.png

ramen-tabero-futsu2.png
「 👆 ニュートラル・リソース・ランゲージを 英語から 日本語へ 変えるぜ。
理由は 開発者が わたし1人だから」

kifuwarabe-futsu.png
「 悲しい話しだぜ」

202307_maui_10-0045--add-new-language-o2o0.png

ramen-tabero-futsu2.png
「 👆 言語を追加するボタンがあるぜ」

202307_maui_10-0049--en-US-o2o0.png

ramen-tabero-futsu2.png
「 👆 とりあえず イーエヌ・ユーエス(en-US;英語(米国))は 必須だろ」

202307_maui_10-0054--add-languages-o2o0.png

ramen-tabero-futsu2.png
「 👆 とりあえず 3つも足しておけば十分だろ」

kifuwarabe-futsu.png
「 アジアに寄ってんな」

202307_maui_10-0059--translation-o2o0.png

ramen-tabero-futsu2.png
「 👆 ばばばっと 翻訳して 空いてるとこ 埋めてくれる機能があるから
使おうぜ?」

202307_maui_10-0105--translation.png

ramen-tabero-futsu2.png
「 👆 なぜか 英語しか 対応してくれなかった。 寄付が足りないとか?」

202307_maui_10-0108--en-US-o2o0.png

kifuwarabe-futsu.png
「 👆 AppResources.en-US.resx ファイルが増えてるぜ」

202307_maui_10-0116--culture-o2o0.png

ramen-tabero-futsu2.png
「 👆 ISO言語コードを変えると」

202307_maui_10-0118--us-o2o0.png
ramen-tabero-futsu2.png
「 👆 翻訳が完了だぜ」

ohkina-hiyoko-futsu2.png
「 📂 Languages フォルダーの中をサーチして、翻訳できる言語を調べて
言語を選べるリスト・ボックスが欲しいわねえ」

ramen-tabero-futsu2.png
「 そのフォルダーに アクセスする方法が 見当つかないんだが」

202307_maui_10-0138--resources-o2o0.png

ramen-tabero-futsu2.png
「 👆 実行環境を見にいってしまうので、開発環境のプロジェクト・フォルダーの中とか見れないのでは?」

ohkina-hiyoko-futsu2.png
「 👇 じゃあ ビルド前のイベント を書いたらいいんじゃない?」

202307_maui_10-0143--event-before-build-o2o0.png

📖 Pre build Events in Visual Studio

ramen-tabero-futsu2.png
「 そこで ベッタリ Windows 依存しそうだしな」

kifuwarabe-futsu.png
「 じゃあ ISO言語コードは ハード・コーディングかな」

ohkina-hiyoko-futsu2.png
「 国旗って フリー素材であるの?」

kifuwarabe-futsu.png
「 👇 同じ問題に突き当たっている人がいるぜ」

📖 Is there a way to get a flag image from a C# CultureInfo?

kifuwarabe-futsu.png
「 👇 WPF で作った人はいるみたいだな」

📖 famfamfam-flags-wpf

ramen-tabero-futsu2.png
「 こういう センシティブな素材は デジタル庁 が作って欲しいものだぜ」

ramen-tabero-futsu2.png
「 国旗は後回しにし、ISO言語コードのドロップダウン・リストを
ハードコーディングする方向で 次回 考えようぜ?」

📅 (2023-07-10 mon)日本語か、英語かを選べるドロップダウン・リストボックスを置いてくれだぜ

kifuwarabe-futsu.png
「 日本語か、英語かを選べるドロップダウン・リストボックスを置いてくれだぜ」

ramen-tabero-futsu2.png
「 まず MAUI に ドロップダウン・リストボックスがあるのかどうかも 分からないしな。
調べないとな」

ramen-tabero-futsu2.png
「 👇 マイクロソフトの記事、映像がなくて どんな画面が出てくるのか 分からん」

📖 Microsoft > Picker

ohkina-hiyoko-futsu2.png
「 👇 ユーチューブで探せばいいのよ」

📺 How To Create Custom Picker Control (Dropdown Button) In .NET MAUI

ramen-tabero-futsu2.png
「 👇 作ってみるのが早いか」

📖 ピッカー

202307_maui_10-2234--picker-o2o0.png

ramen-tabero-futsu2.png
「 👆 こう書けば」

202307_maui_10-2237--picker-appear-o2o0.png

ramen-tabero-futsu2.png
「 👆 ドロップダウン・リストボックスが出てきて……」

202307_maui_10-2238--picker-select-o2o0.png

ramen-tabero-futsu2.png
「 👆 選べるぜ」

ohkina-hiyoko-futsu2.png
「 それが欲しかったのよ」

kifuwarabe-futsu.png
「 初期状態で ja-JP を選んでおいてくれだぜ」

202307_maui_10-2245--picker-initial-o2o0.png

ramen-tabero-futsu2.png
「 👆 ピッカーに 最初に選択されている値を表示することは できないぜ」

kifuwarabe-futsu.png
「 じゃあ、値が最初に選択されていることを ピッカーでどう表現するんだぜ?」

ramen-tabero-futsu2.png
「 マイクロソフトの社員の知能が欠如していて それはできないぜ」

ohkina-hiyoko-futsu2.png
「 👇 初期値を表示するのって HTML の Select タグの Option 要素の Selected 属性でも指定できるのに、
MAUI で 何でできないの?」

📖 HTML selected Attribute

ramen-tabero-futsu2.png
「 マイクロソフトの社員が欠陥だからだぜ」

ohkina-hiyoko-futsu2.png
「 マイクロソフトの社員が欠陥だというところまでは 事実と認めましょう。
それは置いておいて わたしたちは ピッカーに初期値を表示したいのよ。どうしたらいいのよ?」

kifuwarabe-futsu.png
「 ピッカーを使ってはいけないのでは?」

202307_maui_10-2259--loaded-o2o0.png

ramen-tabero-futsu2.png
「 👆 ContentPage 要素に Loaded 属性を追加して……」

202307_maui_10-2301--code-behind-o2o0.png

ramen-tabero-futsu2.png
「 👆 コード・ビハインドで picker.SelectedItem = "ja-JP"; とでも書いておけば……」

202307_maui_10-2303--picker-initial-o2o0.png

ramen-tabero-futsu2.png
「 👆 ページの表示完了時には ピッカーで ja-JP が選択されている、という状態にできるぜ」

kifuwarabe-futsu.png
「 XAML だけでは モックアップも作れないんだな」

ohkina-hiyoko-futsu2.png
「 MVVM に対応できんの?」

ramen-tabero-futsu2.png
「 トップページは MVVM にまだ対応してないんで、これから対応させるぜ」

(カタ カタ カタ カタ)

kifuwarabe-futsu.png
「 あの 1.5日 ぐらい 工数かかったやつ」

ramen-tabero-futsu2.png
「 でけた。 さっきのイベントハンドラも コード・ビハインドも要らんかった。
MVVM だけでいけるぜ」

202307__maui__11-0117--translate.gif
kifuwarabe-futsu.png
「 マイクロソフトの社員は欠陥じゃなかったんだな」

ramen-tabero-futsu2.png
「 まだ 首の皮一枚つながったぐらいだな」

📅 (2023-07-10 mon)タイル・パレット編集画面も多言語化しなさいよ

ohkina-hiyoko-futsu2.png
「 タイル・パレット編集画面も多言語化しなさいよ」

ramen-tabero-futsu2.png
「 あとから 多言語化しようとして レイアウトの変更が必要になったりしたら 大変だしな」

202307__maui__11-1921--item-source-o2o0.png

ramen-tabero-futsu2.png
「 👆 この アイテム・リソースも ハード・コーディングじゃなくて
どこかのファイルにまとめて、一元化したいんだが」

kifuwarabe-futsu.png
「 App.xaml に リソース・ディクショナリーを作って、それを読み込んだらどうだぜ?」

ramen-tabero-futsu2.png
「 👇 テンプレートは リソースにできるが、 データは リソースにできないんじゃないか?」

📖 データ テンプレート
📖 リソース ディクショナリ

ramen-tabero-futsu2.png
「 ItemSource の使い方が分からん。調べても出てこないぜ」

ohkina-hiyoko-futsu2.png
「 この前の多言語化のときの おっさんの You Tube に なんか まとまってんじゃないの?」

kifuwarabe-futsu.png
「 👇 このおっさんは MAUI を作ったチームの中の人らしいぜ」

📺 Gerald Versluis

ramen-tabero-futsu2.png
「 じゃあ その動画を しばらく視聴する!」

📅 (2023-07-11 tue)寝てた

Zzz

📅 (2023-07-12 wed)動画観るか~

ramen-tabero-futsu2.png
「 動画 観るか~」

📅 (2023-07-13 thu)分かんね

ramen-tabero-futsu2.png
「 👇 英語で 何言ってるか 分かんないんだが」

📺 Monkey クラス作成

ohkina-hiyoko-futsu2.png
「 猿を1匹記録するクラスを作るんだけど、例が JSON なのよ」

ramen-tabero-futsu2.png
「 じゃあ 真似して 言語を1つ記録するクラスを作るかだぜ」

202307__maui__13-2019--languagesCSV-o2o0.png

Name,
ja-JP,
en-US,

ramen-tabero-futsu2.png
「 👆 📂 Releases/Raw フォルダーの中に 📄 languages.csv ファイルを作ろうぜ?」

ohkina-hiyoko-futsu2.png
「 その1行に対応する Language クラスを 📂 Models フォルダーの下に作りましょう」

kifuwarabe-futsu.png
「 なんか無駄臭いクラスだな……」

202307__maui__13-2030--languageBuffer-o2o0.png

ramen-tabero-futsu2.png
「 👆 プロパティ1個 置いとけばいいのかだぜ?」

kifuwarabe-futsu.png
「 C# に、 CSV をシリアライズする仕組みなんか あるのかだぜ?」

ohkina-hiyoko-futsu2.png
「 👇 人気があるのは これかしらねえ?」

📖 CsvHelper

ramen-tabero-futsu2.png
「 使い方を覚えるか……」

202307__maui__13-2044--CsvHelper.png

ramen-tabero-futsu2.png
「 👆 NuGET でインストール」

ramen-tabero-futsu2.png
「 Resources/Raw フォルダーの中にあるファイルって どうやって読取るんだぜ?」

kifuwarabe-futsu.png
「 👇 調べろだぜ」

📖 Microsoft > Bundled Files
📖 Get Resources\Raw Path in .NET Maui

202307__maui__13-2118--csvProj-o2o0.png

ramen-tabero-futsu2.png
「 👆 None とか Remove って何だぜ? 無いことになってんの?」

202307__maui__13-2127--buildAction-o2o0.png

ramen-tabero-futsu2.png
「 👆 ビルド・アクションを何か変えたらいいのかだぜ?」

kifuwarabe-futsu.png
「 👇 ビルド・アクションの説明はこれだが」

📖 Build actions

ramen-tabero-futsu2.png
「 CSVファイルは どう配置すりゃいいんだぜ?」

202307__maui__13-2214--copy-o2o0.png
ramen-tabero-futsu2.png
「 👆 出力ディレクトリーにコピー を 新しい場合はコピーする に変えたら、何が起こるんだぜ?」

202307__maui__13-2223--output.png

ramen-tabero-futsu2.png
「 👆 なんで2つあるんだ?」

ramen-tabero-futsu2.png
「 コピーをしなければ bin フォルダーの下に languages.csv はなく、コピーすると2つある」

ohkina-hiyoko-futsu2.png
「 Visual Studio のコンフィグ・ファイルは無いの?
インストール時に 作業ディレクトリーを設定できなければ、
設定ファイルの置き場所も 定まらなくない?」

kifuwarabe-futsu.png
「 アプリケーション・フォルダーに置いてくれないのかだぜ?」

ItemSource 分からん

ramen-tabero-futsu2.png
「 じゃあ いったん、言語のリストは ハード・コーディングするものとしようぜ?」

ohkina-hiyoko-futsu2.png
「 ItemSource って 何を設定できるの?」

ramen-tabero-futsu2.png
「 恐らく、ビューモデルの 変更通知プロパティじゃないか?」

202307__maui__13-2253--localeIdList-o2o0.png

ramen-tabero-futsu2.png
「 👆 変更通知プロパティを ふつうに作って」

202307__maui__13-2317--languagePicker-o2o0.png

ramen-tabero-futsu2.png
「 👆 ItemSource に バインドすれば うまくいくぜ」

ohkina-hiyoko-futsu2.png
「 どのページにも 言語ピッカー を置きたいときは、
どのページにも LanguageCollection 変更通知プロパティーを作ることになるの?」

ramen-tabero-futsu2.png
「 そうじゃないか?」

202307__maui__13-2327--localeIdCollection-o2o0.png

ramen-tabero-futsu2.png
「 👆 ロケールIdのリストなんか 途中で変わらないだろ。
セッターのないプロパティとして、グローバル変数のように利用できるように App クラスに定義しようぜ?」

202307__maui__13-2329--localeIdCollectionProperty-o2o0.png

ramen-tabero-futsu2.png
「 👆 変更できない変更通知プロパティなら、グローバル変数を取得してても 不整合は起こらないだろ」

kifuwarabe-futsu.png
「 これを ビューモデルに置きまくるのか」

配色変更

202307__maui__14-0022--color.png
ramen-tabero-futsu2.png
「 👆 テキストボックスの白が目立つように 配色を変更し、
ロケールIdのピッカーを 右上に置いたぜ」

ohkina-hiyoko-futsu2.png
「 色を使いすぎてんじゃないの? 青だけでも3色もある」

ramen-tabero-futsu2.png
「 タイトルバーの色を 減らしてみるか……」

ramen-tabero-futsu2.png
「 MAUI のスタイルシート的なものは どこにあんの?」

202307__maui__14-0035--style-o2o0.png

kifuwarabe-futsu.png
「 👆 📂 Resources/Styles フォルダーの下にあるぜ」

202307__maui__14-0052--style.png

ramen-tabero-futsu2.png
「 👆 色の主張を 抑えたぜ」

ohkina-hiyoko-futsu2.png
「 テキストボックスの白と黒も きつい 気がするのよね」

202307__maui__14-0121--colors.png

ramen-tabero-futsu2.png
「 👆 ダーク・モードのことを考えずに いじってしまった。
どこか 壊してしまったかも知れないが 分からない。
勘弁しろだぜ」

202307__maui__14-0130--top-page-style.png

ramen-tabero-futsu2.png
「 👆 トップページの配色も 白が無くなるように ゲインズボロ という色をベースに敷いたが
ダークモードにしたら どうなるのか 知らん」

ramen-tabero-futsu2.png
「 もう寝ろ」

📅 (2023-07-14 fri)登録済みタイルがどれか分かるようにしてくれだぜ

kifuwarabe-futsu.png
「 登録済みタイルがどれか分かるようにしてくれだぜ。 例えば……」

202307__maui__14-2002--selected-tiles.png

kifuwarabe-futsu.png
「 👆 こんなふうに」

ramen-tabero-futsu2.png
「 タイルは 重なって登録されることは あるのかだぜ? 例えば……」

202307__maui__14-2006--selected-tiles.png

ramen-tabero-futsu2.png
「 👆 上図 4~9」

ohkina-hiyoko-futsu2.png
「 あるある。 タイル・セットは それ自体が パレットのような配置をしているのよ」

ramen-tabero-futsu2.png
「 タイル・セットと パレットは 意義を分けたいな……」

202307__maui__14-2014--selected-tile-atoms.png

ramen-tabero-futsu2.png
「 👆 ロジカルには こうなるはず」

ohkina-hiyoko-futsu2.png
「 上図の 7 を範囲選択するの 難しくない?」

ramen-tabero-futsu2.png
「 ゲリマンダー(Gerrymander)みたいな形や、飛び地が必要かどうかも 洗い出したいぜ」

kifuwarabe-futsu.png
「 ひとまず 矩形だけでいいのではないか?」

ramen-tabero-futsu2.png
「 じゃあ 被りは有りで 話しを進めるかだぜ」

202307__maui__14-2049--debug-o2o0.png

ramen-tabero-futsu2.png
「 👆 なんか ファイルにいっぱい保存されているぜ」

ohkina-hiyoko-futsu2.png
「 同じ矩形を 何個も登録してるわねえ」

kifuwarabe-futsu.png
「 ファイルのバリデーターを作るべきだが、とりあえず 手作業で直せだぜ」

202307__maui__14-2055--excel.png

ramen-tabero-futsu2.png
「 👆 Excel で CSVファイルを開いたら 文字化けしてるんだが……」

ohkina-hiyoko-futsu2.png
「 BOM付きの UTF-8 じゃないと Shift-JIS と判定されてるわよ」

202307__maui__14-2058--excel-bom.png

ramen-tabero-futsu2.png
「 👆 BOM 付きの UTF-8 にしたら 文字化けが直った!」

202307__maui__14-2101--excel-id.png

ramen-tabero-futsu2.png
「 👆 こういう感じのデータを、エディター上で どう表示するかだよな」

IDrawableインターフェース実装クラスの Draw関数にビューモデルからどうやって値を渡すんだぜ?

202307__maui__14-2105--idrawable-o2o0.png

ramen-tabero-futsu2.png
「 👆 IDrawableインターフェース実装クラスの Draw関数にビューモデルからどうやって値を渡すんだぜ?」

kifuwarabe-futsu.png
「 👇 これを読めだぜ」

📖 In .NET MAUI, how do I pass variables to a GraphicsView.Drawable in a ContentView
📖 How to pass variable data into .NET MAUI GraphicsView canvas

202307__maui__14-2123--bindableProperty-o2o0.png

ramen-tabero-futsu2.png
「 👆 なんだか分からないが 束縛可能プロパティ の書き方のパターンを なぞろうぜ」

202307__maui__14-2128--tile-set-drawing-o2o0.png

ramen-tabero-futsu2.png
「 👆 さっきの IDrawing 実装クラスは、リソースとして ContentPage に読み込まれて……」

202307__maui__14-2131--graphics-view-o2o0.png

ramen-tabero-futsu2.png
「 👆 GraphicsView 要素で使われているな」

202307__maui__14-2141--drawable-o2o0.png

ramen-tabero-futsu2.png
「 👆 それを いったん、こう書きかえるぜ」

ohkina-hiyoko-futsu2.png
「 これでいいなら ビュー・モデルの変更通知プロパティを、
IDrawable クラスの束縛可能プロパティに 渡すことができそうねえ」

202307__maui__14-2147--propertyChanged-o2o0.png

ramen-tabero-futsu2.png
「 👆 ビュー・モデルに 変更通知プロパティを書いて……」

202307__maui__14-2149--view-binding-o2o0.png

ramen-tabero-futsu2.png
「 👆 ビューで 変更通知プロパティを束縛」

202307__maui__14-2151--binding-o2o0.png

ramen-tabero-futsu2.png
「 👆 IDrawing 実装クラスは 束縛可能プロパティに値が入ってくるんで
グローバル変数を1つ 取り除くことに成功だぜ」

ohkina-hiyoko-futsu2.png
「 IDrawing 実装クラスから グローバル変数を取り除いていきましょう!」

ramen-tabero-futsu2.png
「 つら……」

(カタ カタ カタ カタ)

ramen-tabero-futsu2.png
「 ヌル参照例外が出て 動かなくなった つら……」

ramen-tabero-futsu2.png
「 さらに まずいことに 線の太さが 0 になり、
for 文で 横に 0 移動しながら 縦線を引く 無限ループに陥った……」

kifuwarabe-futsu.png
「 束縛プロパティの初期化が始まる前に Draw メソッドが呼び出されているのでは?」

ramen-tabero-futsu2.png
「 どっちが頭で どっちが尻尾問題で、
IDrawable 実装クラスのプロパティが、ビュー・モデルのプロパティーを上書きしてくることはないだろうか?」

ohkina-hiyoko-futsu2.png
「 Way を指定したらいいんじゃないの?」

202307__maui__14-2328--sync-o2o0.png

ramen-tabero-futsu2.png
「 👆 そもそも 変更通知が届いてないぜ」

kifuwarabe-futsu.png
「 グローバル変数が いつ変更されたとか、ビューモデルには 分からないからな」

ramen-tabero-futsu2.png
「 グローバル変数を 使わないようにしたが、束縛プロパティが 渡せていないぜ」

束縛プロパティを練習しようぜ?

kifuwarabe-futsu.png
「 👇 GraphicsViewDrawable クラスの Draw 変数へ、プロパティを渡すだけのサンプル・プログラムを組んでみようぜ?」

📖 Git Hub > Muzudho > MAUI-BindableProperty-Practice

202307__maui__15-0157--practice.png

ramen-tabero-futsu2.png
「 👆 しばらく 練習するぜ」

202307__maui__15-0209--binding-o2o0.png

ramen-tabero-futsu2.png
「 👆 Binding したら 動かないぜ」

ohkina-hiyoko-futsu2.png
「 Bindable なプロパティなのに Binding したら動かないなんてことが あるのかしら?」

kifuwarabe-futsu.png
「 👇 よく読んでくれだぜ」

📖 Bindable properties

202307__maui__15-0216--onBinding-o2o0.png

ramen-tabero-futsu2.png
「 👆 確かに 変更前と、変更後の値を取れて 気が利くが、
そういうの 自動でやってくれるわけじゃないのかだぜ?」

ramen-tabero-futsu2.png
「 いや、取れてないぜ。 Binding したものは 取れてない」

kifuwarabe-futsu.png
「 👇 もっと調べろだぜ」

📖 Binding not working on custom BindableProperty

ramen-tabero-futsu2.png
「 GraphicsView はビュー・モデルを持ってないから Simple30Binding しようとしても持ってないんで、
親コンポーネントのビュー・モデルを指せ、ということらしい」

ramen-tabero-futsu2.png
「 どうやって」

kifuwarabe-futsu.png
「 👇 もっと調べろだぜ」

📖 .NET Maui Binding a contentview to parent ViewModel MVVM
📖 ContentView

ramen-tabero-futsu2.png
「 ContentPage 使ってるのに、 ContentView の説明されても 利用できないぜ」

(カタ カタ カタ カタ)

ramen-tabero-futsu2.png
「 よし、分かった!

202307__maui__15-0255--openBindingContext-o2o0.png

ramen-tabero-futsu2.png
「 👆 ビューの コード・ビハインドに、
バインディング・コンテキストを公開する パブリック・メソッドを書くぜ」

kifuwarabe-futsu.png
「 そんなことをしていいのかだぜ?」

ohkina-hiyoko-futsu2.png
「 MVVMが 崩壊したんじゃないの?」

202307__maui__15-0258--contentPage-o2o0.png

ramen-tabero-futsu2.png
「 👆 ビューの ContentPage 要素に、 x:Name 属性を付けて、その値を thisContentPage とでもしておくぜ」

202307__maui__15-0300--bindingContext-o2o0.png

ramen-tabero-futsu2.png
「 👆 これで MainPageVM プロパティが公開されてるんで、そのメンバーにアクセスできるぜ」

kifuwarabe-futsu.png
「 この記事の 2回目の トリック・コードだな」

202307__maui__15-0304--viewModel.png

ramen-tabero-futsu2.png
「 👆 ViewModel はこんな感じ」

202307__maui__15-0305--drawLine.png

ramen-tabero-futsu2.png
「 👆 線も引けてるぜ」

ohkina-hiyoko-futsu2.png
「 バインディング・コンテキストを公開しているのが 気になるなあ」

202307__maui__15-0325--bugFix.png

ramen-tabero-futsu2.png
「 👆 グローバル変数を減らし、 BindableProperty を使って GraphicsCanvas の Drawable 属性のクラスの
Draw メソッドに プロパティ値を渡すことに成功したぜ」

kifuwarabe-futsu.png
「 ViewModel を public にするのは心理的抵抗がある。
公開するのは interface にして、プロパティだけ公開しろだぜ」

ramen-tabero-futsu2.png
「 かしこいな」

📅 (2023-07-15 sat)タイル・セット上を矩形で塗りつぶしてくれだぜ

kifuwarabe-futsu.png
「 タイル・セット上を矩形で塗りつぶしてくれだぜ」

ramen-tabero-futsu2.png
「 キャンバスで描画するのか、画像オブジェクトでピクセルを直接描画するのがいいのか」

ohkina-hiyoko-futsu2.png
「 インプレース(In-place)で クロップ(Crop)と コピー(Copy)を1ステップでできないと
実行速度が遅くなるんじゃないの?」

ramen-tabero-futsu2.png
「 画像は Microsoft.Maui.Graphics.IImage というインターフェースに抽象化されていて、
とても 高速に画像を描画することを指向しておらず、
マルチ・プラットフォームで一番性能の低いマシンで動くように考慮されてる護送船団方式の雰囲気を感じるぜ」

kifuwarabe-futsu.png
「 性能 上げたけりゃ MAUI なんか使うなだぜ」

ramen-tabero-futsu2.png
「 ぐぬぬぬぬ!」

ramen-tabero-futsu2.png
「 この IImage インスタンスは あくまで 画像ファイルを指さしているだけで、
描画をするときは GraphicsCanvas を使えという思想なのかもしれない」

ohkina-hiyoko-futsu2.png
「 画面の描画前に 画像の前処理を 終わらせておきたいことなんて
いっぱいあると思うのに
キャンバスを用意してから 画像処理しなくちゃいけないのね」

kifuwarabe-futsu.png
「 画像処理 したけりゃ MAUI なんか使うなだぜ」

ohkina-hiyoko-futsu2.png
「 ふむむむむ!」

ramen-tabero-futsu2.png
「 じゃあ 画面上に キャンバスを2層に重ねて表示することにして、
元画像を下レイヤーに、作業用レイヤーを上レイヤーに置いて
作業用レイヤーに いろんな加工をしていくことにしようぜ?」

ohkina-hiyoko-futsu2.png
「 キャンバスの練習を先にしておいた方が いいんじゃない?」

kifuwarabe-futsu.png
「 👇 リポジトリ―は作っておいたぜ」

📖 GitHub > Muzudho > MAUI-IDrawable-Practice

ramen-tabero-futsu2.png
「 変更通知プロパティを バインディング しただけでは
Draw は呼び出されないのか」

ramen-tabero-futsu2.png
「 GraphicsView に Draw メソッドの呼び出しを要求するの、どうやればいい?」

kifuwarabe-futsu.png
「 👇 読めだぜ」

📖 GraphicsView

202307__maui__15-1635--graphicsView-o2o0.png

ramen-tabero-futsu2.png
「 👆 GraphicsView 要素に x:Name 属性を使って名前を付けて……」

202307__maui__15-1637--Invalidate-o2o0.png

ramen-tabero-futsu2.png
「 👆 コード・ビハインドで GraphicsView 要素の Invalidate( ) メソッドを呼び出せば いいわけかだぜ」

ramen-tabero-futsu2.png
「 ビューモデルで Invalidate( ) メソッドは呼び出せないのかだぜ?」

kifuwarabe-futsu.png
「 画面の更新は ビューモデルの仕事では 無いのでは」

202307__maui__15-1651--Drawing.png
ramen-tabero-futsu2.png
「 👆 よっしゃ 2D描画にも 慣れてきたぜ」

1つのキャンバスで何でも描画するのと、複数のキャンバスに分けるの、どっちが得?

kifuwarabe-futsu.png
「 お父んは タイル・カーソルと グリッドと タイル・セット画像を 分けて 置いているが、
そのようにするのと、1つのキャンバスの上に全部描くのとでは、どっちが得なんだぜ?」

ramen-tabero-futsu2.png
「 何も考えなければ 1つのキャンバスの上に全部描くのが お得だぜ」

ohkina-hiyoko-futsu2.png
「 グリッドを分けた理由は?」

ramen-tabero-futsu2.png
「 グリッドは ヴィジブル(Visible;可視性)を オン・オフ したいときがあるだろ。
フラグ1個だけで できるというメリットを生かしたい」

kifuwarabe-futsu.png
「 ライフ・サイクルに似た考え方か」

ohkina-hiyoko-futsu2.png
「 じゃあ カラード・マップ(Colored Map)のキャンバスも 1つ用意したいわねえ」

Draw が呼び出されるのが Loaded より早い

ramen-tabero-futsu2.png
「 GraphicsView の初期設定をする前に Draw が呼び出されているぜ」

ramen-tabero-futsu2.png
「 👇 イベントの呼び出し順序の話しは 書いてないなあ」

📖 グラフィカル オブジェクトを描画する

ramen-tabero-futsu2.png
「 あっ、違うぜ」

ramen-tabero-futsu2.png
「 束縛プロパティの 返り値の型の指定を 間違えていた」

kifuwarabe-futsu.png
「 設定ミスは エラー・メッセージを出してくれないからなあ」

202307__maui__15-1826--GrayRectangle.png

ramen-tabero-futsu2.png
「 👆 薄いグレーを被せてみたが、
どうやっても 視認性が悪くならないか?」

ohkina-hiyoko-futsu2.png
「 もとの画像の 明度を下げてみたら?」

ramen-tabero-futsu2.png
「 👇 明度を下げるとか 上げるとか 説明無いぜ?」

📖 Microsoft > Image

ramen-tabero-futsu2.png
「 ピクセルに アクセスする手段 無いの?」

kifuwarabe-futsu.png
「 👇 スキア・シャープ(Skia Sharp)というものが あるそうだぜ?」

📖 .Net Maui - Create ImageSource from pixel data

ramen-tabero-futsu2.png
「 何だぜ それ まだまだ勉強か……」

SkiaSharp を調べようぜ?

kifuwarabe-futsu.png
「 👇 リポジトリは作っておいたぜ、勉強しろ」

📖 GitHub > Muzudho > MAUI-SkiaSharp-Practice

202307__maui__15-1917--SkiaSharp.png

ramen-tabero-futsu2.png
「 👆 とりあえず SkiaSharp をインストールするか」

ramen-tabero-futsu2.png
「 👇 スキア・シャープの使い方の説明が無いぜ」

📖 GitHub > SkiaSharp

kifuwarabe-futsu.png
「 👇 サンプル・プログラムを直接読めだぜ」

📖 SkiaSharp/samples/Basic/Maui/SkiaSharpSample/MainPage.xaml.cs

ramen-tabero-futsu2.png
「 GraphicsView じゃないんだ」

ramen-tabero-futsu2.png
「 👇 画像処理っぽいことしてるが、学習コストが高そうだ」

📖 Understanding SkiaSharp and Maui Coordinates

kifuwarabe-futsu.png
「 👇 ここに ピクセル単位でのアクセスの仕方が書いてあるのでは?」

📖 SkiaSharp ビットマップ ピクセル ビットへのアクセス

ramen-tabero-futsu2.png
「 まあ、午前中に独習してきた GraphicsView は使わないというのは 分かったが……

ohkina-hiyoko-futsu2.png
「 将来的にやろうとしていることを考えると、 GraphicsView では限界がくるんじゃない?」

202307__maui__15-1950--SkiaSharpViews.png

ramen-tabero-futsu2.png
「 👆 SkiaSharp.Views.Maui.Controls をインストールしてみようぜ?」

202307__maui__15-1956--namespace-o2o0.png

ramen-tabero-futsu2.png
「 👆 xml の namespace として
xmlns:skia="clr-namespace:SkiaSharp.Views.Maui.Controls;assembly=SkiaSharp.Views.Maui.Controls"
を書き足すぜ」

202307__maui__15-2009--skCanvasView--o2o0.png

ramen-tabero-futsu2.png
「 👆 これで skia:SKCanvasView を使えるようになったはずだぜ」

ramen-tabero-futsu2.png
「 使えなかった。エラーが出た」

ohkina-hiyoko-futsu2.png
「 👇 SkiaSharp.Views.Maui.Core はインストールしてんの?」

📖 SkiaSharp.Views.Maui.Core

202307__maui__15-2050--skiaSharpViews.png

ramen-tabero-futsu2.png
「 👆 どれをインストールすりゃいいのか 分からんな」

ramen-tabero-futsu2.png
「 👇 コマンドラインからやってみるか」

📖 SkiaSharp.Views.Maui.Core

dotnet add package SkiaSharp.Views.Maui.Core --version 2.88.3

202307__maui__15-2112--command-o2o0.png

202307__maui__15-2115--mojibake.png

ramen-tabero-futsu2.png
「 👆 なぜ文字化けする?」

.NET Core の文字化けに対応しろ

ramen-tabero-futsu2.png
「 👇 ダメ元で 試してみるか」

📖 .NET Coreのコンソールで日本語が文字化けする

        // NuGET のパッケージ・マネージャー・コンソールの文字化けに対応を期待したが効果なし
        Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);

ramen-tabero-futsu2.png
「 👆 ダメだった」

📖 パッケージマネジャコンソールにおける dotnet コマンド出力の文字化け

dotnet --help

ramen-tabero-futsu2.png
「 👆 ヘルプも文字化けしている」

PM> chcp
現在のコード ページ: 932

ramen-tabero-futsu2.png
「 👆 マイクロソフトの S-JIS ではダメだ」

PM> chcp 65001
Active code page: 65001

ramen-tabero-futsu2.png
「 👆 コードページを 65001 に変えたったが ダメだ」

マイクロソフトのスキアを入れてみようぜ?

202307__maui__15-2137--microsoftMauiGrahicsSkia.png

ramen-tabero-futsu2.png
「 👆 方法も無いし、 Microsoft.Maui.Graphics.Skia でもインストールしてみようぜ?」

kifuwarabe-futsu.png
「 もう 思考が停止してるの わらう」

ramen-tabero-futsu2.png
「 インストールしたところで 何も起こらん」

ohkina-hiyoko-futsu2.png
「 思考をしなさい!」

キャンバスではなく、イメージの方を調べようぜ?

ramen-tabero-futsu2.png
「 👇 描画回りは 対応が遅れてるのかも知らん」

📖 .NET MAUIによるクロスプラットフォーム2D描画(その1)

kifuwarabe-futsu.png
「 👇 MAUI は SkiaSharp をベースに使ってるんだろう」

📖 SkiaCanvas Class

ohkina-hiyoko-futsu2.png
「 👇 キャンバスではなく、イメージの方に ピクセルにアクセスするメソッドがあるんじゃないの?」

📖 SkiaImage Class

202307__maui__15-2205--asBytes.png

ramen-tabero-futsu2.png
「 👆 イメージは バイトに分解できるのか」

ramen-tabero-futsu2.png
「 じゃあ バイトは イメージに 構成できるのかだぜ?」

kifuwarabe-futsu.png
「 👇 調べろだぜ」

📖 ByteArrayToImageSourceConverter
📖 MAUI: How to draw image from byte[] on MAUI

ramen-tabero-futsu2.png
「 画像は バイトに分解できるけど、 バイトは 画像に構成できないのか」

ohkina-hiyoko-futsu2.png
「 👇 じゃあ バイト配列を 直に PNG画像として出力すればいいんじゃないの?」

📖 Create a PNG from an array of bytes

ramen-tabero-futsu2.png
「 ファイルの書出しと 読込みたいな 重い処理やるんだったら なんのための画像処理か 分からんが……」

kifuwarabe-futsu.png
「 MAUI で画像処理しようとするのが 間違いなのでは?」

アホな記事ばかり

ramen-tabero-futsu2.png
「 👇 公式の記事を なぞってるだけじゃないか。アマチュアのコピー記事が」

📖 Handling Images With .NET MAUI Graphics

kifuwarabe-futsu.png
「 真実に対して 怒るなだぜ」

ramen-tabero-futsu2.png
「 明度を下げたいとか、特定の色だけを抽出したいとか、そういう知能はないのかだぜ、記事を書くやつは?
知能だけではない 意志も無い。
インターネット上のアマチュア記事は 公式のダウングレードばかり 情報を増やさない。
筆を折れだぜ」

ohkina-hiyoko-futsu2.png
「 スキアシャープのエラーを取るしかなくない?」

再び SkiaSharp を調べようぜ?

202307__maui__15-2245--skia.png

ramen-tabero-futsu2.png
「 👆 とりあえず、NuGET で 正しい SkiaSharp をパッケージ単位でダウンロードして
アセンブリを使えるようにするところからだぜ」

202307__maui__15-2257--skiaSharp.png

ramen-tabero-futsu2.png
「 👆 だから この SkiaSharp パッケージを入れておくだけで 充分なはずなんだが」

202307__maui__15-2259--skiaSharpError.png

ramen-tabero-futsu2.png
「 👆 だから この SkiaSharp に SkiaSharp.Views は入ってないようだぜ」

202307__maui__15-2301--skiaSharpViews.png

ramen-tabero-futsu2.png
「 👆 SkiaSharp.Views パッケージもインストールしてみるかだぜ」

202307__maui__15-2303--skiaSharpViewsMaui.png

ramen-tabero-futsu2.png
「 👆 だから この SkiaSharp.Views には SkiaSharp.Views.Maui は入ってないようだぜ」

202307__maui__15-2305--skiaSharpViewsMauiCore.png

ramen-tabero-futsu2.png
「 👆 似たような名前のパッケージが並んでいて困るが
とりあえず SkiaSharp.Views.Maui.Core パッケージを インストールしてみるかだぜ」

202307__maui__15-2307--skiaSharpViewsMauiCoreError.png

ramen-tabero-futsu2.png
「 👆 SkiaSharp.Views.Maui.Core には SkiaSharp.Views.Maui.Controls は入ってないようだぜ」

202307__maui__15-2308--skiaSharpViewsMauiControl.png

ramen-tabero-futsu2.png
「 👆 じゃあ SkiaSharp.Views.Maui.Controls パッケージを インストールしてみるかだぜ」

202307__maui__15-2310--build.png

ramen-tabero-futsu2.png
「 👆 ビルドは通ったぜ」

202307__maui__15-2311--run-error.png

ramen-tabero-futsu2.png
「 👆 実行すると 立ち上がる前にエラー」

ohkina-hiyoko-futsu2.png
「 その理由を調べなさいよ」

ramen-tabero-futsu2.png
「 UnhandledException というのは ライブラリが 例外が起こっているのにキャッチせずに終了したということだぜ」

ohkina-hiyoko-futsu2.png
「 だから、その理由」

202307__maui__15-2315--catastrophic-failure.png

ramen-tabero-futsu2.png
「 カタストロフィック(Catastrophic;大災害的)な フェイラー(Failure;失敗)だぜ」

kifuwarabe-futsu.png
「 なんのことだが 分からんな……」

ohkina-hiyoko-futsu2.png
「 👇 同じ不具合に突き当たっている人がいるわよ」

📖 [BUG] MAUI: SKCanvasView crash, unable to display SKBitmap directly #2139

202307__maui__15-2325--help.png

202307__maui__15-2329--builder-o2o0.png

ramen-tabero-futsu2.png
「 👆 どこにも説明が無いが 謎のコードを書き……」

202307__maui__15-2334--run.png

ramen-tabero-futsu2.png
「 👆 実行するとこまでは イケた」

kifuwarabe-futsu.png
「 ようやく 画像処理のスタートラインに経ったな」

ramen-tabero-futsu2.png
「 じゃあ SkiaSharp のサンプル・プログラムを真似たろ」

(カタ カタ カタ カタ)

202307__maui__15-2349--skiaSharp.png

ramen-tabero-futsu2.png
「 👆 文字が出た」

ohkina-hiyoko-futsu2.png
「 じゃあ 文字の代わりに 画像を表示してみなさいよ」

SkiaSharp で画像を表示しろだぜ

ramen-tabero-futsu2.png
「 👇 画像の用意の仕方が分からん」

📖 Microsoft > SKImage Class

kifuwarabe-futsu.png
「 👇 SKBitmap なら、ストリームから作れるんじゃないか?
SKImage は、SKBitmap を読込むメソッドを持っているだろ」

📖 Microsoft > SKBitmap

📖 Microsoft > Decode(Stream)

ramen-tabero-futsu2.png
「 そのサンプル・プログラムが欲しい」

kifuwarabe-futsu.png
「 👇 Xamarine の利用者は SkiaSharp に詳しいらしいぜ」

📖 Bitmap Basics in SkiaSharp

ramen-tabero-futsu2.png
「 知らん世界だ。真似するかあ」

202307__maui__16-0032--SKBitmap.png

ramen-tabero-futsu2.png
「 👆 おー、描画できたぜ。
基本的にラスター画像は SKBitmap で記憶しておいて、
表示するときは SKBitmap を SKImage でラッピングすればいいわけだぜ」

kifuwarabe-futsu.png
「 じゃあ あとは ラスター画像の容量で 画像処理できるな」

ohkina-hiyoko-futsu2.png
「 もう寝なさい」

📅 (2023-07-16 sun)画像の明度を下げてくれだぜ

kifuwarabe-futsu.png
「 画像の明度を下げてくれだぜ」

ramen-tabero-futsu2.png
「 愚直に 1ピクセルずつ 変更するコードなら すぐ書けそうだが、
並列処理に有利な コードの書き方が 分からんな……」

ohkina-hiyoko-futsu2.png
「 👇 これを読みなさい」

📖 SkiaSharp ビットマップ ピクセル ビットへのアクセス

ramen-tabero-futsu2.png
「 マイクロソフトの記事の コード・サンプルのリンク クリックしても
コード・サンプルが置いてないの 何でなんだろな?」

kifuwarabe-futsu.png
「 実行速度の検証は iOS、 Android、 UWP で行われていて、 Windows が含まれていないのは何でだぜ?」

ohkina-hiyoko-futsu2.png
「 Windows 上で Windows 向けのプログラム書いたら有利なの明らかだからよ。
UWP というのが Windows なのよ」

ramen-tabero-futsu2.png
「 unsafe 使って uint のポインター型を使うのが そら早そうだが、
unsafe を使いだしたら C# というより C言語だしな」

ohkina-hiyoko-futsu2.png
「 画像処理の高速化というのは アンセーフなものでは?」

SKBitmap FillBitmapUintPtrColor(out string description, out int milliseconds)
{
    description = "GetPixels SKColor";
    SKBitmap bitmap = new SKBitmap(256, 256);

    stopwatch.Restart();

    IntPtr pixelsAddr = bitmap.GetPixels();

    unsafe
    {
        for (int rep = 0; rep < REPS; rep++)
        {
            uint* ptr = (uint*)pixelsAddr.ToPointer();

            for (int row = 0; row < 256; row++)
                for (int col = 0; col < 256; col++)
                {
                    *ptr++ = (uint)new SKColor((byte)col, 0, (byte)row);
                }
        }
    }

    milliseconds = (int)stopwatch.ElapsedMilliseconds;
    return bitmap;
}

ramen-tabero-futsu2.png
「 👆 先頭から末尾まで 色を置き換えながら シーケンスしてるだけだ やってることは簡単だ
真似るか」

202307__maui__16-1245--unsafe.png

ramen-tabero-futsu2.png
「 👆 じゃあ今後、ネギラーメンでは アンセーフなものも 使っていくことにするぜ」

ramen-tabero-futsu2.png
「 int 型のメモリ・レイアウトは red, green, blue, alpha で確定かだぜ?
環境により異なるかだぜ?」

kifuwarabe-futsu.png
「 ビッグ・エンディアン、リトル・エンディアンが関わってくるかどうか 知らないぜ?」

ここでのコードでは、バイトが赤、緑、青、アルファの順序であり、色の SKColorType.Rgba8888 種類と一致していることを前提としています。 これは iOS と Android の既定の色の種類ですが、ユニバーサル Windows プラットフォームでは使用されないことを思い出してください。

ohkina-hiyoko-futsu2.png
「 👆 環境によって異なるそうよ」

namespace MauiApp1;

using SkiaSharp;

/// <summary>
///     明度を下げる
/// </summary>
internal static class ReduceBrightness
{
    // - インターナル静的メソッド

    /// <summary>
    ///     そうする
    /// </summary>
    internal static SKBitmap DoItInPlace(SKBitmap bitmapInPlace)
    {
        IntPtr pixelsAddr = bitmapInPlace.GetPixels();
        int width = bitmapInPlace.Width;
        int height = bitmapInPlace.Height;

        unsafe
        {
            uint* ptr = (uint*)pixelsAddr.ToPointer();

            for (int row = 0; row < height; row++)
                for (int col = 0; col < width; col++)
                {
                    // ビッグ・エンディアンか、リトル・エンディアンかの違いを吸収してくれることを期待して
                    SKColor color = new SKColor(*ptr);

                    // RGB値が減れば、暗くなるだろ
                    *ptr++ = (uint)new SKColor(
                        red: (byte)(color.Red * 0.7),
                        green: (byte)(color.Green * 0.7),
                        blue: (byte)(color.Blue * 0.7));
                }
        }

        return bitmapInPlace;
    }
}

ramen-tabero-futsu2.png
「 👆 なるほど、
ビッグ・エンディアンか、リトル・エンディアンか、環境の違いを吸収しようとすると
ちょっと 遅くなるのか、まあいいか」

202307__maui__16-1310--reduceBrightness-o2o0.png

ramen-tabero-futsu2.png
「 👆 明度を下げることはできたが、再描画のたびに どんどん暗くなって 真っ黒になる。
コードを書く位置を ミスった」

タイル・パレット編集画面のタイル・セット画像の明度も下げてくれだぜ

kifuwarabe-futsu.png
「 タイル・パレット編集画面のタイル・セット画像の明度も下げてくれだぜ」

ramen-tabero-futsu2.png
「 GraphicsView と、 SKCanvasView の結局どちらも 用途に応じて使い分けることになるの
学習コストと、脳への負荷が高いな」

ramen-tabero-futsu2.png
「 フォルダーの整理も大変だ。
MAUI のフレームワークに従うものと、
SkiaSharp という異質なものを どう配置しよう」

ohkina-hiyoko-futsu2.png
「 FeatSkia みたいなフォルダーを作って
そこに放り込めば?」

ramen-tabero-futsu2.png
「 ミュージシャンみたいだな。
そもそも Skia って何だ? 調べるか」

📖 Wikipedia > Skia

ramen-tabero-futsu2.png
「 👆 元は 会社名らしい」

202307__maui__16-1414--SkiaSharpViewsMauiControls-o2o0.png

ramen-tabero-futsu2.png
「 👆 SkiaSharp.Views.Maui.Controls パッケージをインストールすれば、必要なものは 自動的にインストールしてくれるようだぜ」

202307__maui__16-1418--MauiProgram-o2o0.png

ramen-tabero-futsu2.png
「 👆 MauiProgram.csbuilder.UseMauiApp<App>().UseSkiaSharp(); って書く必要があるの、
探さないと見つからない 分からんと思う」

202307__maui__16-1444--FeatSkia-o2o0.png

ramen-tabero-futsu2.png
「 👆 画像処理は とりあえずお試しに FeatSkia フォルダーを作って そこへ入れよう」

202307__maui__16-1448--namespace-o2o0.png

ramen-tabero-futsu2.png
「 👆 ビューに ネームスペース
xmlns:skia="clr-namespace:SkiaSharp.Views.Maui.Controls;assembly=SkiaSharp.Views.Maui.Controls"
を追加して」

202307__maui__16-1451--SKCanvasView-o2o0.png

ramen-tabero-futsu2.png
「 👆 SKCanvasView 要素を配置」

ohkina-hiyoko-futsu2.png
「 今回、Touch イベントは要らないんじゃない?」

202307__maui__16-1459--SKBitmap-o2o0.png

ramen-tabero-futsu2.png
「 👆 ビューモデルには、 SKBitmap を格納できるようにしておくぜ」

202307__maui__16-1542--PaintSurface-o2o0.png

ramen-tabero-futsu2.png
「 👆 描画処理は、ただビットマップを描画するだけにするぜ」

kifuwarabe-futsu.png
「 コード・ビハインドに 画像処理をベタ書きするのが、 MVVM の思想では イケてないんだろうな」

202307__maui__16-1606--Loaded-o2o0.png

ramen-tabero-futsu2.png
「 👆 ページの読込完了時に、画像読込と、明度を下げるのを 済ませてしまおう」

202307__maui__16-1607--run.png

ramen-tabero-futsu2.png
「 👆 そして実行。 位置とサイズが合ってないな」

202307__maui__16-1611--adjust.png

ramen-tabero-futsu2.png
「 👆 位置とサイズを調整」

ohkina-hiyoko-futsu2.png
「 明度を下げたタイル・セット画像の上に、
半透明のグレーの画像を置いているけど、
その2枚は MAUI によって どうブレンドされているの?
加算合成なのか、乗算合成なのか」

kifuwarabe-futsu.png
「 👇 これを読めだぜ」

📖 ブレンド モード

ramen-tabero-futsu2.png
「 半透明のときの説明は無いな」

ohkina-hiyoko-futsu2.png
「 選択領域か、そうでないかが 明確に見分けられなければ いけなくない?」

202307__maui__16-1638--roundedRectangle.png

ramen-tabero-futsu2.png
「 👆 角丸の矩形でどうだぜ?」

ohkina-hiyoko-futsu2.png
「 暗い場所が残ってると 残差業が残ってるみたいに感じるじゃない。
選択されていないところを 暗くして、 選択されているところは 元の色調にしたら いいんじゃないの?」

ramen-tabero-futsu2.png
「 じゃあ 元画像 は どこかに残しておかないといけないのかだぜ」

kifuwarabe-futsu.png
「 カラード・マップ(Colored Map) は色分けだろ。
色で分けろよ」

202307__maui__16-1727--tone.png

ramen-tabero-futsu2.png
「 👆 青が 暗くなってしまうなあ」

ohkina-hiyoko-futsu2.png
「 青値は 多めになるよう 補正を掛けたら?」

登録タイルの削除ボタンを作れだぜ

ramen-tabero-futsu2.png
「 登録タイルが こんな ぐちゃぐちゃ しているのが悪いんだ。 削除できるようにしよう」

kifuwarabe-futsu.png
「 追加ボタンと 削除ボタンが こんなに近くにあるのは 悪いデザインでは?」

202307__maui__16-1924--deleteButton-o2o0.png

ramen-tabero-futsu2.png
「 👆 これぐらい 離したらいいかだぜ?」

ohkina-hiyoko-futsu2.png
「 削除ボタンだけ 左に持っていったら?」

kifuwarabe-futsu.png
「 削除したいときに 不便なのでは……」

ボタンに押した感じを付けれないの?

ohkina-hiyoko-futsu2.png
「 MAUI のボタンって 反応しないから 押した感じがしないけど
ボタンを押したという演出を 付けれないの?」

ramen-tabero-futsu2.png
「 そんなものは ボタンには最初から付いているものと 思っていたぜ」

kifuwarabe-futsu.png
「 👇 記事を読めだぜ」

📖 【.NET MAUI】Buttonにアニメーションを付けて表示をカスタマイズする

📖 Microsoft > AnimationBehavior

202307__maui__16-1935--toolkit-o2o0.png

ramen-tabero-futsu2.png
「 👆 名前空間を書いて」

202307__maui__16-1939--animation-o2o0.png

ramen-tabero-futsu2.png
「 👆 ボタンに ビヘイビアを書いたが、アニメーションする様子は無いぜ」

202307__maui__16-1941--use-o2o0.png

ramen-tabero-futsu2.png
「 👆 この書き方で いけてないのかだぜ?」

202307__maui__16-1945--builder-o2o0.png

ramen-tabero-futsu2.png
「 👆 チェーンにした方がいいのか?」

ramen-tabero-futsu2.png
「 ダメだ ボタンは アニメーションしないぜ」

202307__maui__16-2047--FadeTo-o2o0.png

ramen-tabero-futsu2.png
「 👆 XAML をどう書いても ボタンはアニメーションせず クソだったので
コード・ビハインドに コードを書くことにしたら アニメーションしたぜ」

kifuwarabe-futsu.png
「 なぜ XAML の設定では アニメーションしなかったのか 謎のままだぜ」

ボタンの上をマウスがホバーしたときに、ボタンの色を変えれないの?

ohkina-hiyoko-futsu2.png
「 ボタンの上をマウスがホバーしたときに、ボタンの色を変えれないの?」

ramen-tabero-futsu2.png
「 👇 ご存じの通り MAUI は マウス操作ではなく タップ操作を前提とした設計なんで マウス・ホバーなんて無いぜ」

📖 Mouse hover detection in .NET MAUI

kifuwarabe-futsu.png
「 デスクトップ・アプリとしての 体験が 悪い……」

kifuwarabe-futsu.png
「 👇 ジェスチャーでなんとかならないのかだぜ?」

📖 Implement PointerGestureRecognizer #9592

ramen-tabero-futsu2.png
「 ボタン毎に ジェスチャー付けるの クソ めんどくさいが やってみるかだぜ」

Colors.xaml に定義されている primary という名前の Color インスタンスはどうやって取得できるんだぜ?

ramen-tabero-futsu2.png
「 Colors.xaml に定義されている primary という名前の Color インスタンスはどうやって取得できるんだぜ?」

kifuwarabe-futsu.png
「 👇 これを読めだぜ」

📖 How to find a resource with key in code behind? [MAUI]

ramen-tabero-futsu2.png
「 いくつかあるディクショナリーのどこかにあるから 探索しろということかだぜ」

namespace _2D_RPG_Negiramen.Models
{
    /// <summary>
    ///     リソース・ヘルパー
    /// </summary>
    internal static class ResourcesHelper
    {
        /// <summary>
        ///     探す
        ///     
        ///     <list type="bullet">
        ///         <item>TODO ★ 実装をもっと書いてほしい</item>
        ///     </list>
        /// </summary>
        /// <param name="key">リソースのキー</param>
        /// <param name="resource">見つけたもの</param>
        /// <returns>見つかった</returns>
        internal static bool TryFind(string key, out object resource)
        {
            if (App.Current==null)
            {
                resource = 0;
                return false;
            }

            // 愚直な探索
            foreach (var resourceDictionary in App.Current.Resources.MergedDictionaries)
            {
                if (resourceDictionary.TryGetValue(key, out resource))
                {
                    return true;
                }
            }

            resource = 0;
            return false;
        }
    }
}

ramen-tabero-futsu2.png
「 👆 じゃあ これでいいだろ」

202307__maui__16-2155--MouseHover-o2o0.png

ramen-tabero-futsu2.png
「 👆 マウスのホバーで色変えるぐらいのことで ジェスチャーのコード 書くことになるの うんざりするが
仕方ない」

202307__maui__16-2200--MouseHoverCode-o2o0.png

ramen-tabero-futsu2.png
「 👆 イベントハンドラは こんなもんでいいだろ」

ramen-tabero-futsu2.png
「 そういえば ボタンにマウスカーソルが被さった時の カーソルの見た目の変更も やり方が分からないな」

202307__maui__16-2210--Coloring-o2o0.png

ramen-tabero-futsu2.png
「 👆 マウス・ホバー時の色味を落ち着かせて、 画面の配色のコントラストも落とすように 変更したぜ」

kifuwarabe-futsu.png
「 ネギラーメンという名前なのに 青が基調でいいのかだぜ?」

ramen-tabero-futsu2.png
「 青は 集中力を高める色という俗説もあるし、 まあいいだろ」

202307__maui__16-2231--UI.png

ramen-tabero-futsu2.png
「 👆 マウスカーソルが ボタンに被さると ボタンが少し 明るく見えるとか 1個1個 設定しないといけない
これは大変だ」

"Tile Set" ではなくて "Tileset" なのでは

kifuwarabe-futsu.png
「 Tileset は 1単語として よく使われているようだぜ」

ramen-tabero-futsu2.png
「 じゃあ リネームするか~」

ohkina-hiyoko-futsu2.png
「 タイル・パレット編集画面 という名前は 実態に合ってんの?」

ramen-tabero-futsu2.png
「 タイル切り抜き画面だよな」

kifuwarabe-futsu.png
「 英語にすると Tile Crop Page ぐらいかだぜ?」

ramen-tabero-futsu2.png
「 意味が伝わるだろうか?」

ohkina-hiyoko-futsu2.png
「 まだ タイル・パレット本体も無いし、
タイル・パレット編集 と言われても 分かんなくない?」

ramen-tabero-futsu2.png
「 とりあえず 文字数が減るのは嬉しいから リネームするか」

TilePaletteEditPage ----> TileCropPage

文字列リソースにはどうやってアクセスすんの?

ramen-tabero-futsu2.png
「 あれっ? C# スクリプトから 文字列リソースを取得するには どうやったらいいんだぜ?」

ohkina-hiyoko-futsu2.png
「 LocalizationResourceManager を直で呼び出したらどう?」

var text = (string)LocalizationResourceManager.Instance["Add"];

ramen-tabero-futsu2.png
「 👆 こんな感じで いけたぜ」

202307__maui__17-0023--NewLine-o2o0.png

ramen-tabero-futsu2.png
「 👆 ローカライズしたら &#10; という改行コードが そのまま表示されてしまった!」

kifuwarabe-futsu.png
「 インジェクション対策だろう」

ramen-tabero-futsu2.png
「 👆 \n でも <br> でもダメ」

ramen-tabero-futsu2.png
「 しゃーない いい感じのところで改行するのは 諦めよう」

ウィンドウ・サイズってどうやって設定するんだぜ?

ramen-tabero-futsu2.png
「 MAUI って デスクトップ上のウィンドウの位置 という概念も無いよな」

kifuwarabe-futsu.png
「 デスクトップ・アプリではないんで」

ohkina-hiyoko-futsu2.png
「 👇 記事を読みなさい」

📖 .NET MAUI でウインドウサイズを指定する方法(Windowsで実行した場合)

ramen-tabero-futsu2.png
「 そんな Win32 みたいなコード 書くのかだぜ?」

(カタ カタ カタ カタ)

ramen-tabero-futsu2.png
「 書いた。 うまくいった」

画面遷移から戻ってきたときに呼び出されるイベントハンドラはあるかだぜ?

ramen-tabero-futsu2.png
「 Loaded は最初の1回しか呼び出されないらしい。
画面遷移で 戻ってきたときに呼び出されたいときは どうすんだぜ?」

ramen-tabero-futsu2.png
「 とりあえず いろんなイベントハンドラ実行したら NavigatedTo が それっぽいかな」

(カタ カタ カタ カタ)

ramen-tabero-futsu2.png
「 よし、いけた」

ramen-tabero-futsu2.png
「 ブログの編集画面が なんか重くなってきたので 次の記事へ飛ぶかだぜ」

kifuwarabe-futsu.png
「 よっしゃ」

次の記事

📖 次の記事: 2D RPG 制作ツールを作ろうぜ(^~^)? <その2>

ツイッターでシェア
みんなに共有、忘れないようにメモ

むずでょ

光速のアカウント凍結されちゃったんで……。ゲームプログラムを独習中なんだぜ☆電王戦IIに出た棋士もコンピューターもみんな好きだぜ☆▲(パソコン将棋)WCSC29一次予選36位、SDT5予選42位▲(パソコン囲碁)AI竜星戦予選16位

Crieitは誰でも投稿できるサービスです。 是非記事の投稿をお願いします。どんな軽い内容でも投稿できます。

また、「こんな記事が読みたいけど見つからない!」という方は是非記事投稿リクエストボードへ!

有料記事を販売できるようになりました!

こじんまりと作業ログやメモ、進捗を書き残しておきたい方はボード機能をご利用ください。
ボードとは?

コメント