Git Product home page Git Product logo

rmlui's Introduction

RmlUi - The HTML/CSS User Interface Library Evolved

RmlUi logo

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


Chat on Gitter Build 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 aims at being a light-weight and performant library with its own layouting engine and few dependencies. In essence, RmlUi takes your HTML/CSS-like source files and turns them into vertices, indices and draw commands, and then you bring your own renderer to draw them. And of course there is full access to the element hierarchy/DOM, event handling, and all the interactivity and customizability you would expect. All of this directly from C++, or optionally from scripting languages using plugins. The core library compiles down to fractions of the size it takes to integrate a fully fledged web browser.

RmlUi is based around the XHTML1 and CSS2 standards while borrowing features from HTML5 and CSS3, and extends them with features suited towards real-time applications. Take a look at the conformance and enhancements sections below for details.

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


RmlUi 6.0 status: We are moving towards the release of RmlUi 6.0. Projects coming from 5.x releases should expect some breaking changes as listed in the changelog. The project is currently in a stabilization phase before release, thus no further major breaking changes are planned.

Our CMake scripts have been completely rewritten using modern CMake practices, with names for options, targets, and executable files being changed. For details, please see the CMake changes in the changelog, and all CMake options in the documentation.


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.

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.
  • Easily integrated and extensible with the Lua scripting plugin.

Controllable

  • The user controls their own update loop, calling into RmlUi as desired.
  • The library strictly runs as a result of calls to its API, never in the background.
  • Input handling and rendering is performed by the user.
  • The library generates vertices, indices, and textures for the user to render how they like.
  • File handling and the font engine can optionally be fully replaced by the user.

Conformance

RmlUi aims to support the most common and familiar features from HTML and CSS, while keeping the library light and performant. We do not aim to be fully compliant with CSS or HTML, in particular when it conflicts with lightness and performance. Users are generally expected to author documents specifically for RmlUi, but any experience and skills from web design should be transferable.

RmlUi supports most of CSS2 with some CSS3 features such as

  • Animations and transitions
  • Transforms (with full interpolation support)
  • Flexbox layout
  • Media queries
  • Border radius

and many of the common HTML elements including <input>, <textarea>, and <select>.

For details, see

Enhancements

RmlUi adds features and enhancements over CSS and HTML where it makes sense, most notably the following.

Dependencies

In addition, a C++14 compatible compiler is required.

Building RmlUi

RmlUi is built using CMake and your favorite compiler, see the building documentation for all the details and options. Windows binaries are also available for the latest release. Most conveniently, it is possible to fetch the library using a dependency manager such as vcpkg or Conan.

vcpkg

vcpkg install rmlui

That's it! See below for details on integrating RmlUi.

To build RmlUi with the included samples we can use git and CMake together with vcpkg to handle dependencies.

vcpkg install freetype glfw
git clone https://github.com/mikke89/RmlUi.git
cd RmlUi
cmake -B Build -S . --preset samples -DRMLUI_BACKEND=GLFW_GL3 -DCMAKE_TOOLCHAIN_FILE="<path-to-vcpkg>/scripts/buildsystems/vcpkg.cmake"
cmake --build Build

Make sure to replace the path to vcpkg. This example uses the GLFW_GL3 backend, other backends are available as shown below. When this completes, feel free to test the freshly built samples, such as the invaders sample (rmlui_sample_invaders target), and enjoy! The executables should be located somewhere in the Build directory.

Conan

RmlUi is readily available from ConanCenter.

Integrating RmlUi

Here are the general steps to integrate the library into a C++ application, have a look at the integration documentation for details.

  1. Build RmlUi as above or fetch the binaries, and link it up to your application.
  2. Implement the abstract render interface, or fetch one of the backends listed below.
  3. Initialize RmlUi with the interfaces, create a context, provide font files, and load a document.
  4. Call into the context's update and render methods in a loop, and submit input events.
  5. Compile and run!

Several samples demonstrate everything from basic integration to more complex use of the library, feel free to have a look for inspiration.

RmlUi Backends

To ease the integration of RmlUi, the library includes many backends adding support for common renderers and platforms. The following terms are used here:

  • Renderer: Implements the render interface for a given rendering API, and provides initialization code when necessary.
  • Platform: Implements the system interface for a given platform (operating system or window library), and adds procedures for providing input to RmlUi contexts.
  • Backend: Combines a renderer and a platform for a complete windowing framework sample, implementing the basic Backend interface.

