def register_listener(self, listener, event_types='all'): """ Add a listener to this event_dispatcher. Any object with an ``on_event`` method can be added as a listener. This method should accept BearEvent as a single argument and return either nothing, or a single BearEvent, or a list of BearEvents. To choose event types to subscribe to, ``event_types`` kwarg can be set to a string or an iterable of strings. If an iterable, its elements should be event types the listener subscribes to. If a string, the following rules apply: 1. If a string equals 'all', the listener is subscribed to all currently registered event types. 2. Elif a string starts with '*', the listener is subscribed to all currently registered event types for whose type ``event_types[1:]`` is a substring (regardless of its position). For example, '*ecs' subscribes to all ECS events, like 'ecs_add', 'ecs_move', 'ecs_remove' and so on; '*move' would subscribe only to 'ecs_move' and 'ecs_remove'. 3. Else a string is interpreted as a single event type. Whether in list or string, unregistered event types raise BearLoopException. :param listener: a listener to add. :param event_types: event types to which it wants to subscribe """ if not hasattr(listener, 'on_event'): raise BearLoopException('Cannot add an object without on_event' + ' method as a listener') if isinstance(event_types, str): if event_types == 'all': # Subscribing to all events types = self.listeners.keys() elif event_types[0] == '*': # Subscribing to a group of events types = [] mask = event_types[1:] for event_type in self.listeners: if mask in event_type: types.append(event_type) else: # Subscribing to a single event type types = [event_types] else: # Subscribing to a list of event types types = event_types for event_type in types: try: self.listeners[event_type].append(listener) except KeyError: # The incorrect list elements or single value processed here raise BearLoopException('Unknown event class {}'.format( event_type))
def add_event(self, event): """ Add a BearEvent to the queue. :param event: :return: """ if not isinstance(event, BearEvent): raise BearLoopException('Only BearEvents can be added to queue') if event.event_type not in self.event_types: raise BearLoopException('Incorrect event type \"{}\"'.format( event.event_type)) self.deque.append(event)
def unregister_listener(self, listener, event_types='all'): """ Unsubscribe a listener from all or some of its event types. :param listener: listener to unsubscribe :param event_types: a list of event types to unsubscribe from or 'all'. Defaults to 'all' """ if event_types == 'all': event_types = self.listeners.keys() for event_type in event_types: if listener in self.listeners[event_type]: try: self.listeners[event_type].remove(listener) except KeyError: raise BearLoopException(f'Attempting to unsubscribe from nonexistent event type {event_type}')
def dispatch_events(self): """ Dispatch all the events to their listeners. Whatever they return is added to the queue. """"" while len(self.deque) > 0: e = self.deque.popleft() for listener in self.listeners[e.event_type]: r = listener.on_event(e) if r: if isinstance(r, BearEvent): self.add_event(r) elif isinstance(r, list): for event in r: self.add_event(event) else: raise BearLoopException('on_event returns something ' + 'other than BearEvent')
def fps(self, value): if not isinstance(value, int): raise BearLoopException('Only int acceptable as FPS') self.frame_time = 1/value