form_loader - ryzom/ryzomcore GitHub Wiki
title: Reading sheets using the form loader description: How to load and read Georges form data at runtime using UFormLoader and UFormElm published: true date: 2023-03-16T23:03:38.891Z tags: editor: markdown dateCreated: 2022-03-16T10:34:59.938Z
For simple loading of sheets, you need to do the following.
-
Add the search path for the sheets you want to load using
CPath::addSearchPath(). -
The required
.dfnand.typfiles must also be in a search path. -
Create a Georges form loader.
NLGEORGES::UFormLoader *formLoader = NLGEORGES::UFormLoader::createLoader();
This loader can be used to load many sheets, so keep it around and reuse it. {.is-info}
-
Load a form.
NLMISC::CSmartPtr<NLGEORGES::UForm> form = formLoader->loadForm("the_sheet_file.sheet_type");
sheet_type is the extension of the sheet file. It must match a DFN name — for example
foo.dfnallows loading of*.foosheets.In other words, when
loadFormis passedbar.fooas an input file, it will try to find thefoo.dfnformat file. If it doesn't find it, the loading fails. -
When done with all loading, release the loader.
NLGEORGES::UFormLoader::releaseLoader(formLoader);
Now you have the form you can access data using the form interface by getting the root element:
const NLGEORGES::UFormElm &root = form->getRootNode();Then you can access data by name using dot notation for nested fields and bracket notation for arrays:
// Read a simple value
sint32 hitPoints;
root.getValueByName(hitPoints, "HitPoints");
// Read a nested struct value
float posX;
root.getValueByName(posX, "PositionData.x");
// Read from an array of structs
std::string name;
root.getValueByName(name, "CoolFilesInfo[0].ShortName");getValueByName has overloads for the following C++ types:
| C++ Type | Georges Type |
|---|---|
std::string |
String |
bool |
Any (parsed from string) |
sint8, uint8, sint16, uint16
|
UnsignedInt / SignedInt |
sint32, uint32
|
UnsignedInt / SignedInt |
float, double
|
Double |
NLMISC::CRGBA |
Color |
All getValueByName overloads return bool indicating success, and take an optional TEval parameter controlling evaluation mode:
-
Eval(default) — fully evaluates the value, resolving references and formulas. -
Formula— evaluates enum definitions but not formulas/references. -
NoEval— returns the raw string without any evaluation.
There is an equivalent setValueByName for modifying form values at runtime:
root.setValueByName(500, "HitPoints");The setValueByName overloads accept an optional bool *created output parameter that indicates whether the value was newly created (rather than overwriting an existing one).
To iterate over an array, first get the array node, then query its size:
const NLGEORGES::UFormElm *arrayNode;
root.getNodeByName(&arrayNode, "TestArray");
if (arrayNode)
{
uint size;
arrayNode->getArraySize(size);
for (uint i = 0; i < size; ++i)
{
std::string value;
arrayNode->getArrayValue(value, i);
nlinfo("TestArray[%d] = %s", i, value.c_str());
}
}For arrays of structs, use getArrayNode to get individual struct elements:
const NLGEORGES::UFormElm *arrayNode;
root.getNodeByName(&arrayNode, "CoolFilesInfo");
if (arrayNode)
{
uint size;
arrayNode->getArraySize(size);
for (uint i = 0; i < size; ++i)
{
const NLGEORGES::UFormElm *structNode;
arrayNode->getArrayNode(&structNode, i);
if (structNode)
{
std::string shortName;
uint32 ranking;
structNode->getValueByName(shortName, "ShortName");
structNode->getValueByName(ranking, "Ranking");
}
}
}To enumerate fields in a struct without knowing their names in advance:
uint structSize;
root.getStructSize(structSize);
for (uint i = 0; i < structSize; ++i)
{
std::string fieldName;
root.getStructNodeName(i, fieldName);
nlinfo("Field %d: %s", i, fieldName.c_str());
}Key methods on UFormElm:
| Method | Description |
|---|---|
getValueByName(result, name) |
Read a value by dot/bracket path |
setValueByName(value, name) |
Write a value by dot/bracket path |
getNodeByName(&node, name) |
Get a child node by path |
isStruct() / isAtom() / isVirtualStruct()
|
Query the node type |
getStructSize(size) |
Get the number of fields in a struct |
getStructNodeName(index, name) |
Get a field name by index |
getStructNode(index, &node) |
Get a field node by index |
getArraySize(size) |
Get the number of elements in an array |
getArrayNode(&node, index) |
Get an array element by index |
getArrayValue(result, index) |
Read an array element value by index |
getDfnName(name) |
Get the DFN filename for this struct node |