The Croc Programming Language

module glfw

GLFW is a cross-platform library for creating windows and OpenGL contexts, managing them, and receiving input. This module presents a Croc-like interface to GLFW 3, and also loads the OpenGL API into the gl module.

Prerequisites

This module loads the GLFW 3 shared library dynamically when it's first imported. On windows, this is glfw3.dll; on Linux, libglfw3.so or libglfw.so.3; and on OSX libglfw.3.dylib.

The loaded library must be GLFW version 3.0.4 or higher. This library will check that the version of GLFW that was loaded is at least this version. If the shared library is not suitable, a RuntimeError will be thrown.

Including this library in the host

To use this library, the host must have it compiled into it. Compile Croc with the CROC_GLFW_ADDON option enabled in the CMake configuration. Then from your host, when setting up the VM use the croc_vm_loadAddons or croc_vm_loadAllAvailableAddons API functions to load this library into the VM. Then from your Croc code, you can just import glfw to access it.

OpenGL

This library will load the OpenGL API for you into a module called gl. It only supports a core context, which means OpenGL 3.0 and up. It supports all the way up to OpenGL 4.5, as well as a number of extensions.

Windows: A note on extensions and contexts

The way Windows exposes OpenGL extension API functions is a bit weird, and supposedly different contexts can give different function addresses for the same extension APIs. This library does not (yet) account for this oddity, but it seems that this is a fairly unlikely scenario. According to this page, "if two contexts come from the same vendor and refer to the same GPU, then the function pointers pulled from one will work in another." Chances are this library will eventually support this strangeness, but for the time being, it doesn't. The OpenGL core and extension APIs are loaded from the first context that you call loadOpenGL on.

Events

The native GLFW API uses callbacks to respond to OS events. This API does not work nicely with Croc's exception handling methods, so instead this library uses a more traditional event API. pollEvents and waitEvents will return event values which you can then dispatch on. If you really want a callback API, it's trivial to implement one on top of this API.

Errors

Similarly, the native GLFW API uses an error callback to handle errors. This library instead throws exceptions to signal errors, and as a result some functions which would return some error value instead throw an exception.

global function init()

Initialize the entire library. You must call this before any other functions!

Bound VM: due to the way GLFW does error handling, this library can only be initialized in one Croc VM at any time. Once you call this function, the VM that called it is "bound" to the library. Attempting to call this function again - from the same VM or from another - will throw a StateError. It is currently not possible to switch which VM is bound, short of calling terminate in the bound VM and then this function in another.

Returns:

a boolean indicating whether or not initialization succeeded. If false, initialization failed and you should terminate your program.

Throws:
StateError

in the situation described above.

global function terminate()

Deinitializes the entire library. If you successfully initialized it before, you must call this at the end of your program.

Bound VM: this unbinds the current VM from the library as explained in init.

global function getVersion()

Returns:

three integers: the major, minor, and release version numbers of the GLFW shared library. For example, if the library is version 3.0.4, this will return 3, 0, 4 in that order.

global function getVersionString()

Returns:

a string representing the version of the GLFW shared library.

global function loadOpenGL()

With a current context (see makeContextCurrent), creates a module named gl and loads the OpenGL core API and any supported extensions into it.

If called a second time, does nothing.

Throws:
OSException

if OpenGL could not be loaded, or if the computer does not support at least OpenGL 3.0.

global function getMonitors()

Returns:

an array of Monitor instances, one for each monitor attached to the system.

global function getPrimaryMonitor()

Returns:

an instance of Monitor which represents the system's primary monitor (usually the one with the taskbar/menubar/panel).

global function windowHint(hint: int, value: int)

Sets a window hint for the next call to createWindow. These hints retain their values until the next call to windowHint or defaultWindowHints.

The best reference for these hints is the official GLFW documentation. Note that where these docs say GL_TRUE, this library uses 1, and for GL_FALSE, 0.

global function defaultWindowHints()

Resets all window hints (those set with windowHint) to their default values.

global function createWindow(width: int, height: int, title: string, monitor: Monitor = null, share: Window = null)

Create a new window, and a new OpenGL context associated with that window.

Params:
width

is the width in pixels of the window.

height

is the height in pixels of the window.

title

will be the window's title, shown in the title bar (if any) or in the task switcher.

monitor

is the optional monitor on which this window will be made fullscreen. If null, the window will instead be windowed.

Note that "traditional" fullscreening is not always the best option thanks to modern window managers. If you want your app to go full screen, at least provide an option to use a borderless window the size of the monitor. Your users will thank you.

