mirror of
https://github.com/3b1b/manim.git
synced 2025-07-28 12:32:36 +08:00
Merge pull request #1335 from sahilmakhijani/master
Refactored Event Handling Mechanism
This commit is contained in:
6
manimlib/event_handler/__init__.py
Normal file
6
manimlib/event_handler/__init__.py
Normal file
@ -0,0 +1,6 @@
|
||||
from manimlib.event_handler.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()
|
92
manimlib/event_handler/event_dispatcher.py
Normal file
92
manimlib/event_handler/event_dispatcher.py
Normal file
@ -0,0 +1,92 @@
|
||||
import numpy as np
|
||||
|
||||
from manimlib.event_handler.event_type import EventType
|
||||
from manimlib.event_handler.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
|
15
manimlib/event_handler/event_listner.py
Normal file
15
manimlib/event_handler/event_listner.py
Normal file
@ -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
|
11
manimlib/event_handler/event_type.py
Normal file
11
manimlib/event_handler/event_type.py
Normal file
@ -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'
|
@ -26,42 +26,39 @@ class MotionMobject(Mobject):
|
||||
super().__init__(**kwargs)
|
||||
assert(isinstance(mobject, Mobject))
|
||||
self.mobject = mobject
|
||||
self.mobject.listen_to_events = True
|
||||
self.mobject.on_mouse_drag = self.mob_on_mouse_drag
|
||||
self.mobject.add_mouse_drag_listner(self.mob_on_mouse_drag)
|
||||
# To avoid locking it as static mobject
|
||||
self.mobject.add_updater(lambda mob: None)
|
||||
self.add(mobject)
|
||||
|
||||
def mob_on_mouse_drag(self, point, d_point, buttons, modifiers):
|
||||
self.mobject.move_to(point)
|
||||
def mob_on_mouse_drag(self, mob, event_data):
|
||||
mob.move_to(event_data["point"])
|
||||
return False
|
||||
|
||||
|
||||
class Button(Mobject):
|
||||
"""
|
||||
Pass any mobject and register an on_click method
|
||||
|
||||
The on_click method takes mobject as argument like updater
|
||||
"""
|
||||
|
||||
def __init__(self, mobject, on_click, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
assert(isinstance(mobject, Mobject))
|
||||
self.on_click = on_click
|
||||
self.mobject = mobject
|
||||
self.mobject.listen_to_events = True
|
||||
self.mobject.on_mouse_press = self.mob_on_mouse_press
|
||||
self.mobject.add_mouse_press_listner(self.mob_on_mouse_press)
|
||||
self.add(self.mobject)
|
||||
|
||||
def mob_on_mouse_press(self, point, button, mods):
|
||||
self.on_click()
|
||||
def mob_on_mouse_press(self, mob, event_data):
|
||||
self.on_click(mob)
|
||||
return False
|
||||
|
||||
|
||||
# Controls
|
||||
|
||||
class ControlMobject(ValueTracker):
|
||||
CONFIG = {
|
||||
"listen_to_events": True
|
||||
}
|
||||
|
||||
def __init__(self, value, *mobjects, **kwargs):
|
||||
super().__init__(value=value, **kwargs)
|
||||
self.add(*mobjects)
|
||||
@ -100,6 +97,7 @@ class EnableDisableButton(ControlMobject):
|
||||
digest_config(self, kwargs)
|
||||
self.box = Rectangle(**self.rect_kwargs)
|
||||
super().__init__(value, self.box, **kwargs)
|
||||
self.add_mouse_press_listner(self.on_mouse_press)
|
||||
|
||||
def assert_value(self, value):
|
||||
assert(isinstance(value, bool))
|
||||
@ -113,8 +111,8 @@ class EnableDisableButton(ControlMobject):
|
||||
def toggle_value(self):
|
||||
super().set_value(not self.get_value())
|
||||
|
||||
def on_mouse_press(self, point, button, mods):
|
||||
self.toggle_value()
|
||||
def on_mouse_press(self, mob, event_data):
|
||||
mob.toggle_value()
|
||||
return False
|
||||
|
||||
|
||||
@ -143,6 +141,7 @@ class Checkbox(ControlMobject):
|
||||
self.box = Rectangle(**self.rect_kwargs)
|
||||
self.box_content = self.get_checkmark() if value else self.get_cross()
|
||||
super().__init__(value, self.box, self.box_content, **kwargs)
|
||||
self.add_mouse_press_listner(self.on_mouse_press)
|
||||
|
||||
def assert_value(self, value):
|
||||
assert(isinstance(value, bool))
|
||||
@ -156,8 +155,8 @@ class Checkbox(ControlMobject):
|
||||
else:
|
||||
self.box_content.become(self.get_cross())
|
||||
|
||||
def on_mouse_press(self, point, button, mods):
|
||||
self.toggle_value()
|
||||
def on_mouse_press(self, mob, event_data):
|
||||
mob.toggle_value()
|
||||
return False
|
||||
|
||||
# Helper methods
|
||||
@ -189,9 +188,6 @@ class Checkbox(ControlMobject):
|
||||
|
||||
class LinearNumberSlider(ControlMobject):
|
||||
CONFIG = {
|
||||
# Since, only slider circle listnes to drag event
|
||||
"listen_to_events": False,
|
||||
|
||||
"value_type": np.float64,
|
||||
"min_value": -10.0,
|
||||
"max_value": 10.0,
|
||||
@ -221,8 +217,7 @@ class LinearNumberSlider(ControlMobject):
|
||||
self.slider_axis.set_opacity(0.0)
|
||||
self.slider.move_to(self.slider_axis)
|
||||
|
||||
self.slider.listen_to_events = True
|
||||
self.slider.on_mouse_drag = self.slider_on_mouse_drag
|
||||
self.slider.add_mouse_drag_listner(self.slider_on_mouse_drag)
|
||||
|
||||
super().__init__(value, self.bar, self.slider, self.slider_axis, ** kwargs)
|
||||
|
||||
@ -233,8 +228,8 @@ class LinearNumberSlider(ControlMobject):
|
||||
prop = (value - self.min_value) / (self.max_value - self.min_value)
|
||||
self.slider.move_to(self.slider_axis.point_from_proportion(prop))
|
||||
|
||||
def slider_on_mouse_drag(self, point, d_point, buttons, modifiers):
|
||||
self.set_value(self.get_value_from_point(point))
|
||||
def slider_on_mouse_drag(self, mob, event_data):
|
||||
self.set_value(self.get_value_from_point(event_data["point"]))
|
||||
return False
|
||||
|
||||
# Helper Methods
|
||||
@ -372,12 +367,12 @@ class Textbox(ControlMobject):
|
||||
digest_config(self, kwargs)
|
||||
self.isActive = self.isInitiallyActive
|
||||
self.box = Rectangle(**self.box_kwargs)
|
||||
self.box.listen_to_events = True
|
||||
self.box.on_mouse_press = self.box_on_mouse_press
|
||||
self.box.add_mouse_press_listner(self.box_on_mouse_press)
|
||||
self.text = Text(value, **self.text_kwargs)
|
||||
super().__init__(value, self.box, self.text, **kwargs)
|
||||
self.update_text(value)
|
||||
self.active_anim(self.isActive)
|
||||
self.add_key_press_listner(self.on_key_press)
|
||||
|
||||
def set_value_anim(self, value):
|
||||
self.update_text(value)
|
||||
@ -400,15 +395,17 @@ class Textbox(ControlMobject):
|
||||
else:
|
||||
self.box.set_stroke(self.deactive_color)
|
||||
|
||||
def box_on_mouse_press(self, point, button, mods):
|
||||
def box_on_mouse_press(self, mob, event_data):
|
||||
self.isActive = not self.isActive
|
||||
self.active_anim(self.isActive)
|
||||
return False
|
||||
|
||||
def on_key_press(self, symbol, modifiers):
|
||||
def on_key_press(self, mob, event_data):
|
||||
symbol = event_data["symbol"]
|
||||
modifiers = event_data["modifiers"]
|
||||
char = chr(symbol)
|
||||
if self.isActive:
|
||||
old_value = self.get_value()
|
||||
if mob.isActive:
|
||||
old_value = mob.get_value()
|
||||
new_value = old_value
|
||||
if char.isalnum():
|
||||
if (modifiers & PygletWindowKeys.MOD_SHIFT) or (modifiers & PygletWindowKeys.MOD_CAPSLOCK):
|
||||
@ -421,7 +418,7 @@ class Textbox(ControlMobject):
|
||||
new_value = old_value + '\t'
|
||||
elif symbol == PygletWindowKeys.BACKSPACE:
|
||||
new_value = old_value[:-1] or ''
|
||||
self.set_value(new_value)
|
||||
mob.set_value(new_value)
|
||||
return False
|
||||
|
||||
|
||||
@ -452,8 +449,7 @@ class ControlPanel(Group):
|
||||
self.panel = Rectangle(**self.panel_kwargs)
|
||||
self.panel.to_corner(UP + LEFT, buff=0)
|
||||
self.panel.shift(self.panel.get_height() * UP)
|
||||
self.panel.listen_to_events = True
|
||||
self.panel.on_mouse_scroll = self.panel_on_mouse_scroll
|
||||
self.panel.add_mouse_scroll_listner(self.panel_on_mouse_scroll)
|
||||
|
||||
self.panel_opener_rect = Rectangle(**self.opener_kwargs)
|
||||
self.panel_info_text = Text(**self.opener_text_kwargs)
|
||||
@ -461,8 +457,7 @@ class ControlPanel(Group):
|
||||
|
||||
self.panel_opener = Group(self.panel_opener_rect, self.panel_info_text)
|
||||
self.panel_opener.next_to(self.panel, DOWN, aligned_edge=DOWN)
|
||||
self.panel_opener.listen_to_events = True
|
||||
self.panel_opener.on_mouse_drag = self.panel_opener_on_mouse_drag
|
||||
self.panel_opener.add_mouse_drag_listner(self.panel_opener_on_mouse_drag)
|
||||
|
||||
self.controls = Group(*controls)
|
||||
self.controls.arrange(DOWN, center=False, aligned_edge=ORIGIN)
|
||||
@ -515,12 +510,14 @@ class ControlPanel(Group):
|
||||
self.move_panel_and_controls_to_panel_opener()
|
||||
return self
|
||||
|
||||
def panel_opener_on_mouse_drag(self, point, d_point, buttons, modifiers):
|
||||
def panel_opener_on_mouse_drag(self, mob, event_data):
|
||||
point = event_data["point"]
|
||||
self.panel_opener.match_y(Dot(point))
|
||||
self.move_panel_and_controls_to_panel_opener()
|
||||
return False
|
||||
|
||||
def panel_on_mouse_scroll(self, point, offset):
|
||||
def panel_on_mouse_scroll(self, mob, event_data):
|
||||
offset = event_data["offset"]
|
||||
factor = 10 * offset[1]
|
||||
self.controls.set_y(self.controls.get_y() + factor)
|
||||
return False
|
||||
|
@ -27,6 +27,9 @@ from manimlib.utils.space_ops import get_norm
|
||||
from manimlib.utils.space_ops import rotation_matrix_transpose
|
||||
from manimlib.shader_wrapper import ShaderWrapper
|
||||
from manimlib.shader_wrapper import get_colormap_code
|
||||
from manimlib.event_handler import EVENT_DISPATCHER
|
||||
from manimlib.event_handler.event_listner import EventListner
|
||||
from manimlib.event_handler.event_type import EventType
|
||||
|
||||
|
||||
class Mobject(object):
|
||||
@ -68,6 +71,7 @@ class Mobject(object):
|
||||
self.init_data()
|
||||
self.init_uniforms()
|
||||
self.init_updaters()
|
||||
self.init_event_listners()
|
||||
self.init_points()
|
||||
self.init_colors()
|
||||
self.init_shader_data()
|
||||
@ -1440,35 +1444,81 @@ class Mobject(object):
|
||||
Event handling follows the Event Bubbling model of DOM in javascript.
|
||||
Return false to stop the event bubbling.
|
||||
To learn more visit https://www.quirksmode.org/js/events_order.html
|
||||
|
||||
Event Callback Argument is a callable function taking two arguments:
|
||||
1. Mobject
|
||||
2. EventData
|
||||
"""
|
||||
|
||||
def on_mouse_motion(self, point, d_point):
|
||||
# To be implemented in subclasses
|
||||
pass
|
||||
def init_event_listners(self):
|
||||
self.event_listners = []
|
||||
|
||||
def on_mouse_drag(self, point, d_point, buttons, modifiers):
|
||||
# To be implemented in subclasses
|
||||
pass
|
||||
def add_event_listner(self, event_type, event_callback):
|
||||
event_listner = EventListner(self, event_type, event_callback)
|
||||
self.event_listners.append(event_listner)
|
||||
EVENT_DISPATCHER.add_listner(event_listner)
|
||||
return self
|
||||
|
||||
def on_mouse_press(self, point, button, mods):
|
||||
# To be implemented in subclasses
|
||||
pass
|
||||
def remove_event_listner(self, event_type, event_callback):
|
||||
event_listner = EventListner(self, event_type, event_callback)
|
||||
while event_listner in self.event_listners:
|
||||
self.event_listners.remove(event_listner)
|
||||
EVENT_DISPATCHER.remove_listner(event_listner)
|
||||
return self
|
||||
|
||||
def on_mouse_release(self, point, button, mods):
|
||||
# To be implemented in subclasses
|
||||
pass
|
||||
def clear_event_listners(self, recurse=True):
|
||||
self.event_listners = []
|
||||
if recurse:
|
||||
for submob in self.submobjects:
|
||||
submob.clear_event_listners(recurse=recurse)
|
||||
return self
|
||||
|
||||
def on_mouse_scroll(self, point, offset):
|
||||
# To be implemented in subclasses
|
||||
pass
|
||||
def get_event_listners(self):
|
||||
return self.event_listners
|
||||
|
||||
def on_key_release(self, symbol, modifiers):
|
||||
# To be implemented in subclasses
|
||||
pass
|
||||
def get_family_event_listners(self):
|
||||
return list(it.chain(*[sm.get_event_listners() for sm in self.get_family()]))
|
||||
|
||||
def on_key_press(self, symbol, modifiers):
|
||||
# To be implemented in subclasses
|
||||
pass
|
||||
def get_has_event_listner(self):
|
||||
return any(
|
||||
mob.get_event_listners()
|
||||
for mob in self.get_family()
|
||||
)
|
||||
|
||||
def add_mouse_motion_listner(self, callback):
|
||||
self.add_event_listner(EventType.MouseMotionEvent, callback)
|
||||
def remove_mouse_motion_listner(self, callback):
|
||||
self.remove_event_listner(EventType.MouseMotionEvent, callback)
|
||||
|
||||
def add_mouse_press_listner(self, callback):
|
||||
self.add_event_listner(EventType.MousePressEvent, callback)
|
||||
def remove_mouse_press_listner(self, callback):
|
||||
self.remove_event_listner(EventType.MousePressEvent, callback)
|
||||
|
||||
def add_mouse_release_listner(self, callback):
|
||||
self.add_event_listner(EventType.MouseReleaseEvent, callback)
|
||||
def remove_mouse_release_listner(self, callback):
|
||||
self.remove_event_listner(EventType.MouseReleaseEvent, callback)
|
||||
|
||||
def add_mouse_drag_listner(self, callback):
|
||||
self.add_event_listner(EventType.MouseDragEvent, callback)
|
||||
def remove_mouse_drag_listner(self, callback):
|
||||
self.remove_event_listner(EventType.MouseDragEvent, callback)
|
||||
|
||||
def add_mouse_scroll_listner(self, callback):
|
||||
self.add_event_listner(EventType.MouseScrollEvent, callback)
|
||||
def remove_mouse_scroll_listner(self, callback):
|
||||
self.remove_event_listner(EventType.MouseScrollEvent, callback)
|
||||
|
||||
def add_key_press_listner(self, callback):
|
||||
self.add_event_listner(EventType.KeyPressEvent, callback)
|
||||
def remove_key_press_listner(self, callback):
|
||||
self.remove_event_listner(EventType.KeyPressEvent, callback)
|
||||
|
||||
def add_key_release_listner(self, callback):
|
||||
self.add_event_listner(EventType.KeyReleaseEvent, callback)
|
||||
def remove_key_release_listner(self, callback):
|
||||
self.remove_event_listner(EventType.KeyReleaseEvent, callback)
|
||||
|
||||
# Errors
|
||||
|
||||
|
@ -19,6 +19,8 @@ from manimlib.scene.scene_file_writer import SceneFileWriter
|
||||
from manimlib.utils.config_ops import digest_config
|
||||
from manimlib.utils.family_ops import extract_mobject_family_members
|
||||
from manimlib.utils.family_ops import restructure_list_to_exclude_certain_family_members
|
||||
from manimlib.event_handler.event_type import EventType
|
||||
from manimlib.event_handler import EVENT_DISPATCHER
|
||||
from manimlib.window import Window
|
||||
|
||||
|
||||
@ -58,9 +60,6 @@ class Scene(object):
|
||||
self.mouse_point = Point()
|
||||
self.mouse_drag_point = Point()
|
||||
|
||||
self.mob_listners = []
|
||||
self.mobjects_to_drag = []
|
||||
|
||||
# Much nicer to work with deterministic scenes
|
||||
if self.random_seed is not None:
|
||||
random.seed(self.random_seed)
|
||||
@ -208,9 +207,6 @@ class Scene(object):
|
||||
"""
|
||||
self.remove(*new_mobjects)
|
||||
self.mobjects += new_mobjects
|
||||
for new_mob in new_mobjects:
|
||||
for mob_listner in filter(lambda mob: mob.listen_to_events, reversed(new_mob.get_family())):
|
||||
self.mob_listners.insert(0, mob_listner)
|
||||
return self
|
||||
|
||||
def add_mobjects_among(self, values):
|
||||
@ -238,9 +234,6 @@ class Scene(object):
|
||||
def bring_to_back(self, *mobjects):
|
||||
self.remove(*mobjects)
|
||||
self.mobjects = list(mobjects) + self.mobjects
|
||||
for new_mob in reversed(mobjects):
|
||||
for mob_listner in filter(lambda mob: mob.listen_to_events, reversed(new_mob.get_family())):
|
||||
self.mob_listners.append(mob_listner)
|
||||
return self
|
||||
|
||||
def clear(self):
|
||||
@ -522,20 +515,12 @@ class Scene(object):
|
||||
self.mobjects = mobjects
|
||||
|
||||
# Event handling
|
||||
def get_event_listeners_mobjects(self):
|
||||
"""
|
||||
This method returns all the mobjects that listen to events
|
||||
in reversed order. So the top most mobject's event is called first.
|
||||
This helps in event bubbling.
|
||||
"""
|
||||
return self.mob_listners
|
||||
|
||||
def on_mouse_motion(self, point, d_point):
|
||||
self.mouse_point.move_to(point)
|
||||
|
||||
for mob_listener in self.get_event_listeners_mobjects():
|
||||
if mob_listener.is_point_touching(point):
|
||||
propagate_event = mob_listener.on_mouse_motion(point, d_point)
|
||||
event_data = {"point": point, "d_point": d_point}
|
||||
propagate_event = EVENT_DISPATCHER.dispatch(EventType.MouseMotionEvent, **event_data)
|
||||
if propagate_event is not None and propagate_event is False:
|
||||
return
|
||||
|
||||
@ -554,35 +539,26 @@ class Scene(object):
|
||||
def on_mouse_drag(self, point, d_point, buttons, modifiers):
|
||||
self.mouse_drag_point.move_to(point)
|
||||
|
||||
for mob_listener in self.mobjects_to_drag:
|
||||
propagate_event = mob_listener.on_mouse_drag(point, d_point, buttons, modifiers)
|
||||
event_data = {"point": point, "d_point": d_point, "buttons": buttons, "modifiers": modifiers}
|
||||
propagate_event = EVENT_DISPATCHER.dispatch(EventType.MouseDragEvent, **event_data)
|
||||
if propagate_event is not None and propagate_event is False:
|
||||
return
|
||||
|
||||
def on_mouse_press(self, point, button, mods):
|
||||
for mob_listener in self.get_event_listeners_mobjects():
|
||||
if mob_listener.is_point_touching(point):
|
||||
self.mobjects_to_drag.append(mob_listener)
|
||||
|
||||
for mob_listener in self.get_event_listeners_mobjects():
|
||||
if mob_listener.is_point_touching(point):
|
||||
propagate_event = mob_listener.on_mouse_press(point, button, mods)
|
||||
event_data = {"point": point, "button": button, "mods": mods}
|
||||
propagate_event = EVENT_DISPATCHER.dispatch(EventType.MousePressEvent, **event_data)
|
||||
if propagate_event is not None and propagate_event is False:
|
||||
return
|
||||
|
||||
def on_mouse_release(self, point, button, mods):
|
||||
self.mobjects_to_drag = []
|
||||
|
||||
for mob_listener in self.get_event_listeners_mobjects():
|
||||
if mob_listener.is_point_touching(point):
|
||||
propagate_event = mob_listener.on_mouse_release(point, button, mods)
|
||||
event_data = {"point": point, "button": button, "mods": mods}
|
||||
propagate_event = EVENT_DISPATCHER.dispatch(EventType.MouseReleaseEvent, **event_data)
|
||||
if propagate_event is not None and propagate_event is False:
|
||||
return
|
||||
|
||||
def on_mouse_scroll(self, point, offset):
|
||||
for mob_listener in self.get_event_listeners_mobjects():
|
||||
if mob_listener.is_point_touching(point):
|
||||
propagate_event = mob_listener.on_mouse_scroll(point, offset)
|
||||
event_data = {"point": point, "offset": offset}
|
||||
propagate_event = EVENT_DISPATCHER.dispatch(EventType.MouseScrollEvent, **event_data)
|
||||
if propagate_event is not None and propagate_event is False:
|
||||
return
|
||||
|
||||
@ -596,8 +572,8 @@ class Scene(object):
|
||||
frame.shift(-20.0 * shift)
|
||||
|
||||
def on_key_release(self, symbol, modifiers):
|
||||
for mob_listener in self.get_event_listeners_mobjects():
|
||||
propagate_event = mob_listener.on_key_release(symbol, modifiers)
|
||||
event_data = {"symbol": symbol, "modifiers": modifiers}
|
||||
propagate_event = EVENT_DISPATCHER.dispatch(EventType.KeyReleaseEvent, **event_data)
|
||||
if propagate_event is not None and propagate_event is False:
|
||||
return
|
||||
|
||||
@ -608,8 +584,8 @@ class Scene(object):
|
||||
print(" Warning: The value of the pressed key is too large.")
|
||||
return
|
||||
|
||||
for mob_listener in self.get_event_listeners_mobjects():
|
||||
propagate_event = mob_listener.on_key_press(symbol, modifiers)
|
||||
event_data = {"symbol": symbol, "modifiers": modifiers}
|
||||
propagate_event = EVENT_DISPATCHER.dispatch(EventType.KeyPressEvent, **event_data)
|
||||
if propagate_event is not None and propagate_event is False:
|
||||
return
|
||||
|
||||
|
Reference in New Issue
Block a user