The provided renderers and platforms are intended to be usable as-is by client projects without modifications, thereby circumventing the need to write custom interfaces. We encourage users to only make changes here when they are useful to all users, and then contribute back to the project. However, if they do not meet your needs it is also possible to copy them into your project for modifications. Feedback is welcome to find the proper abstraction level. The provided system and render interfaces are designed such that they can be derived from and further customized by the backend or end user.

The provided backends on the other hand are not intended to be used directly by client projects, but rather copied and modified as needed. They are intentionally light-weight and implement just enough functionality to make the included samples run, while being simple to understand and build upon by users. See the manual for backend integration details.

Renderers

Renderer features Basic rendering Transforms Clip masks Filters Shaders Built-in image support
OpenGL 2 (GL2) ✔️ ✔️ ✔️ Uncompressed TGA
OpenGL 3 (GL3) ✔️ ✔️ ✔️ ✔️ ✔️ Uncompressed TGA
Vulkan (VK) ✔️ ✔️ Uncompressed TGA
SDLrenderer ✔️ Based on SDL_image

Basic rendering: Render geometry with colors, textures, and rectangular clipping (scissoring). Sufficient for basic 2d-layouts.
Transforms: Enables the transform and perspective properties to take effect.
Clip masks: Enables proper clipping of transformed elements and elements with border-radius.
Filters: Support for all built-in filter functions, such as blur and drop-shadow.
Shaders: Support for all built-in decorators that require shaders, such as linear-gradient and radial-gradient. Other advanced rendering functions are also implemented, including masking and render-to-texture support, for features such as mask-image and box-shadow.
Built-in image support: This only shows the supported formats built-in to the renderer, users are encouraged to derive from and extend the render interface to add support for their desired image formats.

Platforms

Platform support Basic windowing Clipboard High DPI Comments
Win32 ✔️ ✔️ ✔️ High DPI only supported on Windows 10 and newer.
X11 ✔️ ✔️
SFML ✔️ ⚠️ Some issues with Unicode characters in clipboard.
GLFW ✔️ ✔️ ✔️
SDL ✔️ ✔️

Basic windowing: Open windows, react to resize events, submit inputs to the RmlUi context.
Clipboard: Read from and write to the system clipboard.
High DPI: Scale the dp-ratio of RmlUi contexts based on the monitor's DPI settings. React to DPI-changes, either because of changed settings or when moving the window to another monitor.

Backends

Platform \ Renderer OpengGL 2 OpengGL 3 Vulkan SDLrenderer
Win32 ✔️ ✔️
X11 ✔️
SFML ✔️
GLFW ✔️ ✔️ ✔️
SDL¹ ✔️ ✔️² ✔️ ✔️

¹ SDL backends extend their respective renderers to provide image support based on SDL_image.
² Supports Emscripten compilation target.

When building the samples, the backend can be selected by setting the CMake option RMLUI_BACKEND to <Platform>_<RendererShorthand> for any of the above supported combinations of platforms and renderers, such as SDL_GL3.

Example document

This example demonstrates a basic document with data bindings, which is loaded and displayed using the C++ code below.

Document

hello_world.rml

<rml>
<head>
	<title>Hello world</title>
	<link type="text/rcss" href="rml.rcss"/>
	<link type="text/rcss" href="window.rcss"/>
</head>
<body data-model="animals">
	<h1>RmlUi</h1>
	<p>Hello <span id="world">world</span>!</p>
	<p data-if="show_text">The quick brown fox jumps over the lazy {{animal}}.</p>
	<input type="text" data-value="animal"/>
</body>
</rml>

The {{animal}} text and the data-if, data-value attributes represent data bindings and will synchronize with the application data.

Style sheet

window.rcss

body {
	font-family: LatoLatin;
	font-size: 18px;
	color: #02475e;
	background: #fefecc;
	text-align: center;
	padding: 2em 1em;
	position: absolute;
	border: 2px #ccc;
	width: 500px;
	height: 200px;
	margin: auto;
}
		
h1 {
	color: #f6470a;
	font-size: 1.5em;
	font-weight: bold;
	margin-bottom: 0.7em;
}
		
p { 
	margin: 0.7em 0;
}
		
input.text {
	background-color: #fff;
	color: #555;
	border: 2px #999;
	padding: 5px;
	tab-index: auto;
	cursor: text;
	box-sizing: border-box;
	width: 200px;
	font-size: 0.9em;
}

RmlUi defines no styles internally, thus the input element is styled here, and rml.rcss is included for proper layout of common tags.

C++ Initialization and loop

main.cpp

#include <RmlUi/Core.h>

class MyRenderInterface : public Rml::RenderInterface
{
	// RmlUi sends vertices, indices and draw commands through this interface for your
	// application to render how you'd like.
	/* ... */
}

