Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Save and call previous callback installed by user #154

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

akramparvez
Copy link

User installed call backs are lost if installed before initializing GlfwRenderer, the change save previous callback and chains them. Based on change in imgui example.

@coveralls
Copy link

Coverage Status

Coverage decreased (-0.3%) to 53.875% when pulling 57288e4 on akramparvez:improvements/glfw-integrations into c84315e on swistakm:master.

@swistakm
Copy link
Member

Yeah, replacing of callbacks is the exact reason why this mechanism can be disabled with: attach_callbacks=False argument. It such situation (having pre-existing callbacks) users were supposed to link these manually after instantiating GlfwRendered. I understand this is inconvenient and we can do better.

Your solution is quite good but has following issues:

  • there is small risk that some users actually had some of their callbacks replaced knowingly, this would bring them up and cause unexpected behaviour
  • would be great to be able to control the point where new callbacks are attached (first or last)

I'm OK with changing the default behaviour as long as there would be a way to have old behaviour back on-demand.

Following is something that I quickly drafted that would add new argument to the renderer to control the way callbacks are attached:

from enum import Enum


class CallbackMode(Enum):
    REPLACE = auto()
    FIRST = auto()
    LAST = auto()


def _chain_glfw_callback(window, mode, setter, callback):
    if mode not in CallbackMode:
        raise ValueError("Unknown callback mode: {}".format(mode))

    chain = [callback]

    def chained_call(*args, **kwargs):
        for call in chain:
            call(*args, **kwargs)

    previous = setter(window, chained_call)

    if previous and mode != CallbackMode.REPLACE:
        chain.append(previous)

    if mode == CallbackMode.LAST:
        chain.reverse()


class GlfwRenderer(ProgrammablePipelineRenderer):
    def __init__(self, window, attach_callbacks=True, callback_mode=CallbackMode.REPLACE):
        super(GlfwRenderer, self).__init__()
        self.window = window

        if attach_callbacks:
            _chain_glfw_callback(window, callback_mode, glfw.set_key_callback, self.keyboard_callback)
            _chain_glfw_callback(window, callback_mode, glfw.set_cursor_pos_callback, self.mouse_callback)
            _chain_glfw_callback(window, callback_mode, glfw.set_window_size_callback, self.resize_callback)
            _chain_glfw_callback(window, callback_mode, glfw.set_char_callback, self.char_callback)
            _chain_glfw_callback(window, callback_mode, glfw.set_scroll_callback, self.scroll_callback)
        ...

Then you could get the desired behaviour using:

impl = GlfwRenderer(window, callback_mode=CallbackMode.LAST)

This retains full backwards compatibility (although we can make more sensible default here) and allows for a bit more control in future. Unfortunately it depends on enum that is not available in Python<3.4. As we will probably get rid of old Python versions support at some point of time we can use a conditional backport in setup.py:

setup(
    #  ...,
    install_requires=[
        "enum34>=1.1.10; python_version < '3.4'",
    ],
    # ...
)

Would you be willing to integrate this idea into your PR?

@swistakm
Copy link
Member

Just a small reminder: I have just merged #158 so the pyglet integration classes have changed slightly.

@swistakm swistakm added this to the 1.3.0 milestone Jul 20, 2020
@swistakm swistakm added this to To do in New release Jul 20, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
New release
  
To do
Development

Successfully merging this pull request may close these issues.

None yet

3 participants