C++ ときどき ごはん、わりとてぃーぶれいく☆

USAGI.NETWORKのなかのひとのブログ。主にC++。

winget へ choco または他の何かから可能な範囲で移行するメモ

winget を導入

f:id:USAGI-WRP:20200520104607p:plain

winget <- choco 移行例: Node.js

  1. 既存の別の何かで入れてある Node.js はそれぞれの方法で手アンインストール
    • sudo cuninst node ; choco の場合
    • 手導入してある場合も Windows の Apps & features から手アンインストール
  2. winget で導入
    • winget install node

winget install node の場合、 CUI でパッケージのダウンロードが進むとインストール経過は GUI のウィンドウが勝手に出てきて進みます。放っておくと(たぶん)成功で完了して CUI に制御が戻ります。

f:id:USAGI-WRP:20200520105632p:plain

f:id:USAGI-WRP:20200520110013p:plain

いまのところは残念ながら、途中で GUI のウィンドウが"しゃしゃり出て"来てしまうので winget install をバックグラウンドで実行させつつ「ながら」で別作業を並行みたいなかっこいい使い方はできません。

また、既にインストール済みか一切チェックしやがらない現代のパッケージマネージャーとしてはわりとおばかさんな仕様のため、 winget install node が成功した状態で winget install node するとまったく同様にインストールを繰り返します。これは依存パッケージの仕組みやある目的のためにまとめてあれこれを導入したい場合にすっごい無駄です。

おまけメモ

↑では突然winget installしましたが、教科書的な手順としては winget search node, winget show node など確認してから winget install node です。

f:id:USAGI-WRP:20200520104935p:plain

f:id:USAGI-WRP:20200520115440p:plain

所感としては「実用するにはまだはやいけれど期待はしたい」です。Issueがたくさんあがっていますし、パッケージマネージャーとしてのコア機能部分でまだ不足が多いので、現在はパッケージが充実したとしてもパッケージマネージャーとしての機能性からは choco の方が便利でいますぐ移行した方がよいとは言えません。来週には既にそうではなくなっているかもしれませんし、①年後には「そんなプロジェクトもそういえばありましたね、ハハッ」になっているかもしれません。

Electron アプリに electron-store で設定ファイル機能を追加する場合の example & tips 的なメモ

GitHub - sindresorhus/electron-store: Simple data persistence for your Electron app or module - Save and load user preferences, app state, cache, etc を使うメモです。

public/conf.js とか適当に作る例:

const path = require("path");
const store = require("electron-store");

const store_conf = {
 // https://www.npmjs.com/package/electron-store#schema
 schema: {
  // 'foo'でアクセスできる
  foo: {
   type: typeof 0,
   maximum: 100,
   minimum: 1,
   default: 50,
  },
  // 'bar'でアクセスできる
  bar: {
   type: typeof "",
   format: "url",
   default: "https://example.com/",
  },
  // 'window' でアクセスできる Object
  window: {
   type: typeof {},
   // Object は明示的に default: {} を与えておかないと子要素のdefaultがあっても取り出せないとか起こるので注意します
   default: {},
   // Object の子要素は properties で定義します
   properties: {
    // 'window.width' でアクセスできる
    width: {
     type: typeof 0,
     maximum: Number.MAX_SAFE_INTEGER,
     minimum: 480,
     default: 960,
    },
    // 'window.height' でアクセスできる
    height: {
     type: typeof 0,
     maximum: Number.MAX_SAFE_INTEGER,
     minimum: 270,
     default: 540,
    },
   },
  },
 },
 // https://www.npmjs.com/package/electron-store#migrations
 migrations: {},
};

module.exports = new store(store_conf);
  • Note:
    • schamaJSON で表現できるけれど、JSONで分離すると key にわざわざ " を付けなければならないとか Number.MAX_SAFE_INTEGERtypeof ''のような定義方法を使えない制限が生じて不便かもしれません。分離する場合も .js にしておくと便利が良さそうです。
    • schema に Object を入れ、その子要素へ default を設定したい場合は親となる Object で default: {} しておかないと子要素の default を取り出せなくなるので注意する必要があります。

public/conf.js を使う例( public/electron.js エントリーポイントを想定 ):

const electron = require("electron");
const app = electron.app;
const browser_window = electron.BrowserWindow;

const conf = require("./conf.js");

let main_window;