class MySystemInterface : public Rml::SystemInterface
{	
	// RmlUi requests the current time and provides various utilities through this interface.
	/* ... */
}

struct ApplicationData {
	bool show_text = true;
	Rml::String animal = "dog";
} my_data;

int main(int argc, char** argv)
{
	// Initialize the window and graphics API being used, along with your game or application.

	/* ... */

	MyRenderInterface render_interface;
	MySystemInterface system_interface;

	// Install the custom interfaces.
	Rml::SetRenderInterface(&render_interface);
	Rml::SetSystemInterface(&system_interface);

	// Now we can initialize RmlUi.
	Rml::Initialise();

	// Create a context to display documents within.
	Rml::Context* context = Rml::CreateContext("main", Rml::Vector2i(window_width, window_height));

	// Tell RmlUi to load the given fonts.
	Rml::LoadFontFace("LatoLatin-Regular.ttf");
	// Fonts can be registered as fallback fonts, as in this case to display emojis.
	Rml::LoadFontFace("NotoEmoji-Regular.ttf", true);

	// Set up data bindings to synchronize application data.
	if (Rml::DataModelConstructor constructor = context->CreateDataModel("animals"))
	{
		constructor.Bind("show_text", &my_data.show_text);
		constructor.Bind("animal", &my_data.animal);
	}

	// Now we are ready to load our document.
	Rml::ElementDocument* document = context->LoadDocument("hello_world.rml");
	document->Show();

	// Replace and style some text in the loaded document.
	Rml::Element* element = document->GetElementById("world");
	element->SetInnerRML(reinterpret_cast<const char*>(u8"🌍"));
	element->SetProperty("font-size", "1.5em");

	bool exit_application = false;
	while (!exit_application)
	{
		// We assume here that we have some way of updating and retrieving inputs internally.
		if (my_input->KeyPressed(KEY_ESC))
			exit_application = true;

		// Submit input events such as MouseMove and key events (not shown) to the context.
		if (my_input->MouseMoved())
			context->ProcessMouseMove(mouse_pos.x, mouse_pos.y, 0);

		// Update the context to reflect any changes resulting from input events, animations,
		// modified and added elements, or changed data in data bindings.
		context->Update();

		// Render the user interface. All geometry and other rendering commands are now
		// submitted through the render interface.
		context->Render();
	}

	Rml::Shutdown();

	return 0;
}

Rendered output

Hello world document

Users can now edit the text field to change the animal. The data bindings ensure that both the document text as well as the application string my_data.animal are automatically modified accordingly.

Gallery

Game interface from the 'invader' sample
Game interface

Game menu
Game menu

Simple game from the 'databinding' sample
Databinding sample

alt:V installer - a multiplayer client for GTA:V
alt:V installer collage

Unvanquished - a first-person shooter game with real-time strategy elements - menus and HUD in RmlUi
Unvanquished 0.54 collage

Installer software by @xland
xland installer collage

TruckersMP - a multiplayer mod for truck simulators - chat box in RmlUi
TruckersMP

Form controls from the 'demo' sample
Form controls

Sandbox from the 'demo' sample, try it yourself!
Sandbox

Visual testing framework - for built-in automated layout tests
Visual testing framework

Flexbox layout
Flexbox

Animations and transitions from the 'animation' sample

animation_sample.webm


Transitions and transforms on a game menu

game_main_menu.webm


Camera movement in a game menu

game_menu_transform.webm


Transitions on mouse hover (entirely in RCSS)
Transition

Animated transforms (entirely in RCSS)
Transform

Vector animations with the Lottie plugin
Lottie animation

Vector images with the SVG plugin
SVG image

See the full gallery for more screenshots and videos of the library in action.

License

RmlUi is published under the MIT license. The library includes third-party source code and assets with their own licenses, as detailed below.

RmlUi source code and assets

MIT License

Copyright (c) 2008-2014 CodePoint Ltd, Shift Technology Ltd, and contributors
Copyright (c) 2019-2023 The RmlUi Team, 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.

Third-party source code included in RmlUi Core

See Include/RmlUi/Core/Containers/LICENSE.txt - all MIT licensed.

Third-party font assets included in RmlUi Debugger

See Source/Debugger/LICENSE.txt - SIL Open Font License.

Additional sample assets (in Samples/)

See

Library included with the Vulkan backend (in Backends/RmlUi_Vulkan/)

See Backends/RmlUi_Vulkan/LICENSE.txt - MIT licensed.

Libraries included with the test suite (in Tests/Dependencies/)

See Tests/Dependencies/LICENSE.txt.

