func1() > func2() Click the func1 window 3 times, then click th" /> func1() > func2() Click the func1 window 3 times, then click th" /> func1() > func2() Click the func1 window 3 times, then click th"/>

Is the return value of cur3d() correct in this example?

36 Views Asked by At

Is this the correct behavior of cur3d? The code is shown below.

% R
> source("ex.R")
> func1()
> func2()

Click the func1 window 3 times, then click the func2 window 3 times. The result is:

func1: 2
func1: 2 
func1: 2 
func2: 2 
func2: 2 
func2: 2

The code is as follows:

library(rgl)

func1 <- function() {

  func1.dev.id <- open3d()
  func1.scene.id <- newSubscene3d()
  
  begin <- function(x, y) {
    cat("func1:", cur3d(), "\n")
  }

  update <- function(x, y) {
    cat("func1:", cur3d(), "\n")
  }

  useSubscene3d(func1.scene.id)
  rgl.setMouseCallbacks(1, begin, update)
}


func2 <- function() {

  func2.dev.id <- open3d()
  func2.scene.id <- newSubscene3d()
  
  begin <- function(x, y) {
    cat("func2:", cur3d(), "\n")
  }

  update <- function(x, y) {
    cat("func2:", cur3d(), "\n")
  }

  useSubscene3d(func2.scene.id)
  rgl.setMouseCallbacks(1, begin, update)
}

I want to know if this is the correct behavior.

1

There are 1 best solutions below

3
user2554330 On

@Stibu gave the explanation in a comment: "cur3d() returns the device number of the current window, which is the last one that was started. This is the window that rgl will draw to if you run the appropriate functions. cur3d() does not return the device number of the window you clicked because clicking does not change what the current window is. So this is indeed the expected behaviour."

To get the behaviour you were expecting, you should explicitly change the current device in the begin events (which correspond to mouse down events here):

library(rgl)

func1 <- function() {
  
  func1.dev.id <- open3d()
  func1.scene.id <- newSubscene3d()
  
  begin <- function(x, y) {
    set3d(func1.dev.id, silent = TRUE)
    cat("func1:", cur3d(), "\n")
  }
  
  update <- function(x, y) {
    cat("func1:", cur3d(), "\n")
  }
  
  useSubscene3d(func1.scene.id)
  rgl.setMouseCallbacks(1, begin, update)
}


func2 <- function() {
  
  func2.dev.id <- open3d()
  func2.scene.id <- newSubscene3d()
  
  begin <- function(x, y) {
    set3d(func2.dev.id, silent = TRUE)
    cat("func2:", cur3d(), "\n")
  }
  
  update <- function(x, y) {
    cat("func2:", cur3d(), "\n")
  }
  
  useSubscene3d(func2.scene.id)
  rgl.setMouseCallbacks(1, begin, update)
}

Depending on what you intend to do in your real code, you may want to also add useSubscene3d(...) to the begin function. It isn't necessary in this example: each device has an associated current subscene.

On my system (a Mac), the first click on a window selects the window, and only the second click is sent to the contents. So to get your functions to be called on a different rgl window I need to click on it twice.

EDITED to add: Inspired by another @Stibu comment (thanks!), I went looking to see if this is configurable on the Mac. It is. If you choose the XQuartz application and choose Preferences | Windows, an option is "Click-through inactive windows". Selecting that means that a single click on a window both selects it and is passed into the application. For the code above, that means every click produces output.