We can export a CPlusPlus function in wasm for JS to control the time of invoking vtkRenderWindowInteractor::Start.

But after the exported function called, we can’t run the following JS code due to the event loop caused the blockage.

Read the code in VTK to find the way to give JS callback after starting event loop.

void vtkRenderWindowInteractor::Start()
{
  // Let the compositing handle the event loop if it wants to.
  if (this->HasObserver(vtkCommand::StartEvent) && !this->HandleEventLoop)
  {
    this->InvokeEvent(vtkCommand::StartEvent, nullptr);
    return;
  }

  // As a convenience, initialize if we aren't initialized yet.
  if (!this->Initialized)
  {
    this->Initialize();

    if (!this->Initialized)
    {
      return;
    }
  }

  // Pass execution to the subclass which will run the event loop,
  // this will not return until TerminateApp is called.
  this->Done = false;
  this->StartEventLoop();
}


//------------------------------------------------------------------------------
void vtkSDL2RenderWindowInteractor::StartEventLoop()
{
  // No need to do anything if this is a 'mapped' interactor
  if (!this->Enabled)
  {
    return;
  }

  this->StartedMessageLoop = 1;
#ifdef __EMSCRIPTEN__
  emscripten_set_main_loop_arg(&mainLoopCallback, (void*)this, 0, 1);
#else
  while (!this->Done)
  {
    this->ProcessEvents();
  }
#endif
}


namespace
{

void mainLoopCallback(void* arg)
{
  vtkSDL2RenderWindowInteractor* iren = static_cast<vtkSDL2RenderWindowInteractor*>(arg);
  iren->ProcessEvents();
}
}

void vtkSDL2RenderWindowInteractor::ProcessEvents()
{
  // No need to do anything if this is a 'mapped' interactor
  if (!this->Enabled)
  {
    return;
  }

  SDL_Event event;
  std::vector<SDL_Event> events;

  // SDL generates continuous sequences of mouse motion events per frame,
  // let use only last event of each sequence

  while (SDL_PollEvent(&event))
  {
    if (event.type == SDL_MOUSEMOTION && !events.empty() && events.back().type == event.type)
    {
      events.back() = event;
    }
    else
    {
      events.push_back(event);
    }
  }

  for (SDL_Event ev : events)
  {
    if (this->ProcessEvent(&ev))
    {
      break;
    }
  }
}