Additional test suite assets (in Tests/Data/VisualTests/)

See Tests/Data/VisualTests/LICENSE.txt.

rmlui's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

rmlui's Issues

Document doesn't receive the "Load" event

This one is weird but it seems that on the develop branch, the document element never receives the "load" event. I can see the call to DispatchEvent alright but it just doesn't work for me for some reason. Things like "focus" and "blur" do make it to ProcessDefaultAction though.

warning C4717

I'm getting this warning in Visual Studio 2017

'Rml::Core::Variant::Variant<std::tuple<Rml::Core::Variant &&> >': recursive on all control paths, function will cause runtime stack overflow Variant.inl line 38

I temporarily fixed it with this code:

Variant::Variant(const std::tuple<T>& values)
{
	Set(std::get<0>(values));
}

Hiding an element should remove it from the focus tree

This is somewhat a continuation of issue #40. Consider the following scenario:

  1. A document is shown and it has a bunch of elements with the "autofocus" attribute.
  2. The first element is focused as it should.
  3. The OnShow script then decides it doesn't want that first element to be displayed and hides by setting "display" to "none".
  4. Pressing ENTER will result in a click event on the hidden element.

Element::GetProperty<T> isn't safe

T Element::GetProperty(const String& name)
{
	const Property* property = GetProperty(name);
	RMLUI_ASSERTMSG(property, "Invalid property name.");
	return property->Get< T >();
}

The code should also check for property not being nullptr after the assert because RMLUI_ASSERTMSG expands to nothing in release builds, and if property is a nullptr indeed, the program will crash with segmentation fault.

Long compilation times

A whole game engine can be compiled in the time it takes to compile RmlUI alone :P

It would be nice if the compilation time of RmlUI could be reduced. The precompiled header helps but not that much because of the heavy use of templates.

I recall profiling it using MSVC's /d2cgsummary flag (see https://aras-p.info/blog/2017/10/23/Best-unknown-MSVC-flag-d2cgsummary/ ), but I can't remember any details anymore. My best guess would be that most of the time comes from the monstrous Core.h include file but we need that to be re-verified.

Rml::Core::ReleaseCompiledGeometries() is not found

In the Android environment, OpenGL resources are automatically destroyed when the application is put on standby. I want to rebuild the resources. What should I do?

// Rml::Core::ReleaseCompiledGeometries(); not found
Rml::Core::ReleaseTextures();

Rename project, libMissile?

As suggested by @barroto in #2, this fork of libRocket is now quite distinct from the original project. A rename of this work then seems natural.

Some things that me may consider with this change:

  • Update the original documentation with the new changes
  • Rename the namespace from Rocket to.. Missile?
  • A new logo?
  • Updated templates?

What do you think? These are just ideas I'm throwing out there, any ideas you may have are very welcome.

I'm not sure how the original documentation was built, but you seem able to assist here, @barroto?

Renaming performance branch to develop

This change should make it more clear that we will be merging this into master once everything is ready. Develop branch will become RmlUi v3.0.

Also, just letting you know I'm leaving for vacation next week, so there will be less activity from me for the following three weeks.
Happy coding :)

Deprecating things

I think this is a good time to deprecate things that seem really out-of-date. For example, the docs mention Python 2.5 (!) support only. Generally I think Lua is the better way for our audience, being a lot easier to integrate. My impression is that Lua is much more wide-spread in the game-dev community at least.

A list of things which I suggests we remove completely:

  • Python support
  • SFML 1 (but keep SFML 2)
  • DirectX 9
  • Ogre3d? (It seems the supported version is really out of date, dating back almost a decade)
  • Removing the datagrid. This is already broken as of now, and to me it never did work so well. I think implementing table support instead would be a better approach perhaps?

font-charset

The font interface libRocket as a whole relies on "font-charset". If this applies to RmlUi is there a possibility of removing font-charset workaround in order to simply generate glyphs as needed or at least let me use my own better font renderer.

I mostly say this as I want to use emoji and russian and many other languages (depending on user choice).

https://mikke89.github.io/RmlUiDoc/pages/localisation.html

Touch events support

Basically, what I'm suggesting for now is porting over the touch events glue code from qfusion. For that, RmlUi would need to introduce one new API call that translate touch events into mouse events:

  • Context::ProcessTouchEvent(ev_type, x, y)
    -- touch event type (up, down, motion)
    -- x coordinate
    -- y coordinate
  • 3 enums for touch event types
  • 1 key modifier to distinguish translated touch events from real mouse events

