RmlUi - The HTML/CSS User Interface library evolved

#gamedev #gui #ui #hud #cpp #lua #html #css #web #dom #compiled #webview #htmlview #webgui #framework

Michael Ragazzon a784fa0df1 Faster erase duplicates 6 лет назад
Build 9abed76c97 Update generate file lists scripts 6 лет назад
Dependencies d82193614f Initial changes to make building dependancies much easier and require less knowledge of how the sub projects work 10 лет назад
Include fd44d9cfcb Optionally use EventId on add/remove listener. In the EventDispatcher, replace the map<vector> with a flat, manually sorted vector. 6 лет назад
Samples fd44d9cfcb Optionally use EventId on add/remove listener. In the EventDispatcher, replace the map<vector> with a flat, manually sorted vector. 6 лет назад
Source a784fa0df1 Faster erase duplicates 6 лет назад
.appveyor.yml b9e071d3b9 Oops. 6 лет назад
.gitignore bf36355694 Merge branch 'master' into transform 7 лет назад
.travis.yml 3303618124 Install libsfml-dev in clang and gcc builds 6 лет назад
LICENSE bd0fd853e2 Add license file 6 лет назад
changelog.txt dd10a3ecb7 Version number updates for 1.3.0 release 11 лет назад
how_to_build_for_mingw.txt a0dd1982f4 Rename STATIC_LIB macro to ROCKET_STATIC_LIB. 11 лет назад
readme.md 9ec34390be Added system interface functions for getting and setting the clipboard. Implemented in Windows shell, along with mouse cursor. The drag sample and the invader options page demonstrate the cursor property. 6 лет назад

readme.md

RmlUi - The HTML/CSS User Interface Library Evolved

RmlUi

RmlUi - now with added boosters taking control of the rocket, targeting your games and applications.


Build Status Build status

RmlUi is the C++ user interface package based on the HTML and CSS standards, designed as a complete solution for any project's interface needs. It is a fork of the libRocket project, introducing new features, bug fixes, and performance improvements.

RmlUi uses the time-tested open standards XHTML1.0 and CSS2.0 while borrowing features from HTML5 and CSS3, and extends them with features suited towards real-time applications. Because of this, you don't have to learn a whole new proprietary technology like other libraries in this space.

Documentation is located at https://mikke89.github.io/RmlUiDoc/

Features

  • Cross platform architecture: Windows, macOS, Linux, iOS, etc.
  • Dynamic layout system.
  • Full animation and transform support.
  • Efficient application-wide styling, with a custom-built templating engine.
  • Fully featured control set: buttons, sliders, drop-downs, etc.
  • Runtime visual debugging suite.
  • Easily integrated and extensible with Lua or Python scripting.

Extensible

  • Abstracted interfaces for plugging in to any game engine.
  • Decorator engine allowing custom application-specific effects that can be applied to any element.
  • Generic event system that binds seamlessly into existing projects.

RmlUi features

RmlUi introduces several features over the original libRocket branch. While the official RmlUi documentation is being updated with new documentation, some of the new features are also briefly documented here. Pull requests are welcome for improving the documentation at the RmlUi documentation repository.

Breaking changes

If upgrading from the original libRocket branch, some breaking changes should be considered:

  • Rocket::Core::String has been replaced by std::string, thus, interfacing with the library now requires you to change your string types. This change was motivated by a small performance gain, additionally, it should make it easier to interface with the library especially for users already using std::string in their codebase. Similarly, Rocket::Core::WString is now an alias for std::wstring.
  • Querying the property of an element for size, position and similar may not work as expected right after changes to the document or style. This change is made for performance reasons, see the note below for reasoning and a workaround.
  • The Controls::DataGrid "min-rows" property has been replaced by an attribute of the same name.
  • Removed RenderInterface::GetPixelsPerInch, instead the pixels per inch value has been fixed to 96 PPI, as per CSS specs. To achieve a scalable user interface, instead use the 'dp' unit.
  • Removed 'top' and 'bottom' from z-index property.

Events

There are some changes to events in RmlUi, however, for most users, existing code should still work as before.

There is now a distinction between actions executed in event listeners, and default actions for events:

  • Event listeners are attached to an element as before. Events follow the normal phases: capture (root -> target), target, and bubble (target -> root). Each event listener can be either attached to the bubble phase (default) or capture phase. The target phase always executes if reached. Listeners are executed in the order they are added to the element. Each event type specifies whether it executes the bubble phase or not, see below for details.
  • Default actions are primarily for actions performed internally in the library. They are executed in the function virtual void Element::ProcessDefaultAction(Event& event). However, any object that derives from Element can override the default behavior and add new behavior. The default actions follow the normal event phases, but are only executed in the phase according to their default_action_phase which is defined for each event type. If an event is cancelled with Event::StopPropagation(), then the default action is not performed unless already executed.

