4 * \author Matt Raykowski
6 * This sample shows how to load a Georges form and read parts from it.
9 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
10 // Copyright (C) 2010 Winch Gate Property Limited
12 // This source file has been modified by the following contributors:
13 // Copyright (C) 2014 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
15 // This program is free software: you can redistribute it and/or modify
16 // it under the terms of the GNU Affero General Public License as
17 // published by the Free Software Foundation, either version 3 of the
18 // License, or (at your option) any later version.
20 // This program is distributed in the hope that it will be useful,
21 // but WITHOUT ANY WARRANTY; without even the implied warranty of
22 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 // GNU Affero General Public License for more details.
25 // You should have received a copy of the GNU Affero General Public License
26 // along with this program. If not, see <http://www.gnu.org/licenses/>.
36 #include "nel/misc/debug.h"
38 #include "nel/georges/u_form_loader.h"
39 #include "nel/georges/u_form.h"
40 #include "nel/georges/u_form_elm.h"
41 #include "nel/georges/load_form.h"
51 /// This class must be serializable for the form to be packed.
52 void serial(NLMISC::IStream
&f
)
62 /// Load a form, if necessary, and store its data in the members of this class.
63 void readGeorges (const NLMISC::CSmartPtr
<NLGEORGES::UForm
> &form
, const NLMISC::CSheetId
&sheetId
)
68 void readGeorges (const NLMISC::CSmartPtr
<NLGEORGES::UForm
> &form
, const std::string
&sheetId
)
73 void readForm(const NLMISC::CSmartPtr
<NLGEORGES::UForm
> &form
)
75 nlinfo("Loading a sample config object.");
76 // The system has already loaded the form and parsed it using a loader. So get the root node:
77 NLGEORGES::UFormElm
&root
= form
->getRootNode();
79 // And start loading the form values into the object.
80 root
.getValueByName(TestVal1
, ".TestVal1");
81 root
.getValueByName(TestVal2
, ".TestVal2");
83 root
.getValueByName(PosData
.X
,"PositionData.x");
84 root
.getValueByName(PosData
.Y
,"PositionData.y");
85 root
.getValueByName(PosData
.Z
,"PositionData.z");
87 // Get the array called "TestArray"
88 NLGEORGES::UFormElm
*testArray
;
89 root
.getNodeByName(&testArray
, ".TestArray");
90 if(testArray
!= NULL
) {
91 // Get the size of the array.
93 testArray
->getArraySize(size
);
95 // Cycle through the atoms in the array
96 for(uint idx
=0 ; idx
<size
; idx
++) {
97 std::string arrayValue
;
99 // Get the value of the array.
100 testArray
->getArrayValue(arrayValue
, idx
);
101 // And insert it into our container.
102 TestArray
.push_back(arrayValue
);
106 // And so on. We'll skip the rest of the sheet, you get the idea.
110 /// This class must be serializable for the form to be packed.
111 void serial(NLMISC::IStream
&f
)
116 f
.serialCont(TestArray
);
119 /// This is called whenever the loader needs to remove an old sheet.
125 /// This is used to make sure that changes in form/loader versions are correctly handled. This must be > 0.
126 static uint
getVersion() { return 1; }
131 TPositionData PosData
;
133 std::vector
<std::string
> TestArray
;
136 /// This contains the TSampleConfig sheets.
137 std::map
<NLMISC::CSheetId
, TSampleConfig
> MySampleConfigsSheets
;
138 std::map
<std::string
, TSampleConfig
> MySampleConfigs
;
142 new NLMISC::CApplicationContext
;
144 // get a pointer ready for the form loader.
145 NLGEORGES::UFormLoader
*formLoader
= NULL
;
147 NLMISC::CPath::addSearchPath(GF_DIR
, false, false);
150 // set the name of the form you're going to load.
151 std::string sampleConfigFile
= NLMISC::CPath::lookup("default.sample_config", false);
153 // check to see if CPath found the config.
154 if (!sampleConfigFile
.empty()) {
155 // we'll use this to test retrieving vars.
158 // get a form loader.
159 formLoader
= NLGEORGES::UFormLoader::createLoader();
161 // this will hold the form we load - it must be contained in a smart pointer.
162 NLMISC::CSmartPtr
<NLGEORGES::UForm
> form
;
165 form
= formLoader
->loadForm(sampleConfigFile
.c_str());
167 // get the root of the form.
168 NLGEORGES::UFormElm
&root
= form
->getRootNode();
170 // retrieve the two test values
171 uint32 testVal1
, testVal2
, badVar1
;
172 root
.getValueByName(testVal1
, ".TestVal1");
173 root
.getValueByName(testVal2
, ".TestVal2");
175 // try and get a var that doesn't exist.
176 res
=root
.getValueByName(badVar1
, ".Foobar");
178 nlinfo("This should never have matched.");
183 nlinfo("Test Value 1: %d",testVal1
);
184 nlinfo("Test Value 2: %d",testVal2
);
185 nlinfo("Foo Retrieval was: %s", res
? "true" : "false");
187 // Retrieve data from a root-level named struct
188 uint xTest
, yTest
, zTest
;
189 root
.getValueByName(xTest
,"PositionData.x");
190 root
.getValueByName(yTest
,"PositionData.y");
191 root
.getValueByName(zTest
,"PositionData.z");
192 nlinfo("Retrieved Position Data (x,y,z): %d, %d, %d",xTest
,yTest
,zTest
);
194 // get a reference to the TestArray array...
195 NLGEORGES::UFormElm
*testArray
;
196 res
=root
.getNodeByName(&testArray
, ".TestArray");
198 nlinfo("TestArray retrieval returned: %s", res
? "true" : "false");
199 // make sure it was there.
200 if(testArray
!= NULL
) {
201 // get the size of the array.
203 testArray
->getArraySize(size
);
205 // cycle through the atoms in the array
206 for(uint idx
=0 ; idx
<size
; idx
++) {
207 // string to store our array values in.
208 std::string arrayValue
;
210 // and get the value of the array, we know it's a string.
211 testArray
->getArrayValue(arrayValue
, idx
);
213 nlinfo("Found TestArray atom: %s",arrayValue
.c_str());
217 nlinfo("TestArray wasn't configured properly but was found, double check the form.");
219 nlinfo("Something's wrong, the TestArray is missing from the form.");
222 // Next grab a set of structures from an array.
223 NLGEORGES::UFormElm
*coolFiles
;
224 res
=root
.getNodeByName(&coolFiles
, ".CoolFilesInfo");
226 nlinfo("Retrieving CoolFilesInfo returned: %s", res
? "true" : "false");
227 if(coolFiles
!= NULL
) {
229 coolFiles
->getArraySize(size
);
231 // cycle through the structs in the array.
232 for(uint idx
=0 ; idx
<size
; idx
++) {
233 // storage for our vars in the structs
234 std::string name
, shortname
;
235 uint rank
, toptenrank
;
237 // since we know the structure of the file, we know the array contains structs
238 // retrieve the struct for use.
239 NLGEORGES::UFormElm
*files
;
240 coolFiles
->getArrayNode(&files
, idx
);
242 // we can now access this struct in the array as a root.
243 files
->getValueByName(rank
, ".Ranking");
244 files
->getValueByName(toptenrank
, ".TopTenRanking");
245 files
->getValueByName(name
, ".Name");
246 files
->getValueByName(shortname
, ".ShortName");
247 nlinfo("Retrieved struct %d: |%s| - %s at %d (%d)", idx
, name
.c_str(), shortname
.c_str(), rank
, toptenrank
);
252 nlinfo("CoolFilesInfo was found, but might have been entered incorrectly, double check the form.");
254 nlinfo("CoolFilesInfo wasn't found or there was a syntax error loading your form.");
257 // we can also access elements of an array by their backet identifier.
258 std::string bbool1
, bbool2
;
259 root
.getValueByName(bbool1
, ".TestByBracket[0]");
260 root
.getValueByName(bbool2
, ".TestByBracket[1]");
261 nlinfo("Bool Backet 1: %s, Bool Bracket 2: %s",bbool1
.c_str(), bbool2
.c_str());
263 // likewise you can access structures by index and dot notation. take the CoolFilesInfo.
264 // the following should return 1, the ranking for the Nevrax Presents element.
265 // and the 2nd one should return 'Crazy Car Jump' from that element.
267 std::string nameTest
;
268 root
.getValueByName(rankTest
, ".CoolFilesInfo[2].Ranking");
269 root
.getValueByName(nameTest
, ".CoolFilesInfo[1].ShortName");
270 nlinfo("Retrieved .CoolFilesInfo[2].Ranking using bracket and dot notation: %d", rankTest
);
271 nlinfo("Retrieved .CoolFilesInfo[1].ShortName using bracket and dot notation: %s", nameTest
.c_str());
273 // if you set a value to a node name that doesn't exist, it's created. after running this you will see it listed in the form:
276 // first lets see if we can find it:
277 res
=root
.getValueByName(writeValue
,".WriteVal");
278 if(res
) // if it existed, save the value and increment it.
283 // now set the value. created tells us if the value was creaed or just updated.
285 root
.setValueByName(writeValue
,".WriteVal",&created
);
287 nlinfo("WriteVal wasn't found and was created.");
289 nlinfo("Updated WriteVal, it already existed in the form.");
292 // and finally save the form out in case we made changes.
293 // if you're accessing a form read-only (not using set*) you can skip this.
294 NLMISC::COFile
saveSample(sampleConfigFile
);
295 form
->write(saveSample
);
296 nlinfo("Saved sample config file.");
298 // CPath didn't find the file, just print an error and exit.
299 nlinfo("Couldn't find the config file.");
303 // finished, unload the form loader.
304 NLGEORGES::UFormLoader::releaseLoader(formLoader
);
307 // something went wrong, unload the form loader.
308 nlinfo("Caught an exception, quitting.");
309 NLGEORGES::UFormLoader::releaseLoader(formLoader
);
312 // Now demonstrate the packed sheet system.
313 nlinfo("Begin loading packed sheets.");
314 ::loadForm( "sample_config", "sample_configs.packed_sheets", MySampleConfigs
, true, false);
315 nlinfo("Number of sheets loaded: %d", MySampleConfigs
.size());
317 // Now demonstrate the packed sheet system using CSheetId's and the sheet_id.bin file.
318 nlinfo("Load packed sheets using CSheetId and the sheet_id.bin");
319 ::loadForm( "sample_config", "sample_configs_sheets.packed_sheets", MySampleConfigsSheets
, true, false);
320 nlinfo("Number of sheets loaded with CSheetId's: %d", MySampleConfigsSheets
.size());