Await event in coroutine

Hi everyone,

I’m new to panda3d and trying to figure out something that I thought would be simple, but it’s giving me a hard time.

I have a simple application where I want to register the user’s name with a DirectEntry at the beginning of a coroutine. I choice to use a coroutine because several tasks and steps need to be completed in order without blocking the main tread. Because the user ID is important to wait for in this coroutine I want to await a event or task or something, so the application can properly capture the user name before continuing doing the various tasks. However I can’t seem to make it work and neither could find this problem on the forums. I tried to make it with with await messenger.future('even_name') but this is not working. I can’t figure out how to make it work with a Task either. Somebody has some tips on this?

Thanks.

current code:

class MyApp(ShowBase):
    def __init__(self):
        ShowBase.__init__(self)
        self.messenger.toggleVerbose()
        self.user_name = ""

        self.disableMouse()

        self.taskMgr.add(self.main_coroutine())

    async def main_coroutine(self):
        text = OnscreenText(text="name:")
        entry = DirectEntry(focus=1, command=self.set_user_id)
        await self.messenger.future('user_name_set')
        # ... continue coroutine code ... #

    def set_user_id(self, text_entered):
        self.user_name = text_entered
        self.messenger.send('user_name_set')

Hi, welcome to the community!

Regrettably, it does not seem that messenger.future is working for custom-generated events with messenger.send. I suggest filing a bug report for this on the issue tracker.

However, I think in this case I would prefer using explicit futures for this anyway. One possible approach is:

    async def main_coroutine(self):
        text = OnscreenText(text="name:")

        fut = AsyncFuture()
        entry = DirectEntry(focus=1, command=lambda text, fut=fut:fut.set_result(text))
        user_name = await fut
        print(user_name)

Hi rdb,

This indeed solves it, thank you. I will also report a bug report for this on the issue tracker.

One more follow up question, could I have found more information on this fut parameter myself in the documentation? I can’t find it at all in the documentation, and if I look at the python implementation of DirectEntry it’s also not there, how is this code working?

edit: or is this more fundamental to Python’s Async/coroutine/task programming scheme’s?

There’s no fut parameter of DirectEntry, it’s a parameter of the lambda function. This:

myfunction = lambda text, fut=fut:fut.set_result(text)

is more-or-less a short-hand for:

def myfunction(text, fut=fut):
    return fut.set_result(text)

Another way of writing it without a temporary function or lambda is:

    async def main_coroutine(self):
        text = OnscreenText(text="name:")

        fut = AsyncFuture()
        entry = DirectEntry(focus=1, command=self.set_user_id, extraArgs=[fut])
        user_name = await fut
        print(user_name)

    def set_user_id(self, text_entered, fut):
        fut.set_result(text_entered)
1 Like

Thank you, crystal clear now.