-
Notifications
You must be signed in to change notification settings - Fork 113
widget_sample
title: GUI Widget Sample description: Standalone NeL GUI showcase sample (nl_sample_gui) using the legacy w_ interface skin published: true editor: markdown
nl_sample_gui (nel/samples/gui/) is a standalone showcase of the NLGUI widget library. It boots the widget manager, view renderer and interface parser outside the Ryzom client, parses a self-contained interface definition, and renders it with the legacy w_ interface skin — the original beveled reference style whose window frames (w_header_*, w_l0_*, w_l1_*, w_modal_*, w_scroll_l0_*) were later replaced name-for-name by the shipped skin_* set. The sample keeps this otherwise-unused skin exercised and doubles as a minimal reference for embedding NLGUI in any NeL application.
-
main.cpp— bootstrap:UDriver+ text context,CViewRenderer::setDriver/setTextContext+init, atlasloadTextures,parseInterface,updateAllLocalisedElements,activateMasterGroup("ui:sample"), then the pump/draw loop (EventServer.pump→sendClockTickEvent→checkCoords→drawViews). ANLGUI::CEventListenerroutes driver mouse events into the widget manager. -
data/config_sample.xml— master<root id="sample">, database defaults, and thew_skinoptionsblocks (layer0,skin_modal,container_move_opt,container_insertion_opt,context_menu_back, …). -
data/widgets_sample.xml— shared widget styles (text_button_16,button_ok,tab_button) on thew_text_button_*/w_tab_*textures. -
data/main_sample.xml— the showcase windows, thegeneric_pointerview, and the<tree>nodes that register windows.
No interface texture data lives in the code repository. At build time, CMake runs the build_interface tool over interfaces/v3/ of a ryzomcore_graphics checkout (NL_GRAPHICS_DIR, default sibling of the source tree) and packs gui_sample_atlas.png/.txt into the build directory — the same pattern the WebGL water sample uses for its assets. build_interface gained a -k/--keep-going flag for this: input files that cannot be loaded as bitmaps (e.g. unmaterialized git-lfs pointer files) are skipped with a warning instead of aborting the pack. The font comes from fonts/basic.ttf in the same checkout.
The Emscripten build preloads the generated atlas, the XML and the font into the .data bundle; when cross-compiling, point NL_BUILD_INTERFACE_TOOL at a host-built build_interface.
Native (needs WITH_GUI=ON, which needs Lua and ryzom/luabind; build both into a local prefix and pass LUA_*/LUABIND_* cache variables if the distribution does not package them):
cmake -DWITH_GUI=ON -DWITH_NEL_SAMPLES=ON ...
ninja nl_sample_gui
bin/nl_sample_gui # interactive, ESC quits
bin/nl_sample_gui --screenshot out.png --frames 10 # headless witness (works under xvfb-run)
NLGUI ships the widget-level handlers (set, tab_select, ic_* container buttons, combo box, select number, …) but some conventional handlers live in the Ryzom client. The sample registers its own equivalents: proc (run an interface procedure), enter_modal / leave_modal (CWidgetManager::enableModalWindow), and sample_quit.
A launcher window toggles one showcase window per family; the four container layer skins (layer0…layer3, pure w_l0_*…w_l3_* options blocks) are spread across them. Covered and interaction-verified under Xvfb with xdotool: text views (sizes, colors, case modes, multi-line), bitmaps (scaled/tiled), text_number/digit/text_quantity, bar/bar3 gauges, push/toggle/radio buttons, text buttons, sliders on both axes bound to UI:TEMP:* database entries, edit boxes (typed input works), scroll_text (which contains the runtime-filled group_list), group_tree with arbo_* fold arrows, menus (checkable, grayed, separator, nested submenu — a submenu is a nested <action> inside an <action>, not a <menu> element), the combo box with its dropdown, select_number, the color picker (palette + a makeRGB(...) link recoloring a swatch), tab groups, stacked modals (push_modal/pop_modal), a <link> showing a warning icon above a threshold, and the friends/guild-style popin rollout: child containers docked into a parent window via nested <tree> nodes, rolling open/closed with the open-state arrow — nesting depth picks the deeper layer skins automatically, which is where the w_l0 open-strip pieces (tx_*_open, el/em/er) actually draw. Not exercised: group_html/group_table (need the web stack wired), Lua-scripted UI (handler registered, no demo), edit_box_decor, group_frame/header.
Note on container layers: standalone windows can force a deeper skin with options="layer1..3", but the engine normally derives the layer from popin nesting depth.
NLGUI expects several things from the embedding application that the Ryzom client normally supplies:
-
CInterfaceLink::CInterfaceLinkUpdater— instantiate one after creating the widget manager; without it,<link>elements never evaluate (database observer flushes are what pump triggered links). CallCInterfaceLink::updateAllLinks()once after parsing for the initial evaluation. -
CDBGroupComboBox::selectMenu/selectMenuOut/measureMenu— static ids the combo dropdown machinery resolves; point them at your master group's menus. -
Action handlers with client-side conventions:
proc,enter_modal/leave_modal,push_modal/pop_modal,active_menu,lua.
-
Container windows need the global options blocks.
CGroupContainer::setupdereferencescontainer_move_optunchecked — without that options block the firstupdateAllLocalisedElementscrashes. -
Fresh database leaves default to 0.
UI:SAVE:CONTENT_ALPHA,UI:SAVE:CONTAINER_ALPHAand friends must be declared (255) in the XML or every window renders fully transparent. LikewiseUI:SAVE:*_ROLLOVER_FACTORare inverted factors: 255 = no fade-out when the mouse is not over the window, 0 = fade to invisible. -
Root-level plain
<group>s are parsed but never drawn — only windows registered on the master group (containers via<tree>, modals viaenableModalWindow) render. Put HUD-style elements inside a registered window. -
%case_upperetc. are interface defines, not built-ins — declarecase_normal…case_first_word_letter_up(0…5). - The texture lookup normalizes
.png→.tgaon both the atlas-load and lookup sides, so interface XML keeps the canonical.tganames while the atlas is packed from.pngsources. The color picker is the exception: it reads its palette as a loose file (it needs pixel access), so the palette png is staged next to the atlas andCPath::remapExtension("png", "tga", true)is set before the search paths are indexed. - Container windows compute their height from the content group unless
resizer="true"; a fixed-size window withresizer="false"and an empty-sized content collapses to its title bar. -
dbview_quantity's registered class name istext_quantity(notquantity). - Two NLGUI bugs fixed while building this:
CEventListenernever subscribed keyboard events (edit boxes were deaf outside the client), andCGroupTree::SNode::parsecrashed on a<node>withopened=but noshow=(wrong pointer guarded).
The GUI stack builds for the web sample target. Recipe (dev-box; prefix paths are examples):
-
Cross-build the static deps with the emsdk into a local prefix:
- Lua 5.1.5:
make generic CC="emcc -O2" AR="emar rcu" RANLIB=emranlib,make install INSTALL_TOP=<prefix>. - libxml2 (2.12.x):
emcmake cmakewith-DBUILD_SHARED_LIBS=OFF -DLIBXML2_WITH_{PYTHON,ICONV,LZMA,ZLIB,TESTS,PROGRAMS}=OFF. -
ryzom/luabind:
emcmake cmakeagainst the wasm Lua. Boost is headers-only here, but do not pass/usr/includeas the Boost include dir — host headers poison the emscripten sysroot; symlinkboost/into a clean directory instead.
- Lua 5.1.5:
-
curl/openssl are not built —
nel/samples/gui/emscripten/nel_wasm_stubs.c(compiled with emcc, archived aslibcurl.a/libssl.a/libcrypto.ain the prefix, with real curl headers copied alongside) provides symbol-level stubs whose entry points fail the way the real libraries would. NeL's error paths handle that; a JS missing-function import would abort at the first call instead (CCurlHttpClient::connectdereferencescurl_version_info()unconditionally, so that one returns a static struct). SysV IPC stubs cover nelmisc shared memory. -
Configure the emscripten tree with
WITH_GUI=ON WITH_WEB=ON WITH_LUA51=ONplusLUA_*,LUABIND_*,Boost_INCLUDE_DIR,LibXml2_DIR=<prefix>/lib/cmake/libxml2-<ver>,CURL_INCLUDE_DIR/CURL_LIBRARY,OPENSSL_*pointing at the prefix, andNL_BUILD_INTERFACE_TOOL=<host build>/bin/build_interfacefor the atlas pack. The root CMake emscripten branch probes these instead of compiling XML support out (nelmiscgains realCIXmlon wasm this way). - The sample selects
UDriver::OpenGlEs3under emscripten and defaults to the 1600x1200 showcase layout; the html page CSS-scales the canvas. Deploys next to the other WebGL samples (nl_sample_gui.html/.js/.wasm/.data).
Verified in headless chromium over SwiftShader WebGL: rendering matches the native build, including evaluated <link>s and the color picker palette.
- M1 (landed): skeleton —
w_layer0 container window with header/title/buttons,w_modalmodal viaenter_modal, mouse pointer, frame-capped loop, headless screenshot mode, xdotool-verified event chain under Xvfb. - M2 (landed): comprehensive widget coverage as described above, every interaction verified headless.
- M3 (landed): Emscripten/WebGL build deployed with the other NeL web samples.