Here's the boilerplate code for Context::ProcessTouchEvent:

	context->ProcessMouseMove( x, y, KeyConverter::getModifiers() );

	if( type == TOUCH_DOWN ) {
		context->ProcessMouseButtonDown( 0, KeyConverter::getModifiers() );
	} else {
		int delta = contextTouch.y - y;
		if( delta ) {
			if( !contextTouch.scroll ) {
				int threshold = 32 * renderInterface->GetPixelRatio();
				if( abs( delta ) > threshold ) {
					contextTouch.scroll = true;
					contextTouch.y += ( ( delta < 0 ) ? threshold : -threshold );
					delta = contextTouch.y - y;
				}
			}

			if( contextTouch.scroll ) {
				Element *focusElement = context->GetFocusElement();
				if( !focusElement || ( focusElement->GetTagName() != "keyselect" ) ) {
					Element *element;
					for( element = context->GetElementAtPoint( contextTouch.origin ); element; element = element->GetParentNode() ) {
						if( element->GetTagName() == "scrollbarvertical" ) {
							break;
						}

						int overflow = element->GetProperty< int >( "overflow-y" );
						if( ( overflow != Rml::Core::OVERFLOW_AUTO ) && ( overflow != Rml::Core::OVERFLOW_SCROLL ) ) {
							continue;
						}

						int scrollTop = element->GetScrollTop();
						if( ( ( delta < 0 ) && ( scrollTop > 0 ) ) ||
							( ( delta > 0 ) && ( element->GetScrollHeight() > scrollTop + element->GetClientHeight() ) ) ) {
							element->SetScrollTop( element->GetScrollTop() + delta );
							break;
						}
					}
				}
				contextTouch.y = y;
			}
		}

		if( type == TOUCH_UP ) {
			context->ProcessMouseButtonUp( 0, KeyConverter::getModifiers() );
		}
	}

Proposal for replacing decorator syntax, add sprite sheet support

While the work on increasing performance is well underway with great results already, there are some ideas that could improve it further but break some existing things, and possibly reduce some of the generality of the library.

Specifically, strings are passed and copied everywhere around in the code and need to be looked up in hash tables quite a lot. Especially for properties, events, and possibly pseudoclasses. What I propose instead is to use simple numeric IDs, one specific for each property. Everything would become much simpler then if we disallow custom property names (such as those used by decorators) and events.

But of course, we're not getting rid of decorators! Instead, I think we can improve them.

I think it is kind of awkward currently to have to specify the exact subrectangle in a texture right inside the decorator declaration. Instead, I propose first that we enable somehow to define a spritesheet with all subrectangles defining a given sprite in one place. Then we introduce a new property, either decorator or background-image (as in css) which specifies a decorator by combining possibly multiple sprite names from the spritesheet, and comma-separated for multiple decorators.

E.g. something like this:

@spritesheet(invader-theme) {
   src: invader-theme.png;
   invader-left: 10px 40px 30px 10px;
   ...
}
button.invader {
 decorator: tiled-horizontal(invader-left, invader-center, invader-right), image(button-bg);
}

One of the nice things is that we could then easily replace the whole spritesheet (1) to change to a different theme, or more importantly, (2) to specify a higher resolution image when the dp unit changes so that the textures are crisp at say 1dp==2px.

Thoughts?

Moving towards a 3.0 release of RmlUi

I feel like we have a considerable amount of features in the develop branch now, and it's time we merge it with master soon for an official 3.0 release.

The obvious major thing missing is documentation of all the new features, and we probably need to go through all the existing documentation as a lot of details have been changed. The changelog is quite exstensive, and should serve as a good starting point.

If there is something you feel should be done before the release of RmlUi 3.0, then let's discuss it here. Also if you find or know of any larger bugs or stability issues, it would be nice to have these resolved before the release.

Gallery

Every UI library needs a gallery!

I started adding some screenshots in the documentation:
https://mikke89.github.io/RmlUiDoc/pages/gallery.html
And the idea is to put all or some of these in the Readme here.

Ideally, we want something that showcases various parts of the library, and looks nice at the same time. Although, I'm not sure if all of those examples look too good?

Perhaps you're using RmlUi in a project yourself, and you'd be willing to share screenshots? Then please add them here with a reply :)
It would also be nice to have some links to projects using RmlUi, so if you'd like you can leave a link with your screenshots and I'll add them to the gallery.

Pseudo-classes not working

I'm having issues with pseudo classes in the invaders demo. Look at the main menu:
with libRocket:
rocket-invaders
with RmlUi:
rmlui-invaders

It seems like the :hover pseudo-class is not selected as specified in the assets/invaders.rcss file.

Same thing for :active and :checked for other input elements:
libRocket:
rocket-invaders

