This is the API documentation for JSFX UI library. It is also available as an interactive JSFX plugin.
For more information, see GitHub or the Cockos forum topic.
You should read the getting-started tour first (see GitHub), which explains some important concepts such as the viewport stack.
However, here are a few short examples so you know what you're dealing with:
Here's a simple Hello World example.
We import the library in the header, and in @init we allocate it some of the memory buffer. It returns the first unused memory slot. In @gfx, we always call ui_start() first, to reset the UI state.
Then, we call ui_text() to draw some text to the screen.
While this library is designed to help you lay out your GUI, it's possible to ignore all the "viewport" stuff, and just use the rich controls, separate from everything else.
The key is to use ui_set_rect() or ui_push_rect() - this explicitly sets the dimensions of the viewport, which all the controls use to draw themselves.
(Do check out the layout stuff, though, in case it's useful.)desc:JSFX UI: No Layout
import ui-lib.jsfx-inc
@init
freemem = ui_setup(0);
strcpy(#text, "button text");
@gfx
ui_start();
// Set the viewport
ui_set_rect(20, 20, 200, 50);
// Draw a control
control_button(#text);
// And again
ui_set_rect(20, 100, 50, 50);
value = control_dial(value, 0, 1);
// And again
ui_set_rect(20, 180, 200, 50);
inputstate = control_textinput(#text, inputstate);
Any function named ui_*() attempts to be less opinionated about display. These functions handle layout, colours, basic text and mouse/keyboard interaction.
These functions provide a framework for everything else in the library.
ui_setup()
ui_start()
/ control_start()
ui_screen()
ui_screen_open()
ui_screen_close()
ui_screen_level()
ui_screen_arg()
ui_system()
/ control_system()
ui_setup()
new_freemem = ui_setup(freemem=0)
freemem
- index in the memory arraynew_freemem
- index in the memory arrayThis method sets up a section of the memory buffer for use by the UI library.
You must call this in @init, before any other UI code.
@init
//Unused section of memory buffer
freemem = 0;
// Returns end of allocated block (first unused index)
freemem = ui_setup(freemem);
ui_start()
/ control_start()
ui_start(default_screen)
# control_start(default_screen, theme)
default_screen
- default screen ID, an identifiertheme
- "default", "tron" or "black"These methods resets the UI state for the start of each frame. You must call one of these in @gfx, before any other UI code.
The default_screen variable is a screen identifier - see ui_screen().
control_start() has an additional "theme" parameter, which must be a string constant, one of: "default", "tron" or "black".
ui_screen()
This method returns the current screen ID, a unique identifier for that screen. Use this to determine which screen you should draw.
Even if you only have one screen, you should use this so that you can get error messages or other info using ui_system().
The screen ID is treated as a number, but the best screen IDs are string constants - all identical string constants are represented by the same number, and it makes your code more readable.
@gfx
ui_start("main");
ui_screen() == "main" ? (
/* draw your main screen */
) : ui_system();
ui_screen_open()
This method opens a new screen on top of the stack of screens.
The screen stack is limited to 10 layers deep.
@gfx
ui_start("main");
ui_screen() == "main" ? (
control_button("open screen") ? (
ui_screen_open("secondary");
);
) : ui_screen() == "secondary" ? (
/* draw second screen */
) : ui_system();
ui_screen_close()
ui_screen_close()
This function closes the current screen.
@gfx
ui_start("main");
ui_screen() == "main" ? (
control_button("open screen") ? (
ui_screen_open("secondary");
);
) : ui_screen() == "secondary" ? (
control_button("close screen") ? (
ui_screen_close();
);
) : ui_system();
ui_screen_level()
This function tells you how many screens deep you are in your current stack. The top level is 0.
depth = ui_screen_level();
ui_screen_arg()
Sets or gets the screen argument at a given index. If you pass in two arguments, it sets the value. If you only pass in one, it returns the value.
When setting values for a new screen, this must be called *after* ui_screen_open(), otherwise it will set the arguments for the current screen instead.
// Read argument for current screen
foobar = ui_screen_arg(0);
// Open new screen with argument
should_open_screen ? (
ui_screen_open("screen2");
ui_screen_arg(0, foobar);
);
ui_system()
/ control_system()
These methods provide system screens.
ui_system() provides a basic error display (for unrecognised screen IDs, or errors due to incorrect use of the UI library), which is useful for developing and bugfixing.
control_system() provides an additional screen: "control.prompt", as well as a slightly prettier error screen.
@gfx
ui_start("main");
ui_screen() == "main" ? (
/* draw your main screen */
) : ui_system();
This is a screen ID provided by control_system(). It provides a convenient way to prompt the user for text entry.
The screen takes two arguments: a mutable string, and a title for the popup.
The library keeps an internal stack of viewport/drawing states. These include viewport position (area of the screen that is currently being drawn to), colours, fonts, and so on.
Some functions modify the current drawing state (such as changing colour), but layout is generally done by pushing a new viewport/state onto the stack with the desired modifications.
When a state is popped off the stack, the active drawing state (e.g. viewport position, colours) return to their previous values.
In the code examples, we use indentation to help clarify the current depth of the stack.
ui_push()
/ ui_pop()
ui_push_clip()
ui_split_next()
ui_push()
/ ui_pop()
ui_push() pushes a new viewport/state onto the stack. The new state is a copy of the previous state, but changes to this new state do not affect the previous state.
ui_pop() removes the top later of the viewport/state stack.
// stack starts with just 1 state
ui_push();
// stack is now 2 levels deep
ui_color(255, 0, 255);
ui_border(); // draws in purple
ui_pop();
// stack is now 1 deep again
// The colour change above applied
// to the state we popped off,
// so this draws in default colour
ui_text("some text");
ui_push_clip()
ui_push_clip() behaves a lot like ui_push(), except all changes are clipped to the current viewport, and have a global opacity applied. If opacity is zero (or omitted), it is taken to be 1.
Internally, this is implemented by copying the current screen state to a new buffer, drawing as normal (to that buffer, using gfx_dest), and then copying back with the appropriate opacity on the matching ui_pop() call.
ui_push_height(pixels)
# ui_push_heightratio(ratio)
# ui_push_heighttext(#text)
# ui_push_width(pixels)
# ui_push_widthratio(ratio)
# ui_push_widthtext(#text)
pixels
- integer >= 0ratio
- between 0 and 1#text
These methods let you push a new viewport to the stack, with a specified height/width. Their position is determined by the current alignment.
ui_push_above(pixels)
# ui_push_aboveratio(ratio)
# ui_push_abovetext(#text)
# ui_push_below(pixels)
# ui_push_belowratio(ratio)
# ui_push_belowtext(#text)
# ui_push_leftof(pixels)
# ui_push_leftofratio(ratio)
# ui_push_leftoftext(#text)
# ui_push_rightof(pixels)
# ui_push_rightofratio(ratio)
# ui_push_rightoftext(#text)
pixels
- integer >= 0ratio
- between 0 and 1#text
These methods let you push a new viewport to the stack, fitting around the viewport that would be produced by ui_push_height() or ui_push_width().
ui_split_top(height)
# ui_split_bottom(height)
# ui_split_left(width)
# ui_split_right(width)
height
- integer >= 0width
- integer >= 0The ui_split_*() functions push a new viewport/state onto the stack, anchored to one edge. Simultaneously, they shrink the previous viewport by the same amount, so that the two do not overlap.
This gives an easy way to carve out sections of the screen to place elements, and then guarantee that other elements will not overlap with them later.
ui_split_topratio(ratio)
# ui_split_bottomratio(ratio)
# ui_split_leftratio(ratio)
# ui_split_rightratio(ratio)
ratio
- between 0 and 1The ui_split_*ratio() functions work exactly like the ui_split_*() functions, but with the split point specified as a ratio of the height/width.
ui_split_toptext(#text)
# ui_split_bottomtext(#text)
# ui_split_lefttext(#text)
# ui_split_righttext(#text)
#text
The ui_split_*ratio() functions work like the ui_split_*() functions, but the split point is determined by the height/width of a text string, plus some appropriate padding (from ui_padding() and related functions).
If you supply a negative number, it is equivalent to the empty string (which still has non-zero height).
ui_split_next()
ui_split_next()
When you have performed a split using any of the ui_split_*() methods, you can use ui_split_next() to pop the viewport/state from the stack, and then re-split using the same height/width.
This lets you very easily subdivide into equal-sized pieces, or stack items up from one edge.
ui_split_topratio(1/4);
ui_color(255, 0, 0);
ui_border();
ui_text("first section");
ui_split_next();
ui_color(128, 128, 0);
ui_border();
ui_text("second section");
ui_split_next();
ui_color(0, 255, 0);
ui_border();
ui_text("third section");
ui_split_next();
ui_color(0, 128, 255);
ui_border();
ui_text("fourth section");
ui_pop();
If you want to draw a custom control/display, you can query the current viewport so that you can fit into the layout the way that other controls do. For more complicated layouts, it's sometimes useful to directly set the viewport, so there are functions for that too.
You can actually use ui_set_rect() to use the built-in rich controls without using the layout/viewport stack at all - see the "Ignoring all layout" example in the Introduction.
left_x = ui_left()
# right_x = ui_right()
# top_y = ui_top()
# bottom_y = ui_bottom()
# width = ui_width()
# height = ui_height()
left_x
- integerright_x
- integertop_y
- integerbottom_y
- integerwidth
- integerheight
- integerThese return the boundaries and dimensions of the current viewport.
Much like gfx_w and gfx_h, the right/bottom edges are the first pixels that are *not* included in the viewport.
ui_align(0, 0.5);
ui_textnumber(ui_left(), "%i");
ui_align(1, 0.5);
ui_textnumber(ui_right(), "%i");
ui_align(0.5, 0);
ui_textnumber(ui_top(), "%i");
ui_align(0.5, 1);
ui_textnumber(ui_bottom(), "%i");
sprintf(#size, "%i x %i", ui_width(), ui_height());
ui_align(0.5, 0.5);
ui_text(#size);
ui_border();
ui_set_rect(left, top, width, height)
left
- integer >= 0top
- integer >= 0width
- integer >= 0height
- integer >= 0This explicitly sets the position and dimensions of the current viewport.
ui_push_rect()
ui_push_rect(left, top, width, height)
left
- integer >= 0top
- integer >= 0width
- integer >= 0height
- integer >= 0This is equivalent to ui_push() followed by ui_set_rect(). It's useful if what you draw also changes viewport parameters (e.g. colours, fonts), because these are reset on the corresponding ui_pop();.
ui_push_rect(left, top, width, height);
ui_color(255, 0, 255, 0.5);
ui_fill();
ui_pop();
// Colour is not changed
ui_text("some text");
A few of the UI operations involve a default amount of padding. For example, the ui_split_*text() add padding to the text measurements to determine the split size.
This padding size is part of the viewport/drawing state, and is dealt with by these functions.
ui_pad()
ui_pad(left, top, right, bottom)
# ui_pad(leftAndRight, topAndBottom)
# ui_pad()
left
- integer >= 0top
- integer >= 0right
- integer >= 0bottom
- integer >= 0leftAndRight
- integer >= 0topAndBottom
- integer >= 0This function shrinks the current viewport by the specified amount.
When the padding size is omitted (in ui_pad() or in the side-specific variations), it uses a default padding size. This is also the padding size added when using ui_split_*text().
These functions add padding on one edge only. If the length is 0, the default padding is used.
ui_border();
ui_padleft(left);
ui_padtop(top);
ui_padright(right);
ui_padbottom(bottom);
ui_border();
ui_padding(padding_horizontal, padding_vertical)
# padding_horizontal = ui_padding_x()
# padding_vertical = ui_padding_y()
padding_horizontal
- integer >= 0padding_vertical
- integer >= 0These functions allow you to read or set the default padding. Different themes have different default padding sizes.
ui_border();
ui_padding(pad_x, pad_y);
ui_pad();
ui_border();
ui_color(red, green, blue, alpha)
# ui_color()
red
- integer between 0 and 255green
- integer between 0 and 255blue
- integer between 0 and 255alpha
- between 0 and 1This function sets the current drawing colour. It uses RGB values in the 0-255 range, and an optional alpha in the 0-1 range.
These values are translated into the gfx_r/gfx_g/gfx_b/gfx_a variables. If ui_color() is called with no arguments, these variables are recalculated.
ui_align(horizontal, vertical)
# horizontal = ui_align_x()
# vertical = ui_align_y()
horizontal
- between 0 and 1vertical
- between 0 and 1These function set and read the current alignment. They are ratios, so 0 means left/top, and 1 means right/bottom.
If an out-of-range value is passed to ui_align(), it is ignored. This means you can set the alignments independently - e.g. ui_align(0, -1) will change the horizontal alignment to hard-left, but leave the vertical alignment unchanged.
ui_font(#face, size, bold, italics)
# ui_fontface(#face)
# ui_fontsize(size)
# size = ui_fontsize()
# ui_fontbold(bold)
# ui_fontitalic(italics)
# ui_font()
#face
size
- integer between 8 and 100bold
- booleanitalics
- booleanSpecify the font parameters, individually or all at once.
The UI library uses font index 16, and configures this accordingly. ui_font() called with no arguments re-configures this font, in case it has been changed.
Although the default colours vary, these drawing functions are theme-independent.
ui_fill()
ui_fill()
Fills the viewport with the current colour.
ui_image_fill()
Fills the viewport with an image, scaled and cropped to fill the whole area.
The image index is the number used in the "filename:" declaration at the top (or the index of an off-screen buffer).
ui_image_fill(0);
ui_border()
and othersDraws a border in the current colour.
ui_graph(buffer, count, offset=0, min_y, max_y)
# ui_graph(buffer, count, offset, wrap_length, min_y, max_y)
# ui_graph_step(buffer, count, step, offset=0, min_y, max_y)
# ui_graph_step(buffer, count, step, offset, wrap_length, min_y, max_y)
buffer
- index in the memory arraycount
- integer >= 1offset
- offset within the circular buffer, integer >= 0min_y
max_y
wrap_length
- length of circular buffer (defaults to == count), integer >= 1step
- integer >= 1Plots a graph from a buffer. "offset" sets the starting point, treating the buffer as circular. "wrap_length" is for when the circular buffer is longer than "count".
ui_graph() chooses a step size so that not too many points are drawn per horizontal pixel. If you need to draw every point, use ui_graph_step() with step=1.
If min_y and max_y are the same, the graph is centered around that value, and auto-scaled to fit the data.
ui_reserve_image()
The UI library uses some of the offscreen buffers (0-127) for its own use. If there are any buffers (or loaded images) that you are also using, you can notify the UI library so that it avoids them.
The UI library uses buffers from the end (127 downards), so they are unlikely to clash unless you are loading a large number of images or are using offscreen buffers yourself.
@gfx
// Draw something to buffer #95
gfx_dest = 95;
gfx_drawstr("foo");
// Avoid conflict
ui_reserve_image(95);
// This resets gfx_dest, so we're fine
ui_start("main");
/* etc. */
Although the default fonts/etc. vary, these functions are theme-independent.
ui_text()
ui_wraptext()
/ ui_wraptext_height()
ui_texth()
ui_text_width()
/ ui_text_height()
ui_textnumber()
ui_parsenumber()
ui_text()
Draws text into the viewport, using the current alignment.
Text not wrapped, but is shrunk to fit the space if necessary.
ui_wraptext()
/ ui_wraptext_height()
ui_wraptext() draws text into the viewport, using the current alignment. Text wraps, but is not shrunk to fit, so may overflow.
ui_wraptext_height() measures the text without actually drawing it (which is useful for positioning things around wrapped text).
ui_texth()
Gets the current height of a single line, resetting the gfx_* font parameters if necessary.
line_height = ui_texth();
ui_text_width()
/ ui_text_height()
text_width = ui_text_width(#text)
# text_height = ui_text_height(#text)
#text
text_width
- integertext_height
- integerMeasures the width/height of text, resetting the gfx_* font parameters if necessary.
This will return a non-zero height even for empty strings.
text_width = ui_text_width(#text);
text_height = ui_text_height(#text);
ui_textnumber()
Formats a number using sprintf() formats, and draws it using ui_text().
ui_parsenumber()
This function parses string into a number.
It stops at the first invalid character, returning the default value if it did not find a valid number first. Whitespace is ignored.
number = ui_parsenumber(#number_string, default);
For raw mouse state, you can still use mouse_x, mouse_y and mouse_cap. These functions deal with more complex interactions, like dragging and hovering.
For any function that takes a "button index" argument, it uses the standard JSFX numbers of 1=left, 2=right, 64=middle. Omitting this argument defaults to 1 (left click).
ui_click()
/ ui_clickcount()
ui_hover()
ui_press()
relative_x = ui_mouse_x()
# relative_x = ui_mouse_xratio()
# relative_x = ui_mouse_y()
# relative_y = ui_mouse_yratio()
relative_x
relative_y
These functions return the mouse position relative to the current viewport, either in absolute pixels or as a ratio.
x = ui_mouse_x();
y = ui_mouse_y();
x_ratio = ui_mouse_xratio();
y_ratio = ui_mouse_yratio();
ui_click()
/ ui_clickcount()
pressed = ui_click(button=1)
# count = ui_clickcount(button=1)
button
- 1, 2 or 64pressed
- booleancount
- integer >= 0ui_click() returns whether the user clicked within this viewport, and released within this viewport. If the mouse moved outside the viewport within this time and then back in again, it still counts as a "click". It returns 0, or the duration of the click.
ui_clickcount() can be used to detect double-clicks/triple-clicks/etc.
ui_click() ? (
ui_fill();
last_clickcount = ui_clickcount();
);
Returns the mouse movement since the last frame.
dx = ui_mouse_dx();
dy = ui_mouse_dy();
// Draw mouse movement
mx = mouse_x;
my = mouse_y;
gfx_line(mx, my, mx - dx, my - dy);
event = ui_mouse_down(button=1)
# event = ui_mouse_down_outside(button=1)
button
- 1, 2 or 64event
- booleanReturns whether the mouse button has just been pressed, either inside the current viewport (ui_mouse_down) or outside (ui_mouse_down_outside).
event_counter1 += ui_mouse_down(1);
event_counter2 += ui_mouse_down(2);
event_counter64 += ui_mouse_down(64);
Returns whether the mouse button has just been released, while the mouse is inside the current viewport.
event_counter1 += ui_mouse_up(1);
event_counter2 += ui_mouse_up(2);
event_counter64 += ui_mouse_up(64);
drag_time = ui_drag(button=1)
# drag_x = ui_drag_x(button=1)
# drag_y = ui_drag_y(button=1)
button
- 1, 2 or 64drag_time
- booleandrag_x
drag_y
Returns whether the current viewport is currently being dragged or held-down (mouse-down within the viewport, then moved or held for a period of time).
ui_drag() returns either 0, or the time since mouse-down.
drag_time = ui_drag();
drag_x = ui_drag_x();
drag_y = ui_drag_y();
Returns the scroll-wheel movement since the last frame.
dx = ui_scroll_x();
dy = ui_scroll_y();
ui_hover()
Returns whether the mouse position is inside the current viewport.
hover = ui_hover();
hover ? ui_fill();
ui_press()
Whether the user originally clicked within the viewport, and is currently hovering over it with the mouse-button pressed down.
Returns either 0, or the time since the original press.
If the user clicks and drags away from the viewport, then back into it, that still counts as "pressing".
pressed = ui_press();
pressed ? ui_fill();
ui_click_clear()
Prevents any later code from registering clicks, drags, and so on. In essence, it release all currently-held mouse buttons, but without triggering any events.
This is most useful when what's on the screen is about to change - it is done automatically when opening/closing screens, so that the new page does not register any events it shouldn't.
This does not affect mouse_cap, only the functions available in this UI library.
ui_click() ? (
//Prevent anyone else from registering this click
ui_click_clear();
)
ui_key() returns the char code of the latest unhandled key-press, or 0 if there is none.
ui_key() will return the same char code until ui_key_next() is called, or until the next frame (more precisely, the next call to ui_start()). This lets multiple sections of code "peek" at the latest key, and choose whether to ignore it or claim it.
ui_key_printable() is similar, but it also returns 0 for non-printable characters.
If you want to receive the full range of keypresses (including things like space/escape, which normally go to the host), put "options:want_all_kb" in the header of your effect.
char = ui_key();
lastchar = char ? char : lastchar;
ui_interacted()
This function returns whether the user has interacted with this effect since last frame.
Interaction is defined as: pressing/releasing any mouse button or control key, scrolling the mouse wheel, moving the mouse while a button is held down, or pressing a key.
interacted = ui_interacted();
The functions in this section provide a common set of rich interactive controls.
They have a distinct visual look (see control_start() for how to choose a theme), and attempt to present consistent interactions (e.g. double-click to reset to default value, drag up/down to adjust dials).
control_dialog()
action = control_dialog(#title)
# action = control_dialog(#title, #ok)
# action = control_dialog(#title, #ok, #cancel)
# action = control_dialog(#title, width, height, #ok, #cancel)
#title
#ok
#cancel
width
- integer >= 0height
- integer >= 0action
- 0 or 1Decorates the viewport to be a dialog. Afterwards, the viewport is inside the area of the dialog. This is probably the first thing you want to draw inside your screen.
The returned action is 0 if nothing was clicked and it expects to stay on this screen, -1 if "cancel" was clicked, and 1 if "OK" was clicked - if either of these is clicked, the screen will close itself, so you only need to check if you want to perform an additional action (such as saving results or writing screen arguments). This also means that any screen arguments should be read *before* the call to control_navbar(), or they might be read from the incorrect screen.
If "cancel" is omitted, then no cancel button will be displayed.
control_group()
This draws a labelled group indicator in the current viewport, and adds padding so that elements are placed inside this group.
value = control_slider_left(value, left_value, right_value, curve=0, default)
# value = control_slider_x(value, left_value, right_value, curve=0, default)
# value = control_slider_bottom(value, bottom_value, top_value, curve=0, default)
# value = control_slider_y(value, bottom_value, top_value, curve=0, default)
value
left_value
right_value
curve
default
bottom_value
top_value
Draws a horizontal or vertical slider.
The "curve" parameter determines how the visual position of the slider corresponds to the actual values. Positive values give more accuracy on the left/top side, negative on the right/bottom. For a logarithmic scale, use curve=log(left_value/right_value).
Sliders with a particular side (e.g. "left") will show a link between the current value and that side. control_slider_x() and control_slider_y() will not show that link, but *may* show a link between the current value and the default value, if one is provided.
ui_split_topratio(1/4);
ui_split_left(70);
ui_text("curve=0");
ui_pop();
value = control_slider_left(value, 0, 1, 0, 0.5);
ui_split_next();
ui_split_left(70);
ui_text("curve=2");
ui_pop();
value = control_slider_left(value, 0, 1, 2, 0.5);
ui_split_next();
ui_split_left(70);
ui_text("curve=-2");
ui_pop();
value = control_slider_left(value, 0, 1, -2, 0.5);
ui_split_next();
ui_split_left(70);
ui_text("slider_x");
ui_pop();
value = control_slider_x(value, 0, 1, 0, 0.5);
ui_pop();
value = control_dial_left(value, left_value, right_value, curve=0, default)
# value = control_dial(value, left_value, right_value, curve=0, default)
# angle = control_dial_angle(angle, default)
# angle = control_dial_angle_unit(angle, default)
value
left_value
right_value
curve
default
angle
Draws a rotating dial. The "curve" parameter works the same was as for sliders.
Like sliders, control_dial_left() will show a link between the current value and the left value, and control_slider() will not show that link (but may show a link to the default value).
control_dial_angle() provides a dial that can rotate freely, returning a value between 0 and 2*PI, where 0 is vertical. control_dial_angle_unit() is similar, but uses values between 0 and 1.
JSFX has no built-in text inputs, so this isn't quite as smooth as a native control, but it's functional. It supports selecting with the mouse (including double-clicking on words) or keyboard.
Text inputs pack their internal state into an opaque state value, which you need to store and pass back to it next time, otherwise they won't work. You should not store this state in presets/sliders, or attempt to manipulate it directly - use the appropriate functions.
If you want to enter interesting characters (like space) which would otherwise be handled by the host, put "options:want_all_kb" in the header of your effect.
control_textinput()
control_textinput_focused()
control_textinput_focus()
control_textinput_unfocus()
control_textinput_select()
control_hidden_text()
/ control_hidden_textnumber()
control_textinput()
opaquestate = control_textinput(#text, opaquestate)
#text
- mutable stringopaquestate
- opaque value used by the control, initialised to 0Draws a text input, constantly updating the mutable string #text.
control_textinput_focused()
Returns whether the given text input currently has focus (i.e. is processing keyboard events).
control_textinput_focused(opaquestate) ? (
/* do whatever */
);
control_textinput_focus()
Demand focus for this input element
opaquestate = control_textinput_focus(opaquestate);
control_textinput_unfocus()
Decline focus for this input element
opaquestate = control_textinput_unfocus(opaquestate);
control_textinput_select()
opaquestate = control_textinput_select(opaquestate, cursor, select_end)
opaquestate
cursor
- integerselect_end
- integerChanges the selection in the text input (but not the focus state).
should_select_all ? (
state = control_textinput_select(state, 0, strlen(#my_text));
);
control_textinput(#my_text, state);
No UI library can provide everything, so it provides some ways to draw custom controls that fit into the theme.
control_background_enabled(state="auto")
# control_background_disabled(state="auto")
# control_background_passive(state="auto")
# control_background_inset(state="auto")
# control_background_technical(state="auto")
# control_finish_enabled(state="auto")
# control_finish_disabled(state="auto")
# control_finish_passive(state="auto")
# control_finish_inset(state="auto")
# control_finish_technical(state="auto")
state
- "press", "hover", "drag", "none" or "auto"These help you create custom controls that fit into the theme, by drawing a background and an overlay in the appropriate style, including setting an appropriate ui_color().
If state is omitted ("auto"), it is calculated using the current mouse interaction. However when creating a composite control it's useful to have a shared state (e.g. when any part of the control is pressed, the whole control displays as pressed).
ui_split_topratio(1/5);
ui_pad();
control_background_enabled(state);
ui_text("enabled");
control_finish_enabled(state);
ui_split_next();
ui_pad();
control_background_disabled(state);
ui_text("disabled");
control_finish_disabled(state);
ui_split_next();
ui_pad();
control_background_passive(state);
ui_text("passive");
control_finish_passive(state);
ui_split_next();
ui_pad();
control_background_inset(state);
ui_text("inset");
control_finish_inset(state);
ui_split_next();
ui_pad();
control_background_technical(state);
ui_text("technical");
control_finish_technical(state);
ui_pop();
control_state()
This returns the current mouse-interaction state of the current viewport.
These values match what can be passed into control_background_*() and control_finish_*(). This lets you assemble a composite control that shares a single press/hover/drag state.
Reported states are "press", "hover", "drag" and "none", in that order of precedence - so if the user has clicked and dragged, but is still within the control (so it counts as a press), then it will report "press".
state = control_state();
control_arrow()
Draws a triangle in the current viewport, using the current colour.
pixel_scale = ui_retina()
# old_pixel_scale = ui_retina(new_pixel_scale)
new_pixel_scale
pixel_scale
- The current pixel-scaleold_pixel_scale
- the previous pixel scale, before it was changedSupport for Retina displays (double-resolution pixels on Macs) can be enabled by setting gfx_ext_retina=1. If Retina mode is active, the drawing area will be bigger, and mouse positions will be scaled - however, the UI library scales down its viewport/measurements so that it appears to be the same size.
However, if you need to draw your own custom controls, you now have a scaling factor to contend with.
The best way to handle this is ui_retina().
If called with no argument (or 0), ui_retina() returns the current pixels-scaling value (2 for retina displays, 1 otherwise). If called with an argument, it sets the pixel scaling value, and changes the viewport appropriately.
Be warned, however, that mouse positions (both mouse_x/mouse_y and functions like ui_mouse_x()) will remain scaled-down, so you might want to save the previous pixel-scaling value and restore it before the mouse-based calculations.
This state is stored in the viewport/drawing stack, so it will be restored on ui_pop().
// Reset to 1-to-1 scale
old_pixel_scale = ui_retina(1);
/* Draw something using viewport */
gfx_rect(ui_left(), ui_top(), ...);
//Set back to the old one
ui_retina(old_pixel_scale);
/* Logic involving mouse-pointer */
xratio = ui_mouse_xratio();