Skip to content

EventHandler

Module: terminaltexteffects.engine.base_character

Register and handle events related to a character.

Events related to character state changes (e.g. waypoint reached) can be registered with the EventHandler. When an event is triggered, the EventHandler will take the specified action (e.g. activate a Path). The EventHandler is used by the EffectCharacter class to handle events related to the character.

Attributes:

Name Type Description
character EffectCharacter

The character that the EventHandler is handling events for.

registered_events dict[tuple[Event, str], list[tuple[Action, str]]]

A dictionary of registered events. The key is a tuple of the event and the subject_id (waypoint id/scene id). The value is a list of tuples of the action and the action target (waypoint id/scene id).

layer int

The layer of the character. The layer determines the order in which characters are printed.

Note

SEGMENT_ENTERED/EXITED events will trigger the first time the character enters or exits a segment. If looping, each loop will trigger the event, but not backwards motion as is possible with the bounce easing functions.

Source code in terminaltexteffects/engine/base_character.py
class EventHandler:
    """Register and handle events related to a character.

    Events related to character state changes (e.g. waypoint reached) can be registered with the EventHandler.
    When an event is triggered, the EventHandler will take the specified action (e.g. activate a Path).
    The EventHandler is used by the EffectCharacter class to handle events related to the character.

    Attributes:
        character (EffectCharacter): The character that the EventHandler is handling events for.
        registered_events (dict[tuple[Event, str], list[tuple[Action, str]]]): A dictionary of registered events.
            The key is a tuple of the event and the subject_id (waypoint id/scene id).
            The value is a list of tuples of the action and the action target (waypoint id/scene id).
        layer (int): The layer of the character. The layer determines the order in which characters are printed.

    Note:
        SEGMENT_ENTERED/EXITED events will trigger the first time the character enters or exits a segment.
        If looping, each loop will trigger the event, but not backwards motion as is possible with the bounce easing functions.
    """

    def __init__(self, character: "EffectCharacter"):
        """Initializes the instance with the EffectCharacter object.

        Args:
            character (EffectCharacter): The character for which the EventHandler is handling events.
        """
        self.character = character
        self.layer: int = 0
        self.registered_events: dict[
            tuple[EventHandler.Event, animation.Scene | motion.Waypoint | motion.Path],
            list[
                tuple[
                    EventHandler.Action,
                    animation.Scene | motion.Waypoint | motion.Path | int | Coord | EventHandler.Callback,
                ]
            ],
        ] = {}

    class Event(Enum):
        """An Event that can be registered with the EventHandler.

        Register Events with the EventHandler using the register_event method of the EventHandler class.

        Attributes:
            SEGMENT_ENTERED (Event): A path segment has been entered.
            SEGMENT_EXITED (Event): A path segment has been exited.
            PATH_ACTIVATED (Event): A path has been activated.
            PATH_COMPLETE (Event): A path has been completed.
            PATH_HOLDING (Event): A path has entered the holding state.
            SCENE_ACTIVATED (Event): An animation scene has been activated.
            SCENE_COMPLETE (Event): An animation scene has completed.
        """

        SEGMENT_ENTERED = auto()
        SEGMENT_EXITED = auto()
        PATH_ACTIVATED = auto()
        PATH_COMPLETE = auto()
        PATH_HOLDING = auto()
        SCENE_ACTIVATED = auto()
        SCENE_COMPLETE = auto()

    class Action(Enum):
        """Actions that can be taken when an event is triggered.

        An Action is taken when an Event is triggered. Register Actions with the EventHandler using the
        register_event method of the EventHandler class.

        Attributes:
            ACTIVATE_PATH (Action): Activates a path. The action target is the path ID.
            ACTIVATE_SCENE (Action): Activates an animation scene. The action target is the scene ID.
            DEACTIVATE_PATH (Action): Deactivates a path. The action target is the path ID.
            DEACTIVATE_SCENE (Action): Deactivates an animation scene. The action target is the scene ID.
            SET_LAYER (Action): Sets the layer of the character. The action target is the layer number.
            SET_COORDINATE (Action): Sets the coordinate of the character. The action target is the coordinate.
            CALLBACK (Action): Calls a callback function. The action target is an EventHandler.Callback object.
        """

        ACTIVATE_PATH = auto()
        ACTIVATE_SCENE = auto()
        DEACTIVATE_PATH = auto()
        DEACTIVATE_SCENE = auto()
        SET_LAYER = auto()
        SET_COORDINATE = auto()
        CALLBACK = auto()

    @dataclass(init=False)
    class Callback:
        """A callback action target that can be taken when an event is triggered.

        Register callback actions with the EventHandler using the register_event method of the EventHandler class.

        """

        callback: typing.Callable
        args: tuple[typing.Any, ...]

        def __init__(self, callback: typing.Callable, *args: typing.Any):
            """Initializes the instance with the callback function and arguments.

            Args:
                callback (typing.Callable): The callback function to call.
                args (tuple[typing.Any,...]): A tuple of arguments to pass to the callback function. The first argument will be the character, followed by any additional arguments.
            """
            self.callback = callback
            self.args = args

    def register_event(
        self,
        event: Event,
        caller: animation.Scene | motion.Waypoint | motion.Path,
        action: Action,
        target: animation.Scene | motion.Waypoint | motion.Path | int | Coord | Callback,
    ) -> None:
        """Registers an event to be handled by the EventHandler.

        Args:
            event (Event): The event to register.
            caller (animation.Scene | motion.Waypoint | motion.Path): The object that triggers the event.
            action (Action): The action to take when the event is triggered.
            target (animation.Scene | motion.Waypoint | motion.Path | int | Coord | Callback): The target of the action.

        Example:
            Register an event to activate a scene when a Path is complete:
            `event_handler.register_event(EventHandler.Event.PATH_COMPLETE, some_path, EventHandler.Action.ACTIVATE_SCENE, some_scene)`
        """
        new_event = (event, caller)
        new_action = (action, target)
        if new_event not in self.registered_events:
            self.registered_events[new_event] = list()
        self.registered_events[new_event].append(new_action)

    def _handle_event(self, event: Event, caller: animation.Scene | motion.Waypoint | motion.Path) -> None:
        """Handles an event by taking the specified action.

        Args:
            event (Event): An event to handle. If the event is not registered, nothing happens.
            caller (animation.Scene | motion.Waypoint | motion.Path): The object triggering the call.
        """
        action_map = {
            EventHandler.Action.ACTIVATE_PATH: self.character.motion.activate_path,
            EventHandler.Action.ACTIVATE_SCENE: self.character.animation.activate_scene,
            EventHandler.Action.DEACTIVATE_PATH: self.character.motion.deactivate_path,
            EventHandler.Action.DEACTIVATE_SCENE: self.character.animation.deactivate_scene,
            EventHandler.Action.SET_LAYER: lambda layer: setattr(self.character, "layer", layer),
            EventHandler.Action.SET_COORDINATE: lambda coord: setattr(self.character.motion, "current_coord", coord),
            EventHandler.Action.CALLBACK: lambda callback: callback.callback(self.character, *callback.args),
        }

        if (event, caller) not in self.registered_events:
            return
        for event_action in self.registered_events[(event, caller)]:
            action, target = event_action
            action_map[action](target)  # type: ignore