RmlUi:
rmlui-invaders

Remove namespace Core, Debugger, Controls

Usage of RmlUi would be a lot simpler if we removed the sub-namespaces. I don't feel like they are really necessary.

Thus,

Rml::Core::Element* element;
Rml::Controls::ElementFormControl* control_element;
Rml::Core::Log::Message(Rml::Core::Log::LT_WARNING, "...");

would become

Rml::Element* element;
Rml::ElementFormControl* control_element;
Rml::Log::Message(Rml::Log::LT_WARNING, "...");

We may need to keep the namespaces for some functions, so this stays the same:

Rml::Core::Initialise();
Rml::Controls::Initialise();

or, maybe remove it for core?

Rml::Initialise();
Rml::Controls::Initialise();

I haven't tried it to see if there are any name conflicts, but worst case is we need to do some renaming.

Thoughts?

Getting rid of the Stream class, simplify URL and FileInterface

I just don't really see the benefits of the Stream class. We are not loading files so big that they need to be streamed in parts. And we don't really need support for Write() and several other functions that are implemented.

The parsing in particular could be simplified a lot (and probably made faster) by just using a String or StringView in the necessary places.

Anybody have objections to this?

Similarly, the URL class is very big and overly generalized. Do we really need parameters, login/password fields? Perhaps it can all be replaced by a simple URL string, and a way to combine two URLs to resolve relative paths. This is lower priority though, as it doesn't really complicate the rest of the codebase. It's really big though, over 400 bytes here.

Finally, the FileInterface is really only used internally to read in whole files at a time. Thus, why not replace it with a single method to do exactly this?

Remove all manual reference counting

And replace them with unique_ptr, or shared_ptr where strictly necessary. E.g. elements should uniquely own their children. Replace AddChild with CreateChild so users don't have to move them on every element creation.

All use of raw pointers should then denote a non-owning pointer.

Scaling modes of image decorator

Implement scaling modes for the image decorator, e.g. such as:
image

Also, consider adding a 'fixed-size' center mode for tiled-horizontal, tiled-vertical, and tiled-box decorators.

See discussion in: #22 (comment)

Gradients, mask images, WYSIWYG editor

Hello mate!
I've also added animations and transform features to libRocket long time ago, I've also added duktape for javascript bindings, however your work looks more complete.

I've dropped libRocket only because of a few features that were missing:

  • Gradients
  • Opacity Image-Masks
    And specially the possibility to use these two toghether for very cool effects such as
    -webkit-mask-image: radial-gradient(ellipse 60% 45% at 60% 60%, transparent 20%, black 100%);

Are you planning to implement these features in the near future?
Also, is there any WYSIWYG editor for libRocket?

Thanks in advance.

RFC: new font provider interface

The major difference between stock libRocket and our own fork here https://github.com/Qfusion/libRocket is that the former manages its own library of fonts and glyphs and is closely tied to freetype. Quite often this is an undesired behaviour: bitmap fonts, fonts are managed by the application, etc.

Related PR:
https://github.com/libRocket/libRocket/pull/267/files

Related commit in our fork:
Qfusion/libRocket@c0d15d8

The downside of our implementation isn't able to handle font effects as it doesn't export rendered glyphs to libRocket.

Assertion failure in EventDispatcher::TriggerEvents

The following line produces an assertion failure in debug build in MSVC:

	for (auto it = begin; it != end; ++it)

Further down the stack:

	_Vector_const_iterator& operator++()
		{	// preincrement
 #if _ITERATOR_DEBUG_LEVEL != 0
		const auto _Mycont = static_cast<const _Myvec *>(this->_Getcont());
		_STL_VERIFY(_Ptr, "can't increment value-initialized vector iterator");
		_STL_VERIFY(_Ptr < _Mycont->_Mylast, "can't increment vector iterator past end");
 #endif /* _ITERATOR_DEBUG_LEVEL != 0 */

The _Mycont pointer is null

Increasing performance: Call for comments

I've given quite some effort lately into improving the performance of the library, and especially for creation and destruction of elements which can sometimes be slow.

There are some breaking changes, so I'm taking some extra time before merging into master:

  • Mainly, Rocket::Core::String has been replaced by std::string. This gave a small performance boost, but perhaps more importantly, I think it eases the interaction between most users and the library.
  • The update loop has been quite substantially re-engineered. A lot of duplicate work is avoided, instead things update in a more strictly ordered manner. This may cause an issue for some user code such as code that relies on querying elements for position and size, straight after element construction or other documents changes. Some properties are not up-to-date until Context::Update is called. However, there is a workaround as described in the documentation.

To give some numbers, I'm getting a 3.5x (!) speedup during heavy construction / destruction of elements, compared to before I started the performance branch. From 18.5 to 65.0 FPS for more than 500 elements per update loop. These numbers do not even include earlier performance improvements. And I'm not done yet ;)