Each event type now has an associated EventId as well as a specification defined as follows:

  • interruptible: Whether the event can be cancelled by calling Event::StopPropagation().
  • bubbles: Whether the event executes the bubble phase. If true, all three phases: capture, target, and bubble, are executed. If false, only capture and target phases are executed.
  • default_action_phase: One of: None, Target, Bubble, TargetAndBubble. Specifies during which phases the default action is executed, if any. That is, the phase for which Element::ProcessDefaultAction is called. See above for details.

For example, the event type click has the following specification:

id: EventId::Click
type: "click"
interruptible: true
bubbles: true
default_action_phase: TargetAndBubble

Whenever an event listener is added or event is dispatched, and the provided event type does not already have a specification, the default specification interruptible: true, bubbles: true, default_action_phase: None is added for that event type. To provide a custom specification for a new event, first call the method:

EventId Rocket::Core::RegisterEventType(const String& type, bool interruptible, bool bubbles, DefaultActionPhase default_action_phase)

After this call, any usage of this type will use the provided specification by default. The returned EventId can be used to dispatch events instead of the type string.

Various changes:

  • All event listeners on the current element will always be called after calling StopPropagation(). However, the default action on the current element will be prevented. When propagating to the next element, the event is stopped. This behavior is consistent with the standard DOM events model.
  • Element::DispatchEvent can now optionally take an EventId instead of a String.
  • The resize event now only applies to the document size, not individual elements.
  • The scrollchange event has been replaced by a function call. To capture scroll changes, instead use the scroll event.

Other changes

  • Context::ProcessMouseWheel now takes a float value for the wheel_delta property, thereby enabling continuous/smooth scrolling for input devices with such support. The default scroll length for unity value of wheel_delta is now three times the default line-height multiplied by the current dp-ratio.
  • The system interface now has two new functions for setting and getting text to and from the clipboard: virtual void SystemInterface::SetClipboardText(const Core::WString& text) and virtual void SystemInterface::GetClipboardText(Core::WString& text).

Performance

Users moving to this fork should generally see a substantial performance increase.

  • The update loop has been reworked to avoid doing unnecessary, repeated calculations whenever the document or style is changed. Instead of immediately updating properties on any affected elements, most of this work is done during the Context::Update call in a more carefully chosen order. Note that for this reason, when querying the Rocket API for properties such as size or position, this information may not be up-to-date with changes since the last Context::Update, such as newly added elements or classes. If this information is needed immediately, a call to ElementDocument::UpdateDocument can be made before such queries at a performance penalty.
  • Several containers have been replaced, such as std::map to robin_hood::unordered_flat_map.
  • Reduced number of allocations and unnecessary recursive calls.
  • And many more, smaller optimizations, resulting in more than 5x performance increase for creation and destruction of a large number of elements. A benchmark for this is located in the animation sample for now.

Transform property

Based on the work of @shoemark, with additional fixes.

Use perspective, perspective-origin, transform and transform-origin in RCSS, roughly equivalent to their respective CSS properties.

perspective: 1000px;
perspective-origin: 20px 50%;
transform: rotateX(10) skew(-10, 15) translateZ(100px);
transform-origin: left top 0;

All transform properties and their argument types are as follows:

perspective,  length1
matrix,       abs_numbers6
matrix3d,     abs_numbers16
translateX,   length1
translateY,   length1
translateZ,   length1
translate,    length2
translate3d,  length3
scaleX,       number1
scaleY,       number1
scaleZ,       number1
scale,        number2
scale,        number1
scale3d,      number3
rotateX,      angle1
rotateY,      angle1
rotateZ,      angle1
rotate,       angle1
rotate3d,     length3angle1
skewX,        angle1
skewY,        angle1
skew,         angle2

Angles are in degrees by default.

Animations

Most RCSS properties can be animated, this includes properties representing lengths, colors, or transforms. From C++, an animation can be started on an Element by calling

bool Element::Animate(const String& property_name, const Property& target_value, float duration, Tween tween = Tween{}, int num_iterations = 1, bool alternate_direction = true, float delay = 0.0f, const Property* start_value = nullptr);