share

is an existing window with whom this new window will share OpenGL resources. If null, the new context will not share resources.

Returns:

a new Window instance.

global function pollEvents()

Sees if there are any events on the application's event queue.

For all the window events, you must enable them per-window with Window.enableEvents. If you don't, you'll never get any events for them.

Returns:

the first event on the queue, or nothing if there are no pending events.

The event will be returned as an event name, followed by the window or monitor it's for, and then up to four data values.

Because of the way this function returns its values, you can actually use it (without parentheses) as the container in a foreach loop. Your application's main loop might look something like:

while(not window.shouldClose())
{
	foreach(ev, wm, a, b, c, d; glfw.pollEvents)
	{
		// switch on ev; wm contains the window or monitor, and a-d are the event values
	}

	// update window and present
}
The following table explains what each type of event means, and what values will follow it.

Type

Description

Values

Value Description

"winpos"

A window was moved to a new position on the desktop.

window: Window, x: int, y: int

window is the window; (x, y) is its new position on the desktop.

"winsize"

A window was resized. This gives the new size in screen pixels, which can differ from the actual size of the framebufer for high-DPI displays. See the "fbsize" event.

window: Window, w: int, h: int

window is the window; (w, h) is its new size.

"close"

The user has requested a window to close. This doesn't mean the window has been closed, it's up to you to decide how to respond to the user's request to close the window.

window: Window

window is the window that the user wants to close.

"refresh"

The window manager has drawn over part of a window, and the window's contents must be redrawn.

window: Window

window is the window that needs to be redrawn.

"focus"

A window has either gained or lost foreground focus.

window: Window, focused: bool

window is the window; focused is true for focus gained, and false for lost.

"iconify"

A window has been minimized or un-minimized.

window: Window, iconified: bool

window is the window; iconified is true for minimized, and false for un-minimized.

"fbsize"

A window was resized. This gives the new size in framebuffer pixels, which can differ from the window's screen size for high-DPI displays.

window: Window, w: int, h: int

window is the window; (w, h) is its new framebuffer size.

"mousebutton"

A mouse button was either pressed or released.

window: Window, button: int, action: string, mods: int

window is the window; button is the mouse button (0-7); action is either "press" or "release"; and mods is a bitfield of the modifier keys that were pressed at the time.

"curpos"

The mouse cursor moved to a new position.

window: Window, x: float, y: float

window is the window; (x, y) are the floating point coordinates of the cursor, relative to the top-left of window's client area. If the cursor is above or to the left of the window, the coordinates can be negative, and if it's to the right or below the window, they can be larger than the window size.

"curenter"

The mouse cursor has either entered or left a window.

window: Window, entered: bool

window is the window; entered is true if the cursor entered the window, and false if it left the window.

"scroll"

The mouse scroll wheel or scroll ball moved.

window: Window, x: float, y: float

window is the window; x is the change in the x scroll axis (usually only applicable to scroll balls); y is the change in the y scroll axis (most scroll wheels).

"key"

A keyboard key was pressed, repeated, or released. Key repeat uses the user's OS settings. All non-modifier keys will repeat, but if you don't care about repeats, you can just ignore them.

window: Window, key: int, scancode: int, action: string, mods: int

window is the window; key is one of the glfw.KEY_* enumeration values; scancode is the raw keyboard scancode of the key; action is one of "press", "release", and "repeat"; and mods is a bitfield of the modifier keys that were pressed at the time.

"char"

The window received a Unicode character. This isn't the same thing as a keypress since it may have come from an IME of some sort. Use this event to collect proper text input.

window: Window, ch: string

window is the window; ch is the character that was input.

"monconnect"

A monitor was connected to or disconnected from the system.

monitor: Monitor, connected: bool

monitor is the monitor; connected is true for connected, false for diseconnected.

global function waitEvents()

Similar to pollEvents, except this will wait for an event to occur if there is none on the application's event queue.

Whereas pollEvents is better suited for realtime applications (like games), this function is better for event-driven applications, like editors and such. Typically these applications don't need to render a new screen every frame, so they can just idle waiting for a "refresh" event or user input.

In this case the application's main loop will look more like this:

while(not window.shouldClose())
{
	local ev, wm, a, b, c, d = glfw.waitEvents()
	// switch on ev here; present only when needed
}

Returns:

an event as specified in the docs for pollEvents.

global function joystickPresent(joy: int)

Sees if a joystick is connected.

Params:
joy

