0.6.0 — Debugging & misc stuff
Pre-releaseWith 134 commits in since last release, 0.6.0 is probably the biggest update to Fluid yet, and the first one to use the new name. It offers a lot of new improvements, making it easier to manage input thanks to Input Actions, automatic keyboard support through tabbing and arrow keys, improving and optimizing text rendering and providing out-of-the-box Unicode support. Furthermore, Tree Actions enable lazily walking through the tree while drawing and there are significant changes to the library's core, making it possible to use Fluid without depending on Raylib.
Breaking changes
- The entire package has been renamed. Glui is now Fluid.
- Node class prefixes have been removed with few exceptions. Goodbye
GluiFrame
,GluiLabel
,GluiButton
, now we can be more concise.GluiInput
is nowInputNode
- All subclasses of
InputNode
mustmixin enableInputActions
. Presence of the mixin is checked at runtime. - Fluid may now perform some actions by default when pressing Tab, Shift+Tab, Arrow keys, or chosen gamepad buttons (LB, RB, A, B, D-pad). You may override those with
node.tree.bindInputReplace
ornode.tree.clearBoundInput
- Fluid now uses its own
Typeface
class to implement font rendering on top of Freetype2 or Raylib. RichLabel
was removed, because it was rooted in old codebase and impossible to maintain. There is no replacement yet.- Supoprt for Raylib versions 3 and 4 has been dropped. Please use Raylib 5.
- Nodes cannot use Styles and Themes that are
const
orimmutable
anymore.mixin defineStyles
will now define mutable style fields. - Side arrays used in styles for padding, margin and border are now
float[4]
and notint[4]
to support changes to how Fluid handles HiDPI.
Previously deprecated
dropdown
andGluiDropdown
were renamed topopup
andPopup
respectively.mousePass
was renamed toignoreMouse
.hidden
,hovered
anddisabled
were renamed toisHidden
,isHovered
andisDisabled
respectively.preventOverlap
was renamed topreventOverflow
.childRef
has been removed.
Now deprecated
TextInput.multiline
was never implemented. It would probably be better off as a subclass or a separate node.LayoutTree.disabledDepth
has been replaced with a simple booleanisBranchDisabled
. Also, a more genericLayoutTree.depth
was added, which doesn't track disabled nodes.- All font related fields in
Style
, except forfont
itself, have been deprecated. Please use fields and methods present in the Typeface interface, e.g.Style.typeface.lineHeight
. Many options are currently vendor-specific. label
defaulting to being empty is now deprecated — initial text is now required.filePicker
has been renamed tofileInput
[vh]scrollBar
have been renamed to[vh]scrollInput
popup
has been renamed (again) topopupFrame
BasicNodeParams
is deprecated. Node constructors should now takeNodeParams
as the first argument instead. The burden of collecting theme and layout has been moved tosimpleConstructor
.
Input actions
Fluid 0.6.0 introduces the all-new input actions. Those let you easily bind inputs to methods for focused or hovered nodes. Those inputs can later be rebound, so you can make them configurable for the user.
By default, every node has actions bound to switch between nodes via tab, shift+tab and arrow keys. Neighboring nodes are picked based on distance and semantic information, making the feature intuitive for the user with minimal to no effort needed from the programmer.
class MyNode : InputNode!Label {
mixin enableInputActions;
/// Triggers when you press the node with left mouse button or press Enter when focused.
@(FluidInputAction.press)
void _press() {
writeln("Node pressed!");
}
}
// Actions can be rebound
auto ui = vframe(
label("Hello, World!")
);
ui.draw();
ui.tree.bindInput(FluidInputAction.press, InputStroke(KeyboardKey.z));
// Warning: ui.tree access requires at least one draw!
// Gamepads are also supported!
ui.tree.bindInput(FluidInputAction.press, InputStroke(GamepadButton.rightTrigger));
// Actions can be checked at any time with isDown and isActive
ui.tree.isDown!(FluidInputAction.press);
ui.tree.isActive!(FluidInputAction.press);
// You can define your own actions by creating an enum and marking it @InputAction
enum MyAction {
attack,
jump,
dash,
}
class InputHandler : InputNode!Node {
mixin enableInputActions;
@(MyAction.attack)
void _attack() {
}
// You can handle multiple actions in a single function:
@(MyAction.jump, MyAction.dash)
void _move(MyAction action) {
}
}
focusImpl
and mouseImpl
can be used for advanced usage input actions cannot handle.
On a related change, FluidHoverable
is now available as a subset of FluidFocusable
, for nodes that interact with the mouse, but not the keyboard.
textInput now correctly processes repeated backspace thanks to changes in Raylib 5 and backend split.
PR #70, issue #8
Popup improvements
Popups have seen significant improvements thanks to a related change, the introduction of tree actions. Popups can now be displayed without making mapSpace
the root of your node tree, they can be nested and have full keyboard support.
A new node, popupButton
has been introduced, which will open a popup when clicked. It's perfect for creating dropdown menus, and can be nested.
popupButton("Options",
button("Edit", delegate { }),
button("Copy", delegate { }),
popupButton("Share",
button("SMS", delegate { }),
button("Via e-mail", delegate { }),
button("Send to device", delegate { }),
),
);
Freetype2 integration
Fluid now comes with Freetype2 support, which means:
- Improved Unicode support — A compatible font should work straight out of the box!
- Reduced memory footprint — Text should only drain memory when updated.
- Better font quality — All the precious hinting shouldn't get lost.
Moreover, Freetype2 is now the default font backend. The default font is also now Ruda, instead of Raylib's raster typeface.
If you used Style.loadFont
(now aliased to Style.loadTypeface), your app should automatically start using Freetype2. You might however encounter issues if you relied on
Font, since the function now returns a
Typeface`.
Please note that it's still possible to draw text with the Raylib backend, which should see improved performance as well, but is from now on discouraged. This must be done explicitly by using new RaylibTypeface
.
Improved HiDPI support
Fluid now consistently uses "pixel" as 1/96th of an inch. It's possible to specify the DPI of a texture to make it scale better under HiDPI environments. This makes text display a lot better on displays with increased DPI.
Raylib's FLAG_WINDOW_HIGHDPI
flag is now discouraged.
Switching backends
While Raylib remains supported and the best option to use with Fluid, Fluid does not exclusively rely on Raylib anymore. For example, arsd.simpledisplay can now be used with Fluid using the built-in SimpledisplayBackend
. It's possible Hipreme Engine will also get support soon.
This is also a significant shift in development focus of Fluid, since the library could now be integrated into different rendering APIs like Metal or Vulkan, or even CPU rendering. With further modifications, core components could be modified to bind to existing GUI frameworks like Qt, Windows Forms or Cocoa.
The HeadlessBackend is now also available, if you'd like to Fluid flowing in your code, even when not rendering anything. It's particularly useful for running tests — and is now powering Fluid's unit tests.
New showcase
The old examples have been notoriously bad for what examples should have been. They had their share as a testing suite, but Fluid has now moved to regular unit tests.
Instead, they have been replaced with a unified showcase. A single app that goes through different topics covering Fluid usage, with live code examples. It's similar to D's tour page, except specifically to talk about Fluid.
The showcase is still a work in progress and isn't complete, but hopefully should already offer a good start to anyone looking to start using Fluid!
On another note, the readme.md
file has been updated to offer a friendlier introduction to Fluid.
Tree actions
Advanced stuff: Tree actions let you lazily iterate the tree while it's being drawn. It can be really useful for managing focus or performing more complex node tree operations.
A few actions come built-in:
focusRecurse
will set focus on the first available node within a given branch of the tree. Its variant,focusRecurseChildren
will ignore the root of the branch.scrollIntoView
will update any parent scrolling container so that the chosen node appears in the view.
class MyAction : TreeAction {
override void beforeDraw(Node node, Rectangle space) {
// stuff!
// Call `stop()` to immediately end the action. Note afterDraw and afterTree won't be called.
}
// Tree actions are only performed once by default. Override `afterTree` to stop this behavior.
override void afterTree() {
// or if you want to keep it, call `stop()` or `super.afterTree()`
}
}
// Queue an action for the next draw
tree.queueAction(new MyAction);
// Or, queue it for a specific tree branch
node.queueAction(new MyAction);
PR #70, issue #71
Miscellaneous improvements
- Various allocation optimizations; Fluid shouldn't allocate during regular draw loops. Text rendering will be the most affected.
- There have been improvements in how the
filePicker
is displayed. Directories can also be picked using the mouse. Further improvements to the file picker are planned in #82. - The Children debugging helper will now detect missed
updateSize
calls. - OpenGL texture destruction is now performed in a thread-safe and GC-safe manner, making it possible to destroy textures in destructors, even in multithreaded context.
dub init -t fluid
should now work as a way to create new projects using Fluid.