Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 32 additions & 2 deletions src/ui_utils/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,31 @@

from .chat import show_chat_message
from .clipboard import clipboard_copy, clipboard_paste
from .hud_message import show_hud_message
from .hud_message import (
ERewardPopup,
display_button_prompt,
hide_button_prompt,
show_button_prompt,
show_discovery_message,
show_hud_message,
show_reward_popup,
show_second_wind_notification,
)
from .online_message import (
display_blocking_message,
display_message,
hide_blocking_message,
hide_message,
show_blocking_message,
show_message,
)
from .option_box import OptionBox, OptionBoxButton
from .reorder_box import ReorderBox
from .training_box import EBackButtonScreen, TrainingBox

__all__: tuple[str, ...] = (
"EBackButtonScreen",
"ERewardPopup",
"OptionBox",
"OptionBoxButton",
"ReorderBox",
Expand All @@ -18,11 +36,23 @@
"__version_info__",
"clipboard_copy",
"clipboard_paste",
"display_blocking_message",
"display_button_prompt",
"display_message",
"hide_blocking_message",
"hide_button_prompt",
"hide_message",
"show_blocking_message",
"show_button_prompt",
"show_chat_message",
"show_discovery_message",
"show_hud_message",
"show_message",
"show_reward_popup",
"show_second_wind_notification",
)

__version_info__: tuple[int, int] = (1, 3)
__version_info__: tuple[int, int] = (1, 4)
__version__: str = f"{__version_info__[0]}.{__version_info__[1]}"
__author__: str = "bl-sdk"

Expand Down
159 changes: 158 additions & 1 deletion src/ui_utils/hud_message.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,36 @@
from collections.abc import Iterator
from contextlib import contextmanager
from types import EllipsisType
from typing import TYPE_CHECKING

import unrealsdk
from unrealsdk import unreal

from mods_base import get_pc

__all__: tuple[str, ...] = ("show_hud_message",)
if TYPE_CHECKING:
from enum import IntEnum

class ERewardPopup(IntEnum):
ERP_BadassToken = 0
ERP_CharacterHead = 1
ERP_CharacterSkin = 2
ERP_VehicleSkin = 3
ERP_MAX = 4

else:
ERewardPopup = unrealsdk.find_enum("ERewardPopup")

__all__: tuple[str, ...] = (
"ERewardPopup",
"display_button_prompt",
"hide_button_prompt",
"show_button_prompt",
"show_discovery_message",
"show_hud_message",
"show_reward_popup",
"show_second_wind_notification",
)


def show_hud_message(title: str, msg: str, duration: float = 2.5) -> None:
Expand Down Expand Up @@ -39,3 +67,132 @@ def show_hud_message(title: str, msg: str, duration: float = 2.5) -> None:
True,
0,
)


def show_second_wind_notification(
msg: str,
ui_sound: unreal.UObject | None | EllipsisType = ...,
) -> None:
"""
Displays a big notification message in the main in game hud.

Uses the message style of the Second Wind notification.

Note this should not be used for critical messages, it may silently fail at any point.

Args:
msg: The message to display.
ui_sound: An optional AkEvent to play when the message is displayed.
If Ellipsis, default sound will be used.
"""
if (hud_movie := get_pc().GetHUDMovie()) is None:
return

sound_backup = None
sw_interaction = None
for interaction in hud_movie.InteractionOverrideSounds:
if interaction.Interaction == "SecondWind":
sound_backup = interaction.AkEvent
sw_interaction = interaction

if ui_sound is not Ellipsis and sw_interaction:
sw_interaction.AkEvent = ui_sound

backup_string = hud_movie.SecondWindString
hud_movie.SecondWindString = msg
hud_movie.DisplaySecondWind()
hud_movie.SecondWindString = backup_string
if sw_interaction:
sw_interaction.AkEvent = sound_backup


def show_discovery_message(msg: str, show_discovered_message: bool = False) -> None:
"""
Displays a message in the top center of the screen.

Uses the style of the new area discovered message.

Note this should not be used for critical messages, it may silently fail at any point.

Args:
msg: The message to display.
show_discovered_message: If True, the message 'You have discovered' header will show.
"""
if (hud_movie := get_pc().GetHUDMovie()) is None:
return
hud_movie.ShowWorldDiscovery("", msg, show_discovered_message, False)


def show_reward_popup(
msg: str,
reward_type: ERewardPopup = ERewardPopup.ERP_BadassToken,
) -> None:
"""
Displays a reward popup with the given message and reward type.

Note this should not be used for critical messages, it may silently fail at any point.

Args:
msg: The message to display in the popup.
reward_type: The type of reward to display. Defaults to ERewardPopup.ERP_BadassToken.
"""
if (hud_movie := get_pc().GetHUDMovie()) is None:
return