Action

Bases: Enum

Actions that can be taken when an event is triggered.

An Action is taken when an Event is triggered. Register Actions with the EventHandler using the register_event method of the EventHandler class.

Attributes:

Name Type Description
ACTIVATE_PATH Action

Activates a path. The action target is the path ID.

ACTIVATE_SCENE Action

Activates an animation scene. The action target is the scene ID.

DEACTIVATE_PATH Action

Deactivates a path. The action target is the path ID.

DEACTIVATE_SCENE Action

Deactivates an animation scene. The action target is the scene ID.

SET_LAYER Action

Sets the layer of the character. The action target is the layer number.

SET_COORDINATE Action

Sets the coordinate of the character. The action target is the coordinate.

CALLBACK Action

Calls a callback function. The action target is an EventHandler.Callback object.

Source code in terminaltexteffects/engine/base_character.py
class Action(Enum):
    """Actions that can be taken when an event is triggered.

    An Action is taken when an Event is triggered. Register Actions with the EventHandler using the
    register_event method of the EventHandler class.

    Attributes:
        ACTIVATE_PATH (Action): Activates a path. The action target is the path ID.
        ACTIVATE_SCENE (Action): Activates an animation scene. The action target is the scene ID.
        DEACTIVATE_PATH (Action): Deactivates a path. The action target is the path ID.
        DEACTIVATE_SCENE (Action): Deactivates an animation scene. The action target is the scene ID.
        SET_LAYER (Action): Sets the layer of the character. The action target is the layer number.
        SET_COORDINATE (Action): Sets the coordinate of the character. The action target is the coordinate.
        CALLBACK (Action): Calls a callback function. The action target is an EventHandler.Callback object.
    """

    ACTIVATE_PATH = auto()
    ACTIVATE_SCENE = auto()
    DEACTIVATE_PATH = auto()
    DEACTIVATE_SCENE = auto()
    SET_LAYER = auto()
    SET_COORDINATE = auto()
    CALLBACK = auto()

Callback dataclass

A callback action target that can be taken when an event is triggered.

Register callback actions with the EventHandler using the register_event method of the EventHandler class.

Source code in terminaltexteffects/engine/base_character.py
@dataclass(init=False)
class Callback:
    """A callback action target that can be taken when an event is triggered.

    Register callback actions with the EventHandler using the register_event method of the EventHandler class.

    """

    callback: typing.Callable
    args: tuple[typing.Any, ...]

    def __init__(self, callback: typing.Callable, *args: typing.Any):
        """Initializes the instance with the callback function and arguments.

        Args:
            callback (typing.Callable): The callback function to call.
            args (tuple[typing.Any,...]): A tuple of arguments to pass to the callback function. The first argument will be the character, followed by any additional arguments.
        """
        self.callback = callback
        self.args = args

