1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
|
\name{callbacks}
\alias{rgl.setMouseCallbacks}
\alias{rgl.getMouseCallbacks}
\alias{rgl.setWheelCallback}
\alias{rgl.getWheelCallback}
\title{ User callbacks on mouse events }
\description{
Set and get user callbacks on mouse events.
}
\usage{
rgl.setMouseCallbacks(button, begin = NULL, update = NULL, end = NULL,
dev = cur3d(), subscene = currentSubscene3d(dev))
rgl.getMouseCallbacks(button,
dev = cur3d(), subscene = currentSubscene3d(dev))
rgl.setWheelCallback(rotate,
dev = cur3d(), subscene = currentSubscene3d(dev))
rgl.getWheelCallback(dev = cur3d(), subscene = currentSubscene3d(dev))
}
\arguments{
\item{button}{ Which button? Use 1 for left, 2 for
right, 3 for middle, 4 for wheel. Use 0 to set
an action when no button is pressed. }
\item{begin}{ Called when mouse down event occurs }
\item{update}{ Called when mouse moves }
\item{end}{ Called when mouse is released }
\item{rotate}{ Called when mouse wheel is rotated }
\item{dev, subscene}{The RGL device and subscene to work with }
}
\details{
The set functions set event handlers on mouse events that occur within the current RGL window.
The \code{begin} and \code{update} events should be functions taking two arguments; these
will be the mouse coordinates when the event occurs. The \code{end} event handler
takes no arguments. The \code{rotate} event takes a single argument, which will be
equal to \code{1} if the user pushes the wheel away by one click, and \code{2} if
the user pulls the wheel by one click.
Alternatively, the handlers may be set to \code{NULL}, the default value, in which case
no action will occur.
If a subscene has multiple listeners, the user action will still only be called for the
subscene that received the mouse event. It should consult \code{\link{par3d}("listeners")}
if it makes sense to take action on the whole group of subscenes.
The get function retrieves the callbacks that are currently set.
The \dQuote{no button} mouse handler may be set by
specifying \code{button = 0}. The \code{begin}
function will be called the first time the mouse
moves within the subscene, and the \code{update}
function will be called repeatedly as it moves. The
\code{end} function will never be called.
}
\value{
The set functions are called for the side effect of setting the mouse event handlers.
The \code{rgl.getMouseCallbacks} function returns a list containing the callback functions or \code{NULL} if no user callback is set.
The \code{rgl.getWheelCallback} returns the callback function or \code{NULL}.
}
\author{ Duncan Murdoch }
\seealso{ \code{\link{par3d}} to set built-in handlers,
\code{\link{setUserCallbacks}} to work with \code{\link{rglwidget}}.}
\examples{
pan3d <- function(button, dev = cur3d(), subscene = currentSubscene3d(dev)) {
start <- list()
begin <- function(x, y) {
activeSubscene <- par3d("activeSubscene", dev = dev)
start$listeners <<- par3d("listeners", dev = dev, subscene = activeSubscene)
for (sub in start$listeners) {
init <- par3d(c("userProjection","viewport"), dev = dev, subscene = sub)
init$pos <- c(x/init$viewport[3], 1 - y/init$viewport[4], 0.5)
start[[as.character(sub)]] <<- init
}
}
update <- function(x, y) {
for (sub in start$listeners) {
init <- start[[as.character(sub)]]
xlat <- 2*(c(x/init$viewport[3], 1 - y/init$viewport[4], 0.5) - init$pos)
mouseMatrix <- translationMatrix(xlat[1], xlat[2], xlat[3])
par3d(userProjection = mouseMatrix \%*\% init$userProjection, dev = dev, subscene = sub )
}
}
rgl.setMouseCallbacks(button, begin, update, dev = dev, subscene = subscene)
cat("Callbacks set on button", button, "of RGL device", dev, "in subscene", subscene, "\n")
}
open3d()
shade3d(icosahedron3d(), col = "yellow")
# This only works in the internal display...
pan3d(1)
}
\keyword{ dynamic }
|