icon = {
ERewardPopup.ERP_BadassToken: "token",
ERewardPopup.ERP_CharacterHead: "head",
ERewardPopup.ERP_CharacterSkin: "playerSkin",
ERewardPopup.ERP_VehicleSkin: "vehicleSkin",
}.get(reward_type, "token")

hud_movie.SingleArgInvokeS("p1.badassToken.gotoAndStop", "stop")
hud_movie.SingleArgInvokeS("p1.badassToken.gotoAndStop", "go")
hud_movie.SingleArgInvokeS("p1.badassToken.inner.gotoAndStop", icon)
hud_movie.SetVariableString("p1.badassToken.inner.dispText.text", msg)


def show_button_prompt(reason: str, button: str) -> None:
"""
Displays a contextual prompt with the given text and button string.

This will stay visible until it is explicitly hidden, see `hide_contextual_prompt`.

Note this should not be used for critical messages, it may silently fail at any point.

Args:
reason: The text top to display in the prompt.
button: The button string to display in the prompt.
"""

if (hud_movie := get_pc().GetHUDMovie()) is None:
return
contextual_prompt = hud_movie.ContextualPromptButtonString
hud_movie.ContextualPromptButtonString = button
hud_movie.ToggleContextualPrompt(reason, True)
hud_movie.ContextualPromptButtonString = contextual_prompt


def hide_button_prompt() -> None:
"""Hides the currently displayed contextual prompt, if any."""
if (hud_movie := get_pc().GetHUDMovie()) is None:
return
hud_movie.ToggleContextualPrompt("", False)


@contextmanager
def display_button_prompt(reason: str, button: str) -> Iterator[None]:
"""
Context manager to display and hide a contextual prompt.

This will display the prompt when entering the context and hide it when exiting.

Args:
reason: The text to display in the prompt.
button: The button string to display in the prompt.
"""
show_button_prompt(reason, button)
try:
yield
finally:
hide_button_prompt()
102 changes: 102 additions & 0 deletions src/ui_utils/online_message.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
from collections.abc import Iterator
from contextlib import contextmanager

from mods_base import get_pc

__all__: tuple[str, ...] = (
"display_blocking_message",
"display_message",
"hide_blocking_message",
"hide_message",
"show_blocking_message",
"show_message",
)


def show_blocking_message(msg: str, reason: str | None = None) -> None:
"""
Displays a blocking message with the given text.

This message will stay until it is explicitly hidden, see `hide_blocking_message`.

This message will block any input until it is hidden.

Args:
msg: The message to display.
reason: An optional reason for the blocking message, which will be displayed as a subtitle.
If None, the default text will show.
"""
if (msg_movie := get_pc().GetOnlineMessageMovie()) is None:
return

backup = msg_movie.BlockingSubtitle
msg_movie.BlockingSubtitle = reason if reason is not None else backup
msg_movie.DisplayBlockingMessage(msg)
msg_movie.BlockingSubtitle = backup


def hide_blocking_message() -> None:
"""Hides the currently displayed blocking message, if any."""
if (msg_movie := get_pc().GetOnlineMessageMovie()) is None:
return

msg_movie.HideBlocking()


@contextmanager
def display_blocking_message(msg: str, reason: str | None = None) -> Iterator[None]:
"""
Context manager to display and hide a blocking message.

This will display the message when entering the context and hide it when exiting.

Args:
msg: The message to display.
reason: An optional reason for the blocking message, which will be displayed as a subtitle.
If None, the default text will show.
"""
show_blocking_message(msg, reason)
try:
yield
finally:
hide_blocking_message()


def show_message(msg: str) -> None:
"""
Displays a message on the left side of the screen.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this type still needs a better name


This message will stay until it is explicitly hidden, see `hide_message`.

Args:
msg: The message to display.
"""
if (msg_movie := get_pc().GetOnlineMessageMovie()) is None:
return

msg_movie.DisplayMessage(msg)


def hide_message() -> None:
"""Hides the currently displayed message in the online message movie."""
if (msg_movie := get_pc().GetOnlineMessageMovie()) is None:
return

msg_movie.Hide()


@contextmanager
def display_message(msg: str) -> Iterator[None]:
"""
Context manager to display and hide a message.

This will display the message when entering the context and hide it when exiting.

Args:
msg: The message to display.
"""
show_message(msg)
try:
yield
finally:
hide_message()
Loading