is the index of the joystick to check, in the range 0 to 15 inclusive.

Returns:

a boolean indicating whether or not a joystick is present at that index.

global function getJoystickAxes(joy: int, axes: array)

Gets the values of all the axes of a joystick.

Params:
joy

is the index of the joystick to check, in the range 0 to 15 inclusive.

axes

is the array where the values will be stored. axes will be resized to the number of axes and will be filled with floats.

Returns:

axes for convenience.

global function getJoystickButtons(joy: int, buttons: array)

Gets the state of all the buttons of a joystick.

Params:
joy

is the index of the joystick to check, in the range 0 to 15 inclusive.

buttons

is the array where the values will be stored. buttons will be resized to the number of buttons and will be filled with bools.

Returns:

buttons for convenience.

global function getJoystickName(joy: int)

Gets a nice name of a joystick.

Params:
joy

is the index of the joystick to check, in the range 0 to 15 inclusive.

Returns:

its name.

global function makeContextCurrent(window: Window)

Makes a given window's OpenGL context the current one.

OpenGL supports multiple contexts, but only one can be active ("current") at any time. You set which one is current with this function. You must make a context current before you can load the OpenGL API (with loadOpenGL) or use any of the OpenGL API functions.

Params:
window

is the window to make current.

global function getCurrentContext()

Returns:

the Window object whose context is the currently-selected one.

global function swapInterval(interval: int)

Sets the swap interval for the current context, which is the number of screen updates to wait before swapping a window's buffer, also known as "vertical sync" or "vsync."

Params:
interval

is the number of frames to wait before swapping. 0 means no vsync, 1 means normal vsync, and so on. Can be negative on platforms that support the WGL_EXT_swap_control_tear or GLX_EXT_swap_control_tear context extensions, which can be tested for with extensionSupported.

global function extensionSupported(name: string)

Tests if an OpenGL or platform-specific context extension is supported.

Params:
name

is the name of the extension to query.

Returns:

a boolean indicating whether or not it is supported.

global function setMonitorEventsEnabled(enable: bool)

Enables or disables the "monconnect" events. By default they are disabled, but if you enable them you will receive them through pollEvents and waitEvents.

Params:
enable

is true to enable these events, and false to disable them.

global function getTime()

Returns:

the number of seconds elapsed since GLFW was initialized as a float, unless the time has been set with setTime. This is a very high-resolution timer.

global function setTime(time: int|float)

Sets the GLFW time to time, in seconds. It then continues to tick up from this value.

class Monitor

Represents a monitor attached to the system. You don't create instances of this class, instances are given to you by the getMonitors and getPrimaryMonitor functions.

Monitor.this(handle: nativeobj)

Constructor for use internally.

function Monitor.getPos()

Returns:

the position of the top-left corner of this monitor with respect to the "virtual desktop" that spans across all monitors. The position is returned as two integers, x and y.

function Monitor.getPhysicalSize()

Returns:

the width and height of this monitor in millimeters as two integers, x and y.

The size returned from this function may be inaccurate due to faulty drivers or EDID data.

function Monitor.getName()

Returns:

the name of this monitor.

function Monitor.getVideoModes()

Returns:

an array of supported fullscreen video modes.

Each video mode is a table containing the following members:

  • width: pixel width of the video mode

  • height: pixel height of the video mode

  • redBits: bits for the red channel

  • greenBits: bits for the green channel

  • blueBits: bits for the blue channel

  • refreshRate: refresh rate in Hz (as an integer)

function Monitor.getVideoMode()

Returns:

the monitor's current video mode as a table as described in getVideoModes.

function Monitor.setGamma(gamma: int|float)

Generates a gamma ramp using gamma as an exponent and sets the monitor's gamma to the new ramp. A gamma of 1.0 is the default; higher values make things brighter and lower values make things darker.

function Monitor.getGammaRamp()

Returns:

three arrays of integers, all the same length, which represent the monitor's current red, green, and blue gamma ramps.

function Monitor.setGammaRamp(r: array, g: array, b: array)

Takes the red, green, and blue gamma ramps as arrays of integers and sets the monitor's gamma to these new ramps.

All three ramp arrays must be the same length, and they have a maximum length of 256 elements.

Throws:
ValueError

if r, g, and b are not all the same length, or if they are 0 elements or more than 256 elements.

TypeError

if any of the values in the gamma ramps are not integers.

class Window

Represents a window and its associated OpenGL context. You don't create instances of this class, instances are given to you by the createWindow function.

Window.this(handle: nativeobj)