Additional animation keys can be added, extending the duration of the animation, by calling

bool Element::AddAnimationKey(const String& property_name, const Property& target_value, float duration, Tween tween = Tween{});

C++ example usage:

auto p1 = Transform::MakeProperty({ Transforms::Rotate2D{10.f}, Transforms::TranslateX{100.f} });
auto p2 = Transform::MakeProperty({ Transforms::Scale2D{3.f} });
el->Animate("transform", p1, 1.8f, Tween{ Tween::Elastic, Tween::InOut }, -1, true);
el->AddAnimationKey("transform", p2, 1.3f, Tween{ Tween::Elastic, Tween::InOut });

Animations can also be specified entirely in RCSS, with keyframes.

animation: <duration> <delay> <tweening-function> <num_iterations|infinite> <alternate> <paused> <keyframes-name>;

All values, except <duration> and <kyframes-name>, are optional. Delay must be specified after duration, otherwise values can be given in any order. Keyframes are specified as in CSS, see example below. Multiple animations can be specified on the same element by using a comma-separated list.

Tweening functions (or in CSS lingo, animation-timing-functions) specify how the animated value progresses during the animation cycle. A tweening function in RCSS is specified as <name>-in, <name>-out, or <name>-in-out, with one of the following names,

back
bounce
circular
cubic
elastic
exponential
linear
quadratic
quartic
quintic
sine

RCSS example usage:

@keyframes my-progress-bar
{
	0%, 30% {
		background-color: #d99;
	}
	50% {
		background-color: #9d9;
	}
	to { 
		background-color: #f9f;
		width: 100%;
	}
}
#my_element
{
	width: 25px;
	animation: 2s cubic-in-out infinite alternate my-progress-bar;
}

Internally, animations apply their properties on the local style of the element. Thus, mixing RML style attributes and animations should be avoided on the same element.

Animations currently support full interpolation of transforms, largely following the CSS specifications. Additionally, interpolation support for colors, numbers, lengths, and percentages are implemented.

Animations currently support full interpolation of transforms, largely following the CSS specifications. Additionally, interpolation is supported for colors, numbers, lengths, and percentages.

Animations are very powerful coupled with transforms. See the animation sample project for more examples and details. There are also some video demonstrations of these features in the documentation.

Transitions

Transitions apply an animation between two property values on an element when its property changes. Transitions are implemented in RCSS similar to how they operate in CSS. However, in RCSS, they only apply when a class or pseudo-class is added to or removed from an element.

transition: <space-separated-list-of-properties|all|none> <duration> <delay> <tweening-function>;

The property list specifies the properties to be animated. Delay and tweening-function are optional. Delay must be specified after duration, otherwise values can be given in any order. Multiple transitions can be specified on the same element by using a comma-separated list. The tweening function is specified as in the animation RCSS property.

Example usage:

#transition_test {
	transition: padding-left background-color transform 1.6s elastic-out;
	transform: scale(1.0);
	background-color: #c66;
}
#transition_test:hover {
	padding-left: 60px;
	transform: scale(1.5);
	background-color: #ddb700;
} 

See the animation sample project for more examples and details.

Density-independent pixel (dp)

The dp unit behaves like px except that its size can be set globally to scale relative to pixels. This makes it easy to achieve a scalable user interface. Set the ratio globally on the context by calling:

float dp_ratio = 1.5f;
context->SetDensityIndependentPixelRatio(dp_ratio);

Usage example in RCSS:

div#header 
{
	width: 800dp;
	height: 50dp;
	font-size: 20dp;
}

Pointer events

Set the element property to disregard mouse input events on this and descending elements.

pointer-events: none;

Default is auto.

Image-color property

Non-standard RCSS property which multiplies a color with images in <img> tags and image decorators. Useful for :hover-events and for applying transparency.

image-color: rgba(255, 160, 160, 200);
icon-decorator: image;
icon-image: background.png 34px 0px 66px 28px;

Inline-block

Unlike the original branch, elements with

display: inline-block;

will shrink to the width of their content, like in CSS.

Border shorthand

Enables the border property shorthand.

border: 4px #e99;

Various changes

The slider on the input.range element can be dragged from anywhere in the element. Additionally, the :checked pseudo class can be used to style the selected item in drop-down lists.

License (MIT)

Copyright (c) 2019 The RmlUi Team, and contributors\ Copyright (c) 2008-2014 CodePoint Ltd, Shift Technology Ltd, and contributors

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.