This PR adds a new WIndow class and the App global variable to coordinate starting and stopping the GUI environment. Each Window has an associated Canvas object, whose dimensions can be set independently of the size of the window. Resizing the window will scale the canvas to fit it using similar options as the css object-fit property.
Window attributes can be assigned via properties (after the object has been instantiated) or passed as part of an options object passed to the constructor. Its configurable attributes include:
context selection: page
bounds: left / top / width / height
css: cursor / fit
flags: fullscreen / visible
color: background
label: title
Multiple Window objects can be instantiated and will be displayed as soon as the current event loop completes (or once the blocking App.launch() method is called manually). This transfers control of the global event loop away from Node and lets the underlying OS take over moment-to-moment operations. As a result, you will not be able to use any of Node's asynchronous behaviors: in particular, setTimeout and setInterval callbacks will not fire while the App is running.
Instead, you must use event handlers attached to the Window objects. These allow you to respond to user interface events (e.g., mouse and keyboard input, the window being dragged or resized, changes in which window is currently active, etc.). Each window is an EventEmitter object and supports the standard .on(), .off(), and .once() methods for setting event handlers. The full set of supported event types is:
mousedown / mouseup / mousemove / wheel
keydown / keyup / input
move / resize
blur / focus
setup / frame / draw
The frame event is similar to the requestAnimationFrame timer in browsers in that it will trigger your callback at the proper time to update the screen at the current frame rate (by default 60 fps, though this can be set via the App.fps property). The draw event operates the same way but also has the side effect of clearing the canvas before triggering your event handler. This makes it ideal for ‘canned’ animations that don't require user interaction and can be driven solely by the current 'frame number' integer (which is passed as the sole argument to your event handler with each call). The setup event fires once, just before the initial frame is rendered, allowing you to perform last-minute preparation that requires access to the ‘live’ environment.
The run will end once you close all of the open windows or call the App.quit() method, returning control to the Node event loop (but leaving the App in a state where it cannot be re-launched).
On Linux and Windows the display layer uses Vulkan (with the rendering pipeline coordinated by the Rafx framework). On macOS, the system's Metal backend is used instead. To build the rust components locally, you will need to specify the platform-appropriate features to use:
macOS: npm run build -- --release --features metal,window
Linux/Windows: npm run build -- --release --features vulkan,window
This PR adds a new WIndow class and the
App
global variable to coordinate starting and stopping the GUI environment. Each Window has an associated Canvas object, whose dimensions can be set independently of the size of the window. Resizing the window will scale the canvas to fit it using similar options as the css object-fit property.Window attributes can be assigned via properties (after the object has been instantiated) or passed as part of an options object passed to the constructor. Its configurable attributes include:
page
left
/top
/width
/height
cursor
/fit
fullscreen
/visible
background
title
Multiple Window objects can be instantiated and will be displayed as soon as the current event loop completes (or once the blocking
App.launch()
method is called manually). This transfers control of the global event loop away from Node and lets the underlying OS take over moment-to-moment operations. As a result, you will not be able to use any of Node's asynchronous behaviors: in particular,setTimeout
andsetInterval
callbacks will not fire while the App is running.Instead, you must use event handlers attached to the Window objects. These allow you to respond to user interface events (e.g., mouse and keyboard input, the window being dragged or resized, changes in which window is currently active, etc.). Each window is an EventEmitter object and supports the standard
.on()
,.off()
, and.once()
methods for setting event handlers. The full set of supported event types is:mousedown
/mouseup
/mousemove
/wheel
keydown
/keyup
/input
move
/resize
blur
/focus
setup
/frame
/draw
The
frame
event is similar to therequestAnimationFrame
timer in browsers in that it will trigger your callback at the proper time to update the screen at the current frame rate (by default 60 fps, though this can be set via theApp.fps
property). Thedraw
event operates the same way but also has the side effect of clearing the canvas before triggering your event handler. This makes it ideal for ‘canned’ animations that don't require user interaction and can be driven solely by the current 'frame number' integer (which is passed as the sole argument to your event handler with each call). Thesetup
event fires once, just before the initial frame is rendered, allowing you to perform last-minute preparation that requires access to the ‘live’ environment.The run will end once you close all of the open windows or call the
App.quit()
method, returning control to the Node event loop (but leaving the App in a state where it cannot be re-launched).On Linux and Windows the display layer uses Vulkan (with the rendering pipeline coordinated by the Rafx framework). On macOS, the system's Metal backend is used instead. To build the rust components locally, you will need to specify the platform-appropriate features to use:
npm run build -- --release --features metal,window
npm run build -- --release --features vulkan,window