I think I'm mostly reaching out to discuss the performance of librocket in general, as well as what you think about these breaking changes. Any thoughts?

Add Appveyor integration

I have troubles compiling the master branch in appveyor due to the following error:

C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.16.27023\include\vector(1889): error C2036: 'Rocket::Core::Transforms::Primitive *': unknown size [C:\projects\librocket\Build\RocketCore.vcxproj]
  C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.16.27023\include\vector(1872): note: while compiling class template member function 'bool std::vector<Rocket::Core::Transforms::Primitive,std::allocator<_Ty>>::_Buy(const unsigned int)'
          with
          [
              _Ty=Rocket::Core::Transforms::Primitive
          ]
  C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.16.27023\include\vector(735): note: see reference to function template instantiation 'bool std::vector<Rocket::Core::Transforms::Primitive,std::allocator<_Ty>>::_Buy(const unsigned int)' being compiled
          with
          [
              _Ty=Rocket::Core::Transforms::Primitive
          ]
  c:\projects\librocket\include\rocket\core\Transform.h(83): note: see reference to class template instantiation 'std::vector<Rocket::Core::Transforms::Primitive,std::allocator<_Ty>>' being compiled
          with
          [
              _Ty=Rocket::Core::Transforms::Primitive
          ]

Get rid of RTTI

It'd be awesome of RmlUi didn't insist on being compiled with RTTI enabled. First and foremost, it would reduce the footprint of the library considerably. Second of all, this should reduce compilation time. And on top of that, it would make integrating the library into RTTI-less projects easier.

There are all kinds of RTTI and dynamic_cast replacements found on the Internet, however this particular one caught my attention: http://kahncode.com/2019/09/24/c-tricks-fast-rtti-and-dynamic-cast/

Wrong casting in SDL2 sample

At the moment GetElapsedTime divides SDL_GetTicks by 1000 (integer) as a result it returns a rounded value. It should be fixed in this way:

double RmlUiSDL2SystemInterface::GetElapsedTime()
{
	return SDL_GetTicks() / 1000.0;
}

Gradient decorator

I know it's been suggested before, but here's a more less working implementation, which can be salvaged for RmlUI: https://github.com/Qfusion/qfusion/blob/master/source/ui/decorators/ui_gradient_decorator.cpp

I think it's missing three major things (but none are critical in my opinion):

  • diagonal gradients, trivial to implement
  • multiple colors: doable by subdividing the quad into smaller quads for each color transition
  • radial gradients - non trivial, I'd rather skip this one for now

Comments and suggestions are welcome :)

Configuration error on Linux

Hi, I'm on master and this is the output when running cmake on Linux Ubuntu 19.10 (CMake 3.13):

$ cmake ..
CMake Warning (dev) at /usr/share/cmake-3.13/Modules/FindOpenGL.cmake:270 (message):
  Policy CMP0072 is not set: FindOpenGL prefers GLVND by default when
  available.  Run "cmake --help-policy CMP0072" for policy details.  Use the
  cmake_policy command to set the policy and suppress this warning.

  FindOpenGL found both a legacy GL library:

    OPENGL_gl_LIBRARY: /usr/lib/x86_64-linux-gnu/libGL.so

  and GLVND libraries for OpenGL and GLX:

    OPENGL_opengl_LIBRARY: /usr/lib/x86_64-linux-gnu/libOpenGL.so
    OPENGL_glx_LIBRARY: /usr/lib/x86_64-linux-gnu/libGLX.so

  OpenGL_GL_PREFERENCE has not been set to "GLVND" or "LEGACY", so for
  compatibility with CMake 3.10 and below the legacy GL library will be used.
Call Stack (most recent call first):
  CMakeLists.txt:459 (find_package)
This warning is for project developers.  Use -Wno-dev to suppress it.

Documentation for this is here, under the "Linux-specific" section.

This can be fixed adding to CMakeList.txt either

if (POLICY CMP0072)
	cmake_policy (SET CMP0072 NEW)
endif(POLICY CMP0072)

or

set(OpenGL_GL_PREFERENCE "GLVND")

just before find_package(OpenGL REQUIRED)

Build fails with Clang5.0 (C ++ 17)

Build error occurs in VisualStdio Android development environment.
The build is RMLUI_STATIC_LIB only
gnustl_static

Code I tentatively addressed

