From d998530730aba7f24457d4a689dfd43e8dfbc832 Mon Sep 17 00:00:00 2001 From: veguAI <152010387+vegu-ai-tools@users.noreply.github.com> Date: Sat, 4 Jul 2026 20:16:54 +0300 Subject: [PATCH] Background illustration followups: indicator, Immersive scene-tools toggle, per-kind display config (#58) * Background illustration followups: split scene background/illustration display config, scene-tools Background toggle chip, active-backdrop indicator (closes #57) --- CHANGELOG.yaml | 2 +- src/talemate/config/schema.py | 30 +++- .../components/AppConfigAppearanceAssets.vue | 140 +++++++++++------- .../src/components/MessageAssetMixin.js | 10 +- .../src/components/SceneMessages.vue | 117 +++++++++++---- .../src/components/SceneTools.vue | 81 ++++++++-- .../src/components/TalemateApp.vue | 19 ++- talemate_frontend/src/constants/visual.js | 5 + tests/test_config_state.py | 30 ++++ 9 files changed, 319 insertions(+), 115 deletions(-) diff --git a/CHANGELOG.yaml b/CHANGELOG.yaml index 1eaae5d1..31f52c9d 100644 --- a/CHANGELOG.yaml +++ b/CHANGELOG.yaml @@ -1,6 +1,6 @@ 0.39.0.dev: features: - - "Scene Illustration Background Mode: Scene illustrations gained a new 'Background' display size that renders the most recent illustration as a backdrop filling the whole scene view instead of showing it inline with messages. Message text sits on translucent blurred panels with a drop shadow, and the message input, control chips and buttons turn opaque so everything stays legible against the image; panel opacity and the text shadow are configurable. An Illustration chip on the message hover toolbar keeps the image menu (view, regenerate, edit, select) reachable, and the menu offers a 'Display as background' shortcut to switch into the mode. Configure under Settings → Appearance → Message Visuals." + - "Scene Illustration Background Mode: Scene illustrations gained a new 'Background' display size that renders the most recent illustration as a backdrop filling the whole scene view instead of showing it inline with messages. Message text sits on translucent blurred panels with a drop shadow, and the message input, control chips and buttons turn opaque so everything stays legible against the image; panel opacity and the text shadow are configurable. Scene Backgrounds ('Visualize Scene (Background)') and Scene Illustrations ('Visualize Moment') are individually configurable, so environmental backgrounds can fill the backdrop while moment illustrations keep rendering inline — when both use Background, the most recent image is the active backdrop. An 'Immersive' quick-toggle chip in the scene tools flips the mode whenever the scene has a suitable background image, a small marker icon shows which message set the current backdrop (click it for the image menu), and an Illustration chip on the message hover toolbar keeps the image menu (view, regenerate, edit, select) reachable. Configure under Settings → Appearance → Message Visuals." - "Visual Prompt Finalization: The Visualizer agent gained a Prompt Finalization settings tab defining post-processing actions (exact, fuzzy or regex match and replace, or an AI instruction) that rewrite image prompts right before they are sent to the image generation backend. Actions can target positive and/or negative prompts, be restricted to specific visual types, and be overridden per scene. Characters can define their own actions under World Editor → Characters → Visuals → Prompt Finalization, which run after the agent's. Reusable action sets are managed as a new 'Visual prompt finalizer' template type, including a shipped Ideogram JSON preset that converts the positive prompt into an Ideogram 4.0 structured JSON prompt. Prompt-only generation output is finalized as well, and a new FinalizePrompt node exposes the step to custom node graphs." improvements: - "Uniform Settings Framework: Agent settings and client settings now share one field-definition schema on the backend and one field renderer on the frontend. Client-specific settings gain the full widget set previously exclusive to agents (sliders, autocompletes, selects with rich choices, per-value notes) plus conditional visibility, and choice lists are delivered to the frontend in a single normalized shape." diff --git a/src/talemate/config/schema.py b/src/talemate/config/schema.py index e509cdcf..1a7d9f9a 100644 --- a/src/talemate/config/schema.py +++ b/src/talemate/config/schema.py @@ -24,6 +24,8 @@ async_signals.register( "config.changed.follow", ) +MESSAGE_ASSET_KINDS = ("avatar", "card", "scene_illustration", "scene_background") + class Client(pydantic.BaseModel): """ @@ -593,13 +595,14 @@ class MarkupMessageStyle(HistoryMessageStyle): class MessageAssetCadenceConfig(pydantic.BaseModel): cadence: Literal["always", "never", "on_change"] = "always" - # "background" is only meaningful for scene_illustration assets + # "background" is only meaningful for scene_illustration and + # scene_background assets size: Literal["small", "medium", "big", "background"] = "medium" - # opacity of the text panels rendered over the backdrop (scene_illustration - # "background" size mode only) + # opacity of the text panels rendered over the backdrop ("background" + # size mode only) background_panel_opacity: float = pydantic.Field(default=0.8, ge=0.0, le=1.0) - # drop shadow on message text over the backdrop (scene_illustration - # "background" size mode only) + # drop shadow on message text over the backdrop ("background" size mode + # only) background_text_shadow: bool = True @@ -617,16 +620,27 @@ class SceneAppearance(pydantic.BaseModel): brackets: MarkupMessageStyle = MarkupMessageStyle() emphasis: MarkupMessageStyle = MarkupMessageStyle() entities: MarkupMessageStyle = MarkupMessageStyle() + # scene_background and scene_illustration assets share the message-level + # asset_type "scene_illustration"; separate entries keep their display + # individually configurable message_assets: Dict[str, MessageAssetCadenceConfig] = pydantic.Field( default_factory=lambda: { - "avatar": MessageAssetCadenceConfig(), - "card": MessageAssetCadenceConfig(), - "scene_illustration": MessageAssetCadenceConfig(), + kind: MessageAssetCadenceConfig() for kind in MESSAGE_ASSET_KINDS } ) auto_attach_assets: bool = True + @pydantic.field_validator("message_assets", mode="after") + @classmethod + def ensure_default_message_asset_entries(cls, value): + # configs saved before an entry existed (e.g. scene_background) come + # in without it — fill the gaps so consumers can rely on all keys + for key in MESSAGE_ASSET_KINDS: + if key not in value: + value[key] = MessageAssetCadenceConfig() + return value + class Appearance(pydantic.BaseModel): scene: SceneAppearance = SceneAppearance() diff --git a/talemate_frontend/src/components/AppConfigAppearanceAssets.vue b/talemate_frontend/src/components/AppConfigAppearanceAssets.vue index ec58edd3..2507e404 100644 --- a/talemate_frontend/src/components/AppConfigAppearanceAssets.vue +++ b/talemate_frontend/src/components/AppConfigAppearanceAssets.vue @@ -115,14 +115,42 @@ > + + +
+ mdi-image-filter-hdr +
Scene Background
+
+ + + + + + + + - + Always: Show visual on every message
Never: Never show visual inline with messages
On change: Only show when visual changes (portraits: tracked per character)

- Scene Illustration sizes: Big = full width above message, Small/Medium = inline with text, Background = fills behind the scene text + Scene Illustration covers images of the current moment ("Visualize Moment"), Scene Background covers purely environmental images ("Visualize Scene (Background)").
+ Sizes: Big = full width above message, Small/Medium = inline with text, Background = fills behind the scene text. When both types use Background, the most recent image is the active backdrop. @@ -157,6 +186,33 @@