From e9ec5e0c93d4fa4787cb4f7501775f7995e1845e Mon Sep 17 00:00:00 2001 From: Sahil Makhijani Date: Tue, 2 Feb 2021 15:59:27 +0530 Subject: [PATCH] Added Concept of Event Listners and Event Dispatcher --- manimlib/event/__init__.py | 6 ++ manimlib/event/event_dispatcher.py | 92 ++++++++++++++++++++++++++++++ manimlib/event/event_listner.py | 15 +++++ manimlib/event/event_type.py | 11 ++++ 4 files changed, 124 insertions(+) create mode 100644 manimlib/event/__init__.py create mode 100644 manimlib/event/event_dispatcher.py create mode 100644 manimlib/event/event_listner.py create mode 100644 manimlib/event/event_type.py diff --git a/manimlib/event/__init__.py b/manimlib/event/__init__.py new file mode 100644 index 00000000..2702617b --- /dev/null +++ b/manimlib/event/__init__.py @@ -0,0 +1,6 @@ +from manimlib.event.event_dispatcher import EventDispatcher + + +# This is supposed to be a Singleton +# i.e., during runtime there should be only one object of Event Dispatcher +EVENT_DISPATCHER = EventDispatcher() diff --git a/manimlib/event/event_dispatcher.py b/manimlib/event/event_dispatcher.py new file mode 100644 index 00000000..2d6cddad --- /dev/null +++ b/manimlib/event/event_dispatcher.py @@ -0,0 +1,92 @@ +import numpy as np + +from manimlib.event.event_type import EventType +from manimlib.event.event_listner import EventListner + + +class EventDispatcher(object): + def __init__(self): + self.event_listners = { + event_type: [] + for event_type in EventType + } + self.mouse_point = np.array((0., 0., 0.)) + self.mouse_drag_point = np.array((0., 0., 0.)) + self.pressed_keys = set() + self.draggable_object_listners = [] + + def add_listner(self, event_listner): + assert(isinstance(event_listner, EventListner)) + self.event_listners[event_listner.event_type].append(event_listner) + return self + + def remove_listner(self, event_listner): + assert(isinstance(event_listner, EventListner)) + try: + while event_listner in self.event_listners[event_listner.event_type]: + self.event_listners[event_listner.event_type].remove(event_listner) + except: + # raise ValueError("Handler is not handling this event, so cannot remove it.") + pass + return self + + def dispatch(self, event_type, **event_data): + + if event_type == EventType.MouseMotionEvent: + self.mouse_point = event_data["point"] + elif event_type == EventType.MouseDragEvent: + self.mouse_drag_point = event_data["point"] + elif event_type == EventType.KeyPressEvent: + self.pressed_keys.add(event_data["symbol"]) # Modifiers? + elif event_type == EventType.KeyReleaseEvent: + self.pressed_keys.difference_update({event_data["symbol"]}) # Modifiers? + elif event_type == EventType.MousePressEvent: + self.draggable_object_listners = [ + listner + for listner in self.event_listners[EventType.MouseDragEvent] + if listner.mobject.is_point_touching(self.mouse_point) + ] + elif event_type == EventType.MouseReleaseEvent: + self.draggable_object_listners = [] + + propagate_event = None + + if event_type == EventType.MouseDragEvent: + for listner in self.draggable_object_listners: + assert(isinstance(listner, EventListner)) + propagate_event = listner.callback(listner.mobject, event_data) + if propagate_event is not None and propagate_event is False: + return propagate_event + + elif event_type.value.startswith('mouse'): + for listner in self.event_listners[event_type]: + if listner.mobject.is_point_touching(self.mouse_point): + propagate_event = listner.callback( + listner.mobject, event_data) + if propagate_event is not None and propagate_event is False: + return propagate_event + + elif event_type.value.startswith('key'): + for listner in self.event_listners[event_type]: + propagate_event = listner.callback(listner.mobject, event_data) + if propagate_event is not None and propagate_event is False: + return propagate_event + + return propagate_event + + def get_listners_count(self): + return sum([len(value) for key, value in self.event_listners.items()]) + + def get_mouse_point(self): + return self.mouse_point + + def get_mouse_drag_point(self): + return self.mouse_drag_point + + def is_key_pressed(self, symbol): + return (symbol in self.pressed_keys) + + __iadd__ = add_listner + __isub__ = remove_listner + __call__ = dispatch + __len__ = get_listners_count diff --git a/manimlib/event/event_listner.py b/manimlib/event/event_listner.py new file mode 100644 index 00000000..2f8663f7 --- /dev/null +++ b/manimlib/event/event_listner.py @@ -0,0 +1,15 @@ +class EventListner(object): + def __init__(self, mobject, event_type, event_callback): + self.mobject = mobject + self.event_type = event_type + self.callback = event_callback + + def __eq__(self, o: object) -> bool: + return_val = False + try: + return_val = self.callback == o.callback \ + and self.mobject == o.mobject \ + and self.event_type == o.event_type + except: + pass + return return_val diff --git a/manimlib/event/event_type.py b/manimlib/event/event_type.py new file mode 100644 index 00000000..6cd9f73e --- /dev/null +++ b/manimlib/event/event_type.py @@ -0,0 +1,11 @@ +from enum import Enum + + +class EventType(Enum): + MouseMotionEvent = 'mouse_motion_event' + MousePressEvent = 'mouse_press_event' + MouseReleaseEvent = 'mouse_release_event' + MouseDragEvent = 'mouse_drag_event' + MouseScrollEvent = 'mouse_scroll_event' + KeyPressEvent = 'key_press_event' + KeyReleaseEvent = 'key_release_event'