./Include/RmlUi/Core/Types.h
template <class T> struct hash { using utype = typename ::std::underlying_type<T>::type; size_t operator() (const T& t) const { ::std::hash<utype> h; return h(static_cast<utype>(t)); }

to

``
#ifdef ANDROID

template <> struct hash<::Rml::Core::PropertyId> {
using utype = typename ::std::underlying_type<::Rml::Core::PropertyId>::type;
size_t operator() (const ::Rml::Core::PropertyId& t) const { ::std::hash h; return h(static_cast(t)); }
#endif
``

Various compilation issues

Oddly enough but I seem to be unable to compile RmlUi in Travis for my own project and it seems rightfully so:

In file included from /home/travis/build/Qfusion/qfusion/third-party/libRocket/Source/Core/../../Include/RmlUi/Core/Types.h:51:

/home/travis/build/Qfusion/qfusion/third-party/libRocket/Source/Core/../../Include/RmlUi/Core/Containers/robin_hood.h:657:22: error: implicit instantiation of undefined template 'std::hash<Rml::Core::PropertyId>'

struct hash : public std::hash<T> {

                     ^

/home/travis/build/Qfusion/qfusion/third-party/libRocket/Source/Core/../../Include/RmlUi/Core/Containers/robin_hood.h:743:11: note: in instantiation of template class 'robin_hood::hash<Rml::Core::PropertyId>' requested here

        : public Hash,

                 ^

/home/travis/build/Qfusion/qfusion/third-party/libRocket/Source/Core/../../Include/RmlUi/Core/PropertyDictionary.h:87:14: note: in instantiation of template class 'robin_hood::detail::unordered_map<true, 80, Rml::Core::PropertyId, Rml::Core::Property, robin_hood::hash<Rml::Core::PropertyId>, std::equal_to<Rml::Core::PropertyId> >' requested here

        PropertyMap properties;

                    ^

/usr/lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/bits/functional_hash.h:58:12: note: template is declared here

    struct hash;

PropertyId is a enum class and using it as a key for unordered_map requires a specialized hash function but it appears RmlUi is providing one.

ElementFormControlSelect::Add() issue: index returned <= 1

Hi, calling

ElementFormControlSelect::Add(rml, value, -1, true);

return an index 0 or 1.
This should be due to the call to

int WidgetDropDown::AddOption(const Rml::Core::String& rml, const Rml::Core::String& new_value, int before, bool select, bool selectable)
{
	Core::ElementPtr element = Core::Factory::InstanceElement(selection_element, "*", "option", Rml::Core::XMLAttributes());
	element->SetInnerRML(rml);
	bool result = AddOption(std::move(element), new_value, before, select, selectable);
	return result;
}

where result is converted to bool.

Tabsets do not work anymore

The following condition in ElementTabSet::ProcessEvent always fails:

	if (event.GetCurrentElement() == this && event == Core::EventId::Click)

Unable to build samples under Linux

Whilst trying to compile the samples under Linux, this is the error I got:

In file included from /usr/include/X11/Xlib.h:44:0,
                 from /usr/include/GL/glx.h:30,
                 from Samples/shell/include/ShellOpenGL.h:44,
                 from Samples/shell/include/ShellRenderInterfaceOpenGL.h:32,
                 from Samples/shell/src/ShellRenderInterfaceOpenGL.cpp:29:
Include/Rocket/Core/Tween.h:39:14: error: expected identifier before numeric constant
  enum Type { None, Back, Bounce, Circular, Cubic, Elastic, Exponential, Linear, Quadratic, Quartic, Quintic, Sine, Callback, Count };
              ^

Apparently None is already defined as a preprocessor macro in the system header file X.h:

/usr/include/X11/X.h:115:0:
 #define None                 0L /* universal null resource or null atom */

Any idea on the best way to fix this?
I hate defines...

std::variant-less version?

Hi,

thanks for your on animation support for libRocket! Unfortunately due to various operating systems, libs and compilers still catching up with C++17 features, compiling your fork is some real pain. The most problematic bit is std::variant and std::visit, the later is only available in MacOS 10.14 and llvm installed from brew.

Now please forgive my ignorance, but was using std::variant really necessary or maybe there's a way to get rid of it at the expense of a few additional lines of code?

Thanks.

ElementDocument::FocusFirstTabElement

bool FocusFirstTabElement(void) { return FocusNextTabElement(this, true); }

We use this function to focus on the first "tabbable" element when the document is displayed for the first time, if possible. Make sense for modal dialogs, input forms and such.

Please consider adding this function to the public API or maybe, as an alternative, a new Focus flag with similar functionality.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.