DialogPlugin¶
Manages dialog display and pagination for game conversations.
Location¶
- Implementation: src/pedre/plugins/dialog/plugin.py
- Base class: src/pedre/plugins/dialog/base.py
- Events: src/pedre/plugins/dialog/events.py
- Actions: src/pedre/plugins/dialog/actions.py
Configuration¶
The DialogPlugin uses the following settings from pedre.conf.settings:
Behavior Settings¶
DIALOG_AUTO_CLOSE_DEFAULT- Default auto-close behavior when not explicitly specified (default:False)DIALOG_AUTO_CLOSE_DURATION- Seconds to wait after text reveal before auto-closing (default:0.5)DIALOG_CHAR_REVEAL_SPEED- Characters per second for text reveal animation (default:20)DIALOG_INSTANT_TEXT_DEFAULT- Whether text appears instantly by default (default:False)DIALOG_SHOW_HELP- Whether to show instruction text (default:True)DIALOG_SHOW_PAGINATION- Whether to show page indicators (default:True)
Input Settings¶
DIALOG_KEY_ADVANCE- Key for advancing dialog pages and closing dialogs (default:"SPACE")
Layout Settings¶
DIALOG_BOX_WIDTH_PERCENT- Dialog box width as fraction of window width (default:0.75)DIALOG_BOX_MAX_WIDTH- Maximum dialog box width in pixels (default:800)DIALOG_BOX_MIN_WIDTH- Minimum dialog box width in pixels (default:400)DIALOG_BOX_HEIGHT_PERCENT- Dialog box height as fraction of window height (default:0.25)DIALOG_BOX_MIN_HEIGHT- Minimum dialog box height in pixels (default:150)DIALOG_VERTICAL_POSITION- Vertical position from bottom as fraction of window height (default:0.25)DIALOG_OVERLAY_ALPHA- Transparency of background overlay (0-255, default:128)DIALOG_BORDER_WIDTH- Width of dialog box border in pixels (default:3)DIALOG_PADDING_HORIZONTAL- Horizontal padding inside dialog box in pixels (default:20)DIALOG_PADDING_VERTICAL- Vertical padding inside dialog box in pixels (default:20)DIALOG_NPC_NAME_OFFSET- Vertical offset of NPC name from top of dialog box (default:30)DIALOG_FOOTER_OFFSET- Vertical offset of footer elements from bottom of dialog box (default:20)
Font Settings¶
DIALOG_NPC_NAME_FONT_SIZE- Font size for NPC name text (default:20)DIALOG_TEXT_FONT_SIZE- Font size for dialog message text (default:16)DIALOG_INSTRUCTION_FONT_SIZE- Font size for instruction text (default:12)DIALOG_PAGE_INDICATOR_FONT_SIZE- Font size for page indicator text (default:10)
Text Labels¶
DIALOG_TEXT_NEXT_PAGE- Instruction for advancing to next page (default:"Press SPACE for next page")DIALOG_TEXT_CLOSE- Instruction for closing dialog (default:"Press SPACE to close")DIALOG_TEXT_PAGE- Label for page indicator (default:"Page")
These can be overridden in your project's settings.py:
# Custom dialog settings
DIALOG_AUTO_CLOSE_DEFAULT = True
DIALOG_AUTO_CLOSE_DURATION = 1.0
DIALOG_CHAR_REVEAL_SPEED = 30
DIALOG_KEY_ADVANCE = "RETURN"
DIALOG_BOX_WIDTH_PERCENT = 0.8
DIALOG_TEXT_FONT_SIZE = 18
Public API¶
Dialog Display¶
show_dialog¶
show_dialog(npc_name: str, text: list[str], *, instant: bool = settings.DIALOG_INSTANT_TEXT_DEFAULT, auto_close: bool = settings.DIALOG_AUTO_CLOSE_DEFAULT, dialog_level: int | None = None, npc_key: str | None = None) -> None
Display a dialog from an NPC.
Parameters:
npc_name- Display name of the character speaking (shown at top of dialog box)text- List of dialog text strings, one per page. Each string can contain multiple lines and will be wrapped automaticallyinstant- IfTrue, text appears immediately without letter-by-letter reveal. Defaults tosettings.DIALOG_INSTANT_TEXT_DEFAULT. Useful for narration, system messages, or cutscenesauto_close- IfTrue, dialog automatically closes after configured duration. IfFalse, player must manually close. Defaults tosettings.DIALOG_AUTO_CLOSE_DEFAULTdialog_level- Optional dialog level for event tracking. Used when emittingDialogClosedEventnpc_key- Optional NPC key name for event tracking. If provided, this is used inDialogClosedEventinstead ofnpc_name. Use this when the display name differs from the NPC's key name
Example:
# Basic dialog with manual advancement
dialog_plugin.show_dialog("Martin", [
"Hello! I'm Martin, the village elder.",
"Welcome to our humble town.",
"Feel free to explore and talk to the other villagers!"
])
# Instant narration dialog
dialog_plugin.show_dialog(
"Narrator",
["The world fades to black..."],
instant=True
)
# Auto-closing cutscene dialog
dialog_plugin.show_dialog(
"Plugin",
["Achievement unlocked!"],
instant=True,
auto_close=True
)
# Dialog with level tracking
dialog_plugin.show_dialog(
"Merchant",
["Thanks for your help!"],
dialog_level=1,
npc_key="merchant"
)
Notes:
- Each string in the text list becomes one page of dialog
- Players advance through pages by pressing the configured
DIALOG_KEY_ADVANCEkey (default: SPACE) - Text reveals letter-by-letter unless
instant=Trueorsettings.DIALOG_INSTANT_TEXT_DEFAULT=True - Auto-close timer starts after text is fully revealed
- Publishes
DialogOpenedEventwhen dialog is shown
close_dialog() -> None¶
Close the currently showing dialog.
Example:
# Force close on ESC key
if key == arcade.key.ESCAPE and dialog_plugin.is_showing():
dialog_plugin.close_dialog()
Notes:
- Dismisses the dialog overlay and clears all dialog state
- Called automatically when the player advances past the last page
- Does not publish
DialogClosedEvent(that only happens via player interaction)
advance_page¶
advance_page() -> bool
Advance to the next page or close dialog if on last page.
Returns:
Trueif dialog was closed (was on last page)Falseif text was revealed or advanced to next page
Example:
# In your input handler
if symbol == arcade.key.SPACE and dialog_plugin.is_showing():
was_closed = dialog_plugin.advance_page()
if was_closed:
# Dialog finished, can trigger follow-up actions
pass
Notes:
- If text is still being revealed, it instantly completes the reveal animation
- Otherwise, advances to the next page if there are more pages
- Closes the dialog and returns
Trueif on the last page - Called automatically by the DialogPlugin's
on_key_pressmethod
State Queries¶
is_showing¶
is_showing() -> bool
Check if dialog is currently displayed.
Returns:
Trueif a dialog is currently showing,Falseotherwise
Example:
get_current_page¶
get_current_page() -> DialogPage | None
Get the currently displayed page.
Returns:
DialogPageobject withnpc_name,text,page_num,total_pagesNoneif no dialog is showing
Example:
page = dialog_plugin.get_current_page()
if page:
print(f"{page.npc_name}: {page.text}")
print(f"Page {page.page_num + 1}/{page.total_pages}")
Dialog State Management¶
set_current_dialog_level¶
set_current_dialog_level(dialog_level: int) -> None
Set the current dialog level for event tracking.
Parameters:
dialog_level- Dialog level to set
Notes:
- Used internally for event emission
- Typically set automatically when showing dialog
set_current_npc_name¶
set_current_npc_name(npc_name: str) -> None
Set the current NPC name for event tracking.
Parameters:
npc_name- NPC name to set
Notes:
- Used internally for event emission
- Typically set automatically when showing dialog
Text Reveal Control¶
speed_up_text¶
speed_up_text() -> None
Instantly reveal all text on the current page.
Example:
Notes:
- Called automatically when player presses SPACE while text is revealing
- Useful for implementing skip functionality
Plugin Lifecycle¶
setup¶
setup(context: GameContext) -> None
Initialize the dialog plugin with game settings.
Parameters:
context- Game context for accessing the event bus
Notes:
- Called automatically by the PluginLoader
- Stores the game context for event publishing
cleanup¶
cleanup() -> None
Clean up dialog resources when the scene unloads.
Notes:
- Closes any open dialog and clears text objects
- Called automatically by the PluginLoader
update¶
update(delta_time: float) -> None
Update the dialog text reveal animation and auto-close timer.
Parameters:
delta_time- Time elapsed since last update, in seconds
Notes:
- Called automatically every frame
- Handles text reveal animation at rate controlled by
DIALOG_CHAR_REVEAL_SPEED - Manages auto-close countdown when enabled
on_key_press¶
on_key_press(symbol: int, modifiers: int) -> bool
Handle input for dialog advancement.
Parameters:
symbol- Arcade key constantmodifiers- Modifier key bitfield
Returns:
Trueif dialog is showing and event was consumedFalseif dialog is not showing
Notes:
- Called automatically by the PluginLoader
- Handles the configured
DIALOG_KEY_ADVANCEkey to advance pages or close dialog - Publishes
DialogClosedEventwhen dialog closes
on_draw_ui¶
on_draw_ui() -> None
Draw the dialog overlay in screen coordinates.
Notes:
- Called automatically by the PluginLoader during UI draw phase
- Renders the complete dialog UI on top of the game world
- Uses lazy initialization for text objects
Dialog Configuration Files¶
Dialogs are typically loaded from JSON files in the assets/dialogs/ directory. Each file follows the pattern <scene>_dialogs.json (e.g., casa_dialogs.json).
JSON Structure¶
{
"npc_name": {
"0": {
"name": "Display Name",
"text": [
"First page of dialog",
"Second page of dialog"
]
},
"1": {
"name": "Display Name",
"text": ["Next dialog level"],
"conditions": [
{
"check": "inventory_accessed",
"equals": true
}
],
"on_condition_fail": [
{
"type": "dialog",
"speaker": "Display Name",
"text": ["Alternative text if condition fails"]
}
]
}
}
}
Fields:
name- Optional display name shown in the dialog box instead of the NPC's key nametext- Array of strings, one per pageconditions- Optional array of conditions that must be met to show this dialogon_condition_fail- Optional array of actions to run if conditions fail
Example Dialog File¶
{
"martin": {
"0": {
"name": "Martin",
"text": [
"Buenos días mi amor! Feliz cumpleaños!",
"Te hice un café, me acompañas a tomarlo?"
]
},
"1": {
"name": "Martin",
"text": ["Qué hermoso día, no?"],
"conditions": [
{
"check": "inventory_accessed",
"equals": true
}
]
}
},
"merchant": {
"0": {
"text": [
"Welcome to my shop!",
"I have the finest wares in town."
]
}
}
}
Events¶
DialogOpenedEvent¶
Published when a dialog is shown to the player.
Attributes:
npc_name: str- Name of the NPC whose dialog was openeddialog_level: int- Conversation level at the time dialog was shown
Script Trigger Example:
{
"trigger": {
"event": "dialog_opened",
"npc": "martin",
"dialog_level": 1
},
"actions": [
{"type": "play_sfx", "sound": "dialog_open.wav"}
]
}
DialogClosedEvent¶
Published when a dialog is dismissed by the player.
Attributes:
npc_name: str- Name of the NPC whose dialog was closeddialog_level: int- Conversation level at the time dialog was shown
Script Trigger Example:
{
"trigger": {
"event": "dialog_closed",
"npc": "martin",
"dialog_level": 0
},
"actions": [
{"type": "set_dialog_level", "npc": "martin", "level": 1}
]
}
Notes:
- Trigger filters (
npc,dialog_level) are optional - Omit
npcto trigger for any NPC - Omit
dialog_levelto trigger at any level
Actions¶
DialogAction¶
Show a dialog to the player.
Type: dialog
Parameters:
speaker: str- Name of the character speakingtext: list[str]- List of dialog pages to showinstant: bool- IfTrue, text appears immediately without letter-by-letter reveal. Defaults tosettings.DIALOG_INSTANT_TEXT_DEFAULT(optional)auto_close: bool- IfTrue, dialog automatically closes after configured duration. IfFalse, player must manually close. Defaults tosettings.DIALOG_AUTO_CLOSE_DEFAULT(optional)
Example:
{
"type": "dialog",
"speaker": "Narrator",
"text": ["The world fades to black..."],
"instant": true,
"auto_close": true
}
Notes:
- Action completes immediately after queuing the dialog
- Use
WaitForDialogCloseActionto wait for player to dismiss the dialog
WaitForDialogCloseAction¶
Wait for dialog to be closed.
Type: wait_for_dialog_close
Parameters: None
Example:
[
{"type": "dialog", "speaker": "Martin", "text": ["Hello!"]},
{"type": "wait_for_dialog_close"},
{"type": "dialog", "speaker": "Yema", "text": ["Hi there!"]}
]
Notes:
- Pauses script execution until the player dismisses the currently showing dialog
- Essential for creating proper dialog sequences where each message should be read before continuing
Custom Dialog Implementation¶
If you need to replace the dialog plugin with a custom implementation, you can extend the DialogBasePlugin abstract base class.
DialogBasePlugin¶
Location: src/pedre/plugins/dialog/base.py
The DialogBasePlugin class defines the minimum interface that any dialog plugin must implement.
Required Methods¶
Your custom dialog plugin must implement these abstract methods:
from pedre.conf import settings
from pedre.plugins.dialog.base import DialogBasePlugin
class CustomDialogPlugin(DialogBasePlugin):
"""Custom dialog implementation."""
name = "dialog"
dependencies = ["npc", "interaction"]
def show_dialog(
self,
npc_name: str,
text: list[str],
*,
instant: bool = settings.DIALOG_INSTANT_TEXT_DEFAULT,
auto_close: bool = settings.DIALOG_AUTO_CLOSE_DEFAULT,
dialog_level: int | None = None,
npc_key: str | None = None,
) -> None:
"""Show a dialog from an NPC."""
...
def set_current_dialog_level(self, dialog_level: int) -> None:
"""Set current dialog level."""
...
def set_current_npc_name(self, npc_name: str) -> None:
"""Set current NPC name."""
...
def is_showing(self) -> bool:
"""Verify if dialog is showing."""
...
Registration¶
Register your custom dialog plugin using the @PluginRegistry.register decorator:
from pedre.plugins.registry import PluginRegistry
from pedre.plugins.dialog.base import DialogBasePlugin
@PluginRegistry.register
class CustomDialogPlugin(DialogBasePlugin):
name = "dialog"
dependencies = ["npc", "interaction"]
# ... implement all abstract methods ...
Notes on Custom Implementation¶
- Your custom plugin inherits from
BasePlugin(viaDialogBasePlugin), so you must implement the standard plugin lifecycle methods:setup(),cleanup(), andon_key_press() - The
roleattribute is set to"dialog_plugin"in the base class - Your implementation can use any rendering backend, not just Arcade's text system
- Register your custom dialog plugin in your project's
INSTALLED_PLUGINSsetting before the default"pedre.plugins.dialog"to replace it
Example Custom Implementation:
# In myproject/plugins/custom_dialog.py
from pedre.plugins.registry import PluginRegistry
from pedre.plugins.dialog.base import DialogBasePlugin
@PluginRegistry.register
class RichTextDialogPlugin(DialogBasePlugin):
"""Custom dialog plugin with rich text support."""
name = "dialog"
dependencies = ["npc", "interaction"]
def __init__(self):
self.showing = False
self.rich_text_renderer = RichTextRenderer()
# ... rest of initialization ...
def show_dialog(
self,
npc_name: str,
text: list[str],
*,
instant: bool = settings.DIALOG_INSTANT_TEXT_DEFAULT,
auto_close: bool = settings.DIALOG_AUTO_CLOSE_DEFAULT,
dialog_level: int | None = None,
npc_key: str | None = None,
) -> None:
# Custom rich text dialog display logic
self.rich_text_renderer.render(npc_name, text)
self.showing = True
# ... implement other abstract methods ...
# In myproject/settings.py
INSTALLED_PLUGINS = [
"myproject.plugins.custom_dialog", # Load custom dialog first
"pedre.plugins.camera",
"pedre.plugins.audio",
# ... rest of plugins (omit "pedre.plugins.dialog") ...
]
Usage Examples¶
Basic Dialog Interaction¶
# Show a simple greeting
dialog_plugin.show_dialog("Guard", [
"Halt! Who goes there?",
"State your business in our town."
])
Cutscene with Auto-Close¶
# Narration that auto-advances
dialog_plugin.show_dialog(
"Narrator",
[
"A long time ago...",
"In a land far away...",
"A hero was born."
],
instant=True,
auto_close=True
)
Scripted Dialog Sequence¶
{
"trigger": {
"event": "npc_interacted",
"npc": "martin"
},
"actions": [
{
"type": "dialog",
"speaker": "Martin",
"text": ["Hello!", "How are you today?"]
},
{
"type": "wait_for_dialog_close"
},
{
"type": "set_dialog_level",
"npc": "martin",
"level": 1
}
]
}
Dialog with Event Tracking¶
# Show dialog with level tracking for scripts
dialog_plugin.show_dialog(
"Elder",
["You have completed the first trial."],
dialog_level=1,
npc_key="elder"
)
# This will publish DialogOpenedEvent(npc_name="elder", dialog_level=1)
# And DialogClosedEvent(npc_name="elder", dialog_level=1) when dismissed
See Also¶
- AudioPlugin - Background music and sound effects
- ScriptPlugin - Event-driven scripting
- NPCPlugin - NPC state and interactions
- Configuration Guide