function createWindow() {
 app.allowRendererProcessReuse = false;

 main_window = new browser_window({
  width: conf.get("window.width"),
  height: conf.get("window.height"),
  webPreferences: { preload: `${__dirname}/preload.js` },
 });

 // (...abbr...; 後略)

Electron アプリに electron-localshortcut で非グローバルでMenuのアクセラレーターも使わないキーバインドを追加するメモ

準備:

実装例(public/electron.js):

const electron = require("electron");
const app = electron.app;
const browser_window = electron.BrowserWindow;

const local_shortcut = require("electron-localshortcut");

let main_window;

function createWindow() { 
  // (...abbr...; 中略)
}

// (...abbr...; 中略)

app.on("ready", () => {
 createWindow();
 local_shortcut.register(main_window, "F12", () =>
  main_window.webContents.toggleDevTools()
 );
});

// (...abbr...; 後略)

参考

  • javascript - Electron does not listen keydown event - Stack Overflow
    • Note: 今回のメモの直接の参考です。
  • Keyboard Shortcuts | Electron
    • Note: 公式情報として参考にはなるけれど electron-localshortcut を使う方法は紹介されていません。グローバルショートカット(ウィンドウが非アクティブでも反応する)、Menuのアクセラレーター機能(メニューに項目を作る必要が生じる)、レンダラープロセス側でにゃんにゃん(若干面倒&今回ケースの用途では直接レンダラープロセス側にコードをごりごりするのは微妙に美しくない気がしたので今回は↑の方法へ)

Electron アプリに i18next を追加して i18n/l10n 対応するメモ

基本的な使用の流れ

  1. yarn add i18next i18next-node-fs-backend
  2. public/i18n.js など適当に作り
  3. l10n 文字列を取り出したいソースで const i18n = require('./i18n.js') して
  4. 必要なら await i18n.changeLanguage('ja-JP') のように l10n 先を実行時に設定する仕込みをして
  5. i18n.t('hoge') とすると i18next で l10n した文字列を取り出せます
  6. i18next の options で渡す loadPathJSON{ "hoge": "ほげ" } のように key-value 的に l10n リソースを定義追加します。saveMissingtrue にしておけば addPath で与える missing 用のファイルへ l10n リソースが未定義で実行時に要求された文字列のリストが保存されます。

public/i18n.js

  • Note
    • ファイル名や配置はお好みで。
    • optionsConfiguration Options - i18next documentation を見て適当に。
    • fallbackLng を定義すると、 missing による add 動作先も fallbackLng になりました。未設定にしておけば missing による add は dev.missing.json のように addPath で与える {{lng}}dev になります。
const i18n = require("i18next");
const i18n_backend = require("i18next-node-fs-backend");
const path = require("path");
// const is_dev = require("electron-is-dev");

const options = {
 // debug: is_dev,
 lng: "en-US",
 initImmediate: false,
 backend: {
  loadPath: path.resolve(__dirname, "..", "i18n/{{lng}}.json"),
  addPath: path.resolve(__dirname, "..", "i18n/{{lng}}.missing.json"),
  jsonIndent: 2,
 },
 saveMissing: is_dev,
 // fallbackLng: "en-US",
 whiteList: [
  "en-US",
  "ja-JP",
  //, "ko-KR"
  //, "zh-CN"
  //, "zh-TW"
  //, "zh-HK"
 ],
};

i18n.use(i18n_backend);

if (!i18n.isInitialized) i18n.init(options);

module.exports = i18n;

i18n/ja-JP.json の例

  • Note: ファイル名と配置は i18next へ与える options で任意に設定できるのでお好みで。
{ "hoge": "ほげ" }

参考

Inkscape-1.0: 新規作成されるSVGドキュメントの背景色のデフォルト値を変える方法; ダークモードのテーミング&defaultドキュメント背景の設定方法のメモ

Inkscape-1.0 では Theme 機能が実装されたので、 Edit -> Preferences -> Interface -> Theme を設定するとダークモードに優しいテーミングができるようになりました。嬉しいです。しかし、闇の世界に住む私たちの目にInkscapeの画面で最も眩しくて困る部分はドキュメント本体の背景色です。白い画面は疲れます。真っ黒なのも黒線が完全に埋没してしまいますし、初期値は暗い灰色が好みです。これはいまのところ Preferences からではなく、ドキュメント新規作成時のテンプレートを直接変更する必要があります。

  • C:\Program Files\Inkscape\share\inkscape\templates (Windowsのデフォルトのインストールパスを用いている場合)

default.svg (InkscapeのUIをen-USで使用している場合) があるので、管理者権限の適当なテキストエディターで開いて svg/sodipodi:namedview[pagecolor]#FFFFFF からお好みの色へ変更して保存します。

GNU/Linuxでは /usr/share/inkscape/... とかそのあたりに templates があるかもしれません。 en-US 以外の言語をInkscapeのUIに設定している場合は default.ja.svg (日本語用) のように言語が付いたバージョンの templates/default.??.svg を編集します。

f:id:USAGI-WRP:20200506063817p:plain

心穏やかに闇のInkscapeを使えるようになります👍

参考

Blender: 正規表現でがさっと Vertex Group(s) をタゲって統合しつつ元は削除して置き換えられる Scripting: usagi/blender-merge-vertex-groups.py のメモ

前回のメモで使用した p2or/blender-merge-vertex-groups.py を元に:

  1. 正規表現 regex 設定で Vertex Group(s) をまとめてタゲれて
  2. 統合元になった Vertex Group(s) は削除する replace モードを True/False 設定できて
  3. 統合先を明示的な名付け to またはそれが未設定なら "+".join できて
  4. 削除と作成について簡単なログを吐いてくれる
  5. dryTrue/False して dry-run (実際には操作しないけど今の設定で実行するとこれこれが remove でこんな merge ができるよ、を表示だけ)してくれる (2020-04-14追記)

ように改造した Fork:

を作りました💪 便利ですよ✨

f:id:USAGI-WRP:20200413230555p:plain

f:id:USAGI-WRP:20200413230529p:plain

連続で複数パターンを操作する場合は add-on にするならちゃんとGUIを付けないと使いにくそうだし、 Scripting で regex, replace, to を逐次書き換えながら使ってね、でもとりあえずの便利には十分かなって思います。

(2020-04-14追記:↓dry-run)

f:id:USAGI-WRP:20200414011825p:plain

Blender: Armature の削除や変更で Vertex Group との整合性が狂ってしまったときの修正方法、のメモ

状況

「Armature を節約しなきゃ→簡単に Merge できるところは Merge!→ Merge が難しいところは Delete / Disolve ! 」

とかした後に、

「 Armature を Delete / Disolve した部分に対応していた Vertex Group と残した Armature との対応が壊れてしまった…再ペイントは…しんどいでござる」

になった時、 Weight Paint で塗り絵せずに残っている Vertex Group をにゃんにゃんしてうまいことする方法のメモです。

例えば、

f:id:USAGI-WRP:20200413205449p:plain

↑ Armature は1つ!(に Merge & Delete / Disolve した!)

f:id:USAGI-WRP:20200413205400p:plain

↑↓ Vertex Group は2つ!(Armatureとの対応も一部が壊れてしまっているのでうまく動かなくなっています)

f:id:USAGI-WRP:20200413205421p:plain

方法

Blender-2.82 時点では Vertex Group を直接操作して Merge する UI は無さそうなので、 Scripting を使います。今回は何かないかなーと探してみたところ:

-p2or/blender-merge-vertex-groups.py

↑いい感じのコード片が見つかったのでこれを応用します💪

手順:

  1. "いまは分かれてしまっているが統合したい" Vertex Group の正確な名前を確認します。 F2 で名前を編集状態にして Copy すると間違いが無くて安心
  2. ScriptingNew して p2or/blender-merge-vertex-groups.py を貼り付け
  3. 貼り付けた blender-merge-vertex-groups.py の group_input を ↑↑(1) で調べた名前群にする
  4. Object Mode で操作対象の Mesh が選択された状態にする
  5. Run Script
  6. 名前も "+" でくっついて統合された Vertex Group ができている(はず)なので確認
  7. 統合後の Vertex Group に対応付けたい Armature の名前を確認。 F2 で名前を編集状態にして Copy すると間違いが無くて安心
  8. 不要な場合は統合前の Vertex Group 群を - Vertex Groups UI の右側についているボタンをぽちって削除
  9. ↑↑↑(5) の統合された Vertex Group の名前を F2 で名前編集状態にして ↑↑(6) で確認した名前に変更。↑↑(6) で Copy してあれば Paste するだけ
  10. Pose Mode で期待動作を確認

Note: 統合後の Vertex Group の名前を統合前の Vertex Group で使用している名前にしたい場合は (7)と(8)を逆順で行います。

↓例えば Vertex Group 群 "NekoMimiBone_L_001""NekoMimiBone_L_003" を統合して "NekoMimiBone_L_001+NekoMimiBone_L_003" を作成し、

f:id:USAGI-WRP:20200413212459p:plain

f:id:USAGI-WRP:20200413213317p:plain

↓不要になった Vertex Group 群 "NekoMimiBone_L_001""NekoMimiBone_L_003" は Remove し、

f:id:USAGI-WRP:20200413213458p:plain

↓統合後の Vertex Group の名前を対応付けたい Armature と同じに

f:id:USAGI-WRP:20200413213810p:plain

します💪

f:id:USAGI-WRP:20200413214008p:plain

↑期待動作した成功✨