bool vtkSDL2RenderWindowInteractor::ProcessEvent(void* arg)
{
//...
    case SDL_KEYDOWN:
    {
      // simplified, not fully implemented
      std::string keyname = SDL_GetKeyName(event->key.keysym.sym);
      if (keyname.size())
      {
        this->SetKeyEventInformation(ctrl, shift, keyname[0], event->key.repeat, keyname.c_str());
        this->SetAltKey(alt);
        this->InvokeEvent(vtkCommand::KeyPressEvent, nullptr);
      }
    }
//...
    case SDL_WINDOWEVENT:
    {
      switch (event->window.event)
      {
        case SDL_WINDOWEVENT_SIZE_CHANGED:
        {
          this->UpdateSize(event->window.data1, event->window.data2);
          this->Render();
        }
        break;
        case SDL_WINDOWEVENT_CLOSE:
        {
          this->TerminateApp();
        }
        break;
      }
    }


void vtkInteractorStyle::ProcessEvents(
  vtkObject* vtkNotUsed(object), unsigned long event, void* clientdata, void* calldata)
{
  vtkInteractorStyle* self = reinterpret_cast<vtkInteractorStyle*>(clientdata);

  bool aborted = false;

  switch (event)
  {
//...
    case vtkCommand::KeyPressEvent:
      if (self->HandleObservers && self->HasObserver(vtkCommand::KeyPressEvent))
      {
        self->InvokeEvent(vtkCommand::KeyPressEvent, nullptr);
      }
      else
      {
        self->OnKeyDown();
        self->OnKeyPress();
      }
      break;


/**
 *  \brief Display state change event data (event.display.*)
 */
typedef struct SDL_DisplayEvent
{
    Uint32 type;        /**< ::SDL_DISPLAYEVENT */
    Uint32 timestamp;   /**< In milliseconds, populated using SDL_GetTicks() */
    Uint32 display;     /**< The associated display index */
    Uint8 event;        /**< ::SDL_DisplayEventID */
    Uint8 padding1;
    Uint8 padding2;
    Uint8 padding3;
    Sint32 data1;       /**< event dependent data */
} SDL_DisplayEvent;

/**
 *  \brief Window state change event data (event.window.*)
 */
typedef struct SDL_WindowEvent
{
    Uint32 type;        /**< ::SDL_WINDOWEVENT */
    Uint32 timestamp;   /**< In milliseconds, populated using SDL_GetTicks() */
    Uint32 windowID;    /**< The associated window */
    Uint8 event;        /**< ::SDL_WindowEventID */
    Uint8 padding1;
    Uint8 padding2;
    Uint8 padding3;
    Sint32 data1;       /**< event dependent data */
    Sint32 data2;       /**< event dependent data */
} SDL_WindowEvent;

The observer can receive SDL event after starting event loop, we can see the 3D scene window displayed after calling the exported function which contains vtkRenderWindowInteractor::Start. So I guess there will be SDL window event received in vtkSDL2RenderWindowInteractor::ProcessEvent.

In the test program, I got the window event I expected.

bool UInteractor::ProcessEvent(void *arg)
{
  SDL_Event *event = reinterpret_cast<SDL_Event *>(arg);
  std::cout << "event type: " << event->type << std::endl;

  // SDL_DISPLAYEVENT   = 0x150,  /**< Display state change */  336
  // SDL_WINDOWEVENT    = 0x200, /**< Window state change */  512
  // SDL_MOUSEMOTION    = 0x400, /**< Mouse moved */  1024
  // SDL_MOUSEWHEEL,             /**< Mouse wheel motion */ 1027
  if (SDL_WINDOWEVENT == event->type)
  {
    std::cout << "window.event: " << (int)(event->window.event) << std::endl; // SDL_WINDOWEVENT_SHOWN is 1
    // 6, 5, 10, 12, 1
    // SDL_WINDOWEVENT_SIZE_CHANGED, SDL_WINDOWEVENT_RESIZED, SDL_WINDOWEVENT_ENTER, SDL_WINDOWEVENT_FOCUS_GAINED, SDL_WINDOWEVENT_SHOWN
  }

  // SDL_WINDOWEVENT_NONE,           /**< Never used */
  // SDL_WINDOWEVENT_SHOWN,          /**< Window has been shown */
  // SDL_WINDOWEVENT_HIDDEN,         /**< Window has been hidden */
  // SDL_WINDOWEVENT_EXPOSED,        /**< Window has been exposed and should be
  //                                     redrawn */
  // SDL_WINDOWEVENT_MOVED,          /**< Window has been moved to data1, data2
  //                                 */
  // SDL_WINDOWEVENT_RESIZED,        /**< Window has been resized to data1xdata2 */  //5
  // SDL_WINDOWEVENT_SIZE_CHANGED,   /**< The window size has changed, either as
  //                                     a result of an API call or through the
  //                                     system or user changing the window size. */
  // SDL_WINDOWEVENT_MINIMIZED,      /**< Window has been minimized */
  // SDL_WINDOWEVENT_MAXIMIZED,      /**< Window has been maximized */
  // SDL_WINDOWEVENT_RESTORED,       /**< Window has been restored to normal size
  //                                      and position */
  // SDL_WINDOWEVENT_ENTER,          /**< Window has gained mouse focus */  //10
  // SDL_WINDOWEVENT_LEAVE,          /**< Window has lost mouse focus */
  // SDL_WINDOWEVENT_FOCUS_GAINED,   /**< Window has gained keyboard focus */ //12
  // SDL_WINDOWEVENT_FOCUS_LOST,     /**< Window has lost keyboard focus */


  return vtkSDL2RenderWindowInteractor::ProcessEvent(arg);
}

The result on the firefox browser.

Test project had been uploaded to GitHub:

https://github.com/theArcticOcean/tutorials/tree/main/learnWebAssembly/vtkInteractorStartCallBack

Categories: VTKWeb

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Inline Feedbacks
View all comments

join us
: You can get unlimited access to free membership content

X
0
Would love your thoughts, please comment.x
()
x