Constructor for use internally.

function Window.destroy()

Destroys this window and its associated OpenGL context. No more events will be generated for this window.

Throws:
StateError

if you call this method more than once.

function Window.shouldClose()

Returns:

a bool indicating whether this window should close. This flag is set to true when the user tries to close the window, and can also be set to true or false with setShouldClose.

function Window.setShouldClose(should: bool)

Sets the "should close" flag on this window to should.

function Window.setTitle(title: string)

Sets this window's title to title.

function Window.getPos()

Returns:

the desktop position of this window as two ints, x and y.

function Window.setPos(x: int, y: int)

Sets this window's desktop position to (x, y).

function Window.getSize()

Returns:

the size of this window in screen pixels as two integers, width and height.

The screen size can differ from the actual size of the framebufer for high-DPI displays. See getFramebufferSize.

function Window.setSize(w: int, h: int)

Sets the window's screen size to (w, h).

function Window.getFramebufferSize()

Returns:

the size of the window's framebuffer as two integers, width and height.

The framebuffer size can differ from the window's screen size for high-DPI displays.

function Window.iconify()

Minimizes this window.

function Window.restore()

Un-minimizes this window.

function Window.show()

Makes this window visible.

function Window.hide()

Makes this window invisible. It doesn't minimize it, it really makes it disappear from view entirely.

function Window.swapBuffers()

After drawing to the framebuffer through OpenGL, you must call this method to display anything.

function Window.getMonitor()

Returns:

the Monitor object that this window is fullscreened on, or null if this window is in windowed mode.

function Window.setCursorMode(mode: string)

Sets this window's cursor handling mode.

Params:
mode

must be one of the following values:

  • "normal": the cursor appears over this window as usual.

  • "hidden": the cursor will be invisible when over this window, but it can still be moved freely.

  • "disabled": the cursor will be hidden and also disallowed from leaving this window. This is useful for "mouselook" camera controls and the like.

function Window.getCursorMode()

Returns:

this window's cursor mode as a string, as described in setCursorMode.

function Window.setStickyKeys(enable: bool)

Sets whether or not this window uses "sticky keys".

If sticky keys are enabled, calls to getKey will return true even if the key in question has been released since it was last pressed. This is useful if you only care if keys have been pressed, but don't care about when.

function Window.getStickyKeys()

Returns:

this window's sticky keys mode. See setStickyKeys.

function Window.getStickyMouseButtons()

Returns:

whis window's sticky mouse buttons mode. See setStickyMouseButtons.

function Window.setStickyMouseButtons(enable: bool)

Sets whether or not this window uses "sticky mouse buttons".

This is the same as setStickyKeys except for mouse buttons and the getMouseButton method.

function Window.getKey(key: int)

Checks whether a key is currently being held down in this window.

Params:
key

should be one of the key enumerations.

Returns:

true if the key is being held down and false if not.

function Window.getMouseButton(button: int)

Checks whether a mouse button is currently being held down in this window.

Params:
button

should be a mouse button in the range 0 to 7 inclusive.

Returns:

true if the button is being held down and false if not.

function Window.getCursorPos()

Returns:

the position of the cursor relative to the top-left corner of this window as two doubles, x and y.

function Window.setCursorPos(x: int|float, y: int|float)

Moves the cursor to the screen position (x, y) relative to the top-left corner of this window.

function Window.setClipboardString(data: string)

Puts the string data on the OS clipboard.

This function can only be called from the main thread of your host application.

function Window.getClipboardString()

Returns:

the contents of the clipboard as a string, or null if the contents are not a string.

This method does not throw any exceptions, unlike many others.

function Window.getAttrib(attrib: int)

Gets one of the window's attributes.

The best reference for these attributes is the official docs. Note that where these docs say GL_TRUE, this library uses 1, and for GL_FALSE, 0.

function Window.enableEvents(vararg)

Enables any number of events on this window by name.

After creation, windows will not produce any events until you enable them with this method. You enable them by name, which are listed in the docs for pollEvents. For example, if you want to receive key, mouse button, and cursor position events, you might call:

window.enableEvents("key", "mousebutton", "curpos")
Now these events will be generated for this window.

function Window.disableEvents(vararg)

The opposite of enableEvents. Takes any number of event names just like it.

function Window.enableAllEvents()

Enables ALL types of events for this window.

function Window.disableAllEvents()

Disables ALL types of events for this window.

HTML and JavaScript source derived from by Victor Nakoryakov; Page generated on 15 Nov 2014 10:28:14