diff --git a/.gitignore b/.gitignore index 75e73ee..bc3ff28 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,5 @@ Thumbs.db # --- ComfyUI/カスタムノード特有 --- # もし一時ファイルやログを書き出す仕組みを作ったなら、それも追加じゃ *.log + +.ruff_cache/ \ No newline at end of file diff --git a/README.md b/README.md index 81cea73..735a106 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,15 @@ フロー内に複数個置いても、それぞれ独立して動くぞ。 +## v0.5.0 + +`Safe Random Seed` を追加したのじゃ。 + +- `Safe Random Seed` + - KSampler向けに、0以上のランダムseedだけを出力する小型ノード + - Python側で `secrets` を使って発番します + - 実行後、ノードタイトルを `Seed: 4897362896` のように書き換えます + ## v0.4.0 `Prompt Random Choice Ex` を追加したのじゃ。 @@ -45,6 +54,10 @@ - 実行時にノードタイトルが `Choice: coffee shop` のように更新されるぞ。 - KSamplerのプレビューと見比べやすいのじゃ。 +- **KSampler向けの安全なランダムseed生成** + - `Safe Random Seed` は、0以上のINTだけを出力するぞ。 + - 実行後、ノードタイトルが `Seed: 4897362896` のように更新されるのじゃ。 + - **複数設置に対応** - 背景用、時間帯用、天気用など、複数ノードを置いてそれぞれ別々に使えるぞ。 @@ -175,6 +188,23 @@ day|day|day|sunset|night - `change_every` が 1 なら毎回選び直す - `change_every` が 2 以上なら、その回数ぶん同じ候補を維持する - 実行時にタイトルへ `Choice: lake` や `Choice: (empty) (2/3)` のように表示する +- `Safe Random Seed` は実行時にタイトルへ `Seed: 4897362896` のように表示する + +## Safe Random Seed + +KSampler向けに、0以上のランダムseedを1つ生成します。 +汎用の整数Primitiveを `randomize` すると負数が出る場合がありますが、このノードは負数を出しません。 +SDE系サンプラーで `expected non-negative integer` が出る事故を避けるための小さな保険じゃ。 + +- 入力はありません +- 出力は `seed` だけです +- 乱数はComfyUIサーバー側、Pythonの `secrets` で生成します +- 発番はノード実行時です +- 出力値の範囲は `0` から `2^53 - 1` です +- 同じノードの出力を複数箇所へ接続した場合、同じseed値を配ります +- 別々のseedが欲しい場合は、`Safe Random Seed` ノードを複数置いてください +- 前回出力されたseed値は、次回の乱数生成には影響しません +- 実行後、ノードタイトルを `Seed: 4897362896` のように書き換えます ## Prompt Random Choice diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index b01f79a..aa1ce77 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,3 +1,21 @@ +## v0.5.0 + +`Safe Random Seed` を追加しました。 + +## 追加 + +- `Safe Random Seed` + - KSampler向けに、0以上のランダムseedだけを出力する小型ノード + - Python側の `secrets` を使って発番 + - 実行後、ノードタイトルを `Seed: 4897362896` のように更新 + - 同じノードの出力を複数箇所へ接続した場合は、同じseed値を配布 + +## 変更 + +- タイトル表示用JavaScriptで、`Prompt Random Choice Ex` の短縮文字数設定が反映されるように修正 + +--- + ## v0.4.0 `Prompt Random Choice Ex` を追加しました。 diff --git a/icon.png b/icon.png new file mode 100644 index 0000000..384ddcf Binary files /dev/null and b/icon.png differ diff --git a/nodes.py b/nodes.py index 12d3375..7101474 100644 --- a/nodes.py +++ b/nodes.py @@ -30,6 +30,7 @@ amusement park{ferris wheel|carousel|balloons} MAX_EXPAND_STEPS = 64 MAX_EXPANDED_OPTIONS = 4096 +MAX_SAFE_SEED = 2**53 - 1 def _split_options(options_text: str): @@ -427,12 +428,43 @@ class PromptRandomChoiceEx(_RandomChoiceStateMixin): } +class SafeRandomSeed: + @classmethod + def INPUT_TYPES(cls): + return { + "required": {}, + } + + RETURN_TYPES = ("INT",) + RETURN_NAMES = ("seed",) + FUNCTION = "generate" + CATEGORY = "utils/random" + + @classmethod + def IS_CHANGED(cls, **kwargs): + # Force re-execution for each queued run. + return secrets.token_hex(16) + + def generate(self): + seed = secrets.randbelow(MAX_SAFE_SEED + 1) + + return { + "ui": { + "seed_title": [f"Seed: {seed}"], + "seed_value": [str(seed)], + }, + "result": (seed,), + } + + NODE_CLASS_MAPPINGS = { "PromptRandomChoice": PromptRandomChoice, "PromptRandomChoiceEx": PromptRandomChoiceEx, + "SafeRandomSeed": SafeRandomSeed, } NODE_DISPLAY_NAME_MAPPINGS = { "PromptRandomChoice": "Prompt Random Choice", "PromptRandomChoiceEx": "Prompt Random Choice Ex", + "SafeRandomSeed": "Safe Random Seed", } diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..28b3fc6 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,18 @@ +[project] +name = "prompt-random-choice" +version = "0.5.0" +description = "A ComfyUI custom node that randomly selects one item from a list of prompt suggestions each time it is executed." +license = { file = "LICENSE" } +readme = "README.md" +requires-python = ">=3.10" +dependencies = [] + +[project.urls] +Repository = "https://github.com/ruminar/ComfyUI-PromptRandomChoice" +Documentation = "https://github.com/ruminar/ComfyUI-PromptRandomChoice/blob/main/README.md" +"Bug Tracker" = "https://github.com/ruminar/ComfyUI-PromptRandomChoice/issues" + +[tool.comfy] +PublisherId = "ruminar" +DisplayName = "Prompt Random Choice" +Icon = "https://raw.githubusercontent.com/ruminar/ComfyUI-PromptRandomChoice/main/icon.png" diff --git a/web/prompt_random_choice.js b/web/prompt_random_choice.js index c3ebca2..2b29a5e 100644 --- a/web/prompt_random_choice.js +++ b/web/prompt_random_choice.js @@ -4,6 +4,7 @@ const EXTENSION_NAME = "ruminar.PromptRandomChoice"; const NODE_NAMES = new Set([ "PromptRandomChoice", "PromptRandomChoiceEx", + "SafeRandomSeed", ]); function shorten(text, maxLength = 40) { @@ -30,14 +31,22 @@ app.registerExtension({ nodeType.prototype.onExecuted = function (message) { originalOnExecuted?.apply(this, arguments); + if (nodeName === "SafeRandomSeed") { + this.title = String(message?.seed_title?.[0] ?? "Seed: ?"); + + this.setDirtyCanvas?.(true, true); + app.graph?.setDirtyCanvas?.(true, true); + return; + } + const selectedTitle = message?.selected_text_title?.[0] ?? "(empty)"; const repeatIndex = Number(message?.repeat_index?.[0] ?? 0); const changeEvery = Number(message?.change_every?.[0] ?? 1); if (changeEvery <= 1) { - this.title = `${prefix}: ${shorten(selectedTitle)}`; + this.title = `${prefix}: ${shorten(selectedTitle, maxTitleLength)}`; } else { - this.title = `${prefix}: ${shorten(selectedTitle)} (${repeatIndex}/${changeEvery})`; + this.title = `${prefix}: ${shorten(selectedTitle, maxTitleLength)} (${repeatIndex}/${changeEvery})`; } this.setDirtyCanvas?.(true, true);