__init__(callback, *args)

Initializes the instance with the callback function and arguments.

Parameters:

Name Type Description Default
callback Callable

The callback function to call.

required
args tuple[Any, ...]

A tuple of arguments to pass to the callback function. The first argument will be the character, followed by any additional arguments.

()
Source code in terminaltexteffects/engine/base_character.py
def __init__(self, callback: typing.Callable, *args: typing.Any):
    """Initializes the instance with the callback function and arguments.

    Args:
        callback (typing.Callable): The callback function to call.
        args (tuple[typing.Any,...]): A tuple of arguments to pass to the callback function. The first argument will be the character, followed by any additional arguments.
    """
    self.callback = callback
    self.args = args

Event

Bases: Enum

An Event that can be registered with the EventHandler.

Register Events with the EventHandler using the register_event method of the EventHandler class.

Attributes:

Name Type Description
SEGMENT_ENTERED Event

A path segment has been entered.

SEGMENT_EXITED Event

A path segment has been exited.

PATH_ACTIVATED Event

A path has been activated.

PATH_COMPLETE Event

A path has been completed.

PATH_HOLDING Event

A path has entered the holding state.

SCENE_ACTIVATED Event

An animation scene has been activated.

SCENE_COMPLETE Event

An animation scene has completed.

Source code in terminaltexteffects/engine/base_character.py
class Event(Enum):
    """An Event that can be registered with the EventHandler.

    Register Events with the EventHandler using the register_event method of the EventHandler class.

    Attributes:
        SEGMENT_ENTERED (Event): A path segment has been entered.
        SEGMENT_EXITED (Event): A path segment has been exited.
        PATH_ACTIVATED (Event): A path has been activated.
        PATH_COMPLETE (Event): A path has been completed.
        PATH_HOLDING (Event): A path has entered the holding state.
        SCENE_ACTIVATED (Event): An animation scene has been activated.
        SCENE_COMPLETE (Event): An animation scene has completed.
    """

    SEGMENT_ENTERED = auto()
    SEGMENT_EXITED = auto()
    PATH_ACTIVATED = auto()
    PATH_COMPLETE = auto()
    PATH_HOLDING = auto()
    SCENE_ACTIVATED = auto()
    SCENE_COMPLETE = auto()

__init__(character)

Initializes the instance with the EffectCharacter object.

Parameters:

Name Type Description Default
character EffectCharacter

The character for which the EventHandler is handling events.

required
Source code in terminaltexteffects/engine/base_character.py
def __init__(self, character: "EffectCharacter"):
    """Initializes the instance with the EffectCharacter object.

    Args:
        character (EffectCharacter): The character for which the EventHandler is handling events.
    """
    self.character = character
    self.layer: int = 0
    self.registered_events: dict[
        tuple[EventHandler.Event, animation.Scene | motion.Waypoint | motion.Path],
        list[
            tuple[
                EventHandler.Action,
                animation.Scene | motion.Waypoint | motion.Path | int | Coord | EventHandler.Callback,
            ]
        ],
    ] = {}

register_event(event, caller, action, target)

Registers an event to be handled by the EventHandler.

Parameters:

Name Type Description Default
event Event

The event to register.

required
caller Scene | Waypoint | Path

The object that triggers the event.

required
action Action

The action to take when the event is triggered.

required
target Scene | Waypoint | Path | int | Coord | Callback

The target of the action.

required
Example

Register an event to activate a scene when a Path is complete: event_handler.register_event(EventHandler.Event.PATH_COMPLETE, some_path, EventHandler.Action.ACTIVATE_SCENE, some_scene)

Source code in terminaltexteffects/engine/base_character.py
def register_event(
    self,
    event: Event,
    caller: animation.Scene | motion.Waypoint | motion.Path,
    action: Action,
    target: animation.Scene | motion.Waypoint | motion.Path | int | Coord | Callback,
) -> None:
    """Registers an event to be handled by the EventHandler.

    Args:
        event (Event): The event to register.
        caller (animation.Scene | motion.Waypoint | motion.Path): The object that triggers the event.
        action (Action): The action to take when the event is triggered.
        target (animation.Scene | motion.Waypoint | motion.Path | int | Coord | Callback): The target of the action.

    Example:
        Register an event to activate a scene when a Path is complete:
        `event_handler.register_event(EventHandler.Event.PATH_COMPLETE, some_path, EventHandler.Action.ACTIVATE_SCENE, some_scene)`
    """
    new_event = (event, caller)
    new_action = (action, target)
    if new_event not in self.registered_events:
        self.registered_events[new_event] = list()
    self.registered_events[new_event].append(new_action)