propertyParsing.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #include "core/strings/stringFunctions.h"
  23. #include "core/strings/stringUnit.h"
  24. #include "console/consoleInternal.h"
  25. #include "core/color.h"
  26. #include "console/consoleTypes.h"
  27. #include "math/mPoint2.h"
  28. #include "math/mPoint3.h"
  29. #include "math/mPoint4.h"
  30. #include "math/mRect.h"
  31. #include "math/mBox.h"
  32. #include "math/mQuat.h"
  33. #include "math/mAngAxis.h"
  34. #include "math/mMatrix.h"
  35. // Property system includes:
  36. #include "console/propertyParsing.h"
  37. extern ExprEvalState gEvalState;
  38. namespace PropertyInfo
  39. {
  40. //-----------------------------------------------------------------------------
  41. // Bool
  42. //-----------------------------------------------------------------------------
  43. bool default_scan(const String &data, bool & result)
  44. {
  45. result = dAtob(data.c_str());
  46. return true;
  47. }
  48. bool default_print(String & result, bool const & data)
  49. {
  50. if(data)
  51. result = String("1");
  52. else
  53. result = String("0");
  54. return true;
  55. }
  56. //-----------------------------------------------------------------------------
  57. // F32/U32/S32
  58. //-----------------------------------------------------------------------------
  59. bool default_scan(const String &data, F32 & result)
  60. {
  61. result = dAtof(data.c_str());
  62. return true;
  63. }
  64. bool default_print(String & result, F32 const & data)
  65. {
  66. result = String::ToString(data);
  67. return true;
  68. }
  69. bool default_scan(const String &data, U32 & result)
  70. {
  71. result = dAtoi(data.c_str());
  72. return true;
  73. }
  74. bool default_print(String & result, U32 const & data)
  75. {
  76. result = String::ToString(data);
  77. return true;
  78. }
  79. bool default_scan(const String &data, S32 & result)
  80. {
  81. result = dAtoi(data.c_str());
  82. return true;
  83. }
  84. bool default_print(String & result, S32 const & data)
  85. {
  86. result = String::ToString(data);
  87. return true;
  88. }
  89. //-----------------------------------------------------------------------------
  90. // Basic Vector Types
  91. //-----------------------------------------------------------------------------
  92. template <typename T>
  93. inline void default_vector_scan(const String &data, Vector<T> & result)
  94. {
  95. result.clear();
  96. for(S32 i = 0; i < StringUnit::getUnitCount(data, " \t\n"); i++)
  97. result.push_back(dAtof(StringUnit::getUnit(data, i, " \t\n")));
  98. }
  99. template <typename T>
  100. inline void default_vector_print(String & result, Vector<T> const & data)
  101. {
  102. result = String("");
  103. S32 items = data.size();
  104. for(S32 i = 0; i < items; i++)
  105. {
  106. result += String::ToString(data[i]);
  107. if(i < items-1)
  108. result += String(" ");
  109. }
  110. }
  111. bool default_scan(const String &data, Vector<F32> & result)
  112. {
  113. default_vector_scan(data,result);
  114. return true;
  115. }
  116. bool default_print(String & result, Vector<F32> const & data)
  117. {
  118. default_vector_print<F32>(result,data);
  119. return true;
  120. }
  121. bool default_scan(const String &data, Vector<U32> & result)
  122. {
  123. default_vector_scan(data,result);
  124. return true;
  125. }
  126. bool default_print(String & result, Vector<U32> const & data)
  127. {
  128. default_vector_print<U32>(result,data);
  129. return true;
  130. }
  131. bool default_scan(const String &data, Vector<S32> & result)
  132. {
  133. default_vector_scan(data,result);
  134. return true;
  135. }
  136. bool default_print(String & result, Vector<S32> const & data)
  137. {
  138. default_vector_print<S32>(result,data);
  139. return true;
  140. }
  141. //-----------------------------------------------------------------------------
  142. // Math - Points
  143. //-----------------------------------------------------------------------------
  144. bool default_scan(const String &data, Point2F & result)
  145. {
  146. dSscanf(data.c_str(),"%g %g",&result.x,&result.y);
  147. return true;
  148. }
  149. bool default_print(String & result, Point2F const & data)
  150. {
  151. result = String::ToString("%g %g",data.x,data.y);
  152. return true;
  153. }
  154. bool default_scan(const String &data, Point2I & result)
  155. {
  156. // Handle passed as floating point from script
  157. if(data.find('.') != String::NPos)
  158. {
  159. Point2F tempResult;
  160. dSscanf(data.c_str(),"%f %f",&tempResult.x,&tempResult.y);
  161. result.x = mFloor(tempResult.x);
  162. result.y = mFloor(tempResult.y);
  163. }
  164. else
  165. dSscanf(data.c_str(),"%d %d",&result.x,&result.y);
  166. return true;
  167. }
  168. bool default_print(String & result, Point2I const & data)
  169. {
  170. result = String::ToString("%d %d",data.x,data.y);
  171. return true;
  172. }
  173. bool default_scan(const String &data, Point3F & result)
  174. {
  175. dSscanf(data.c_str(),"%g %g %g",&result.x,&result.y,&result.z);
  176. return true;
  177. }
  178. bool default_print(String & result, Point3F const & data)
  179. {
  180. result = String::ToString("%g %g %g",data.x,data.y,data.z);
  181. return true;
  182. }
  183. bool default_scan(const String &data, Point3I & result)
  184. {
  185. // Handle passed as floating point from script
  186. if(data.find('.') != String::NPos)
  187. {
  188. Point3F tempResult;
  189. dSscanf(data.c_str(),"%f %f %f",&tempResult.x,&tempResult.y,&tempResult.z);
  190. result.x = mFloor(tempResult.x);
  191. result.y = mFloor(tempResult.y);
  192. result.z = mFloor(tempResult.z);
  193. }
  194. else
  195. dSscanf(data.c_str(),"%d %d %d",&result.x,&result.y,&result.z);
  196. return true;
  197. }
  198. bool default_print(String & result, Point3I const & data)
  199. {
  200. result = String::ToString("%d %d %d",data.x,data.y,data.z);
  201. return true;
  202. }
  203. bool default_scan(const String &data, Point4F & result)
  204. {
  205. dSscanf(data.c_str(),"%g %g %g %g",&result.x,&result.y,&result.z,&result.w);
  206. return true;
  207. }
  208. bool default_print(String & result, Point4F const & data)
  209. {
  210. result = String::ToString("%g %g %g %g",data.x,data.y,data.z,data.w);
  211. return true;
  212. }
  213. bool default_scan(const String &data, Point4I & result)
  214. {
  215. // Handle passed as floating point from script
  216. if(data.find('.') != String::NPos)
  217. {
  218. Point4F tempResult;
  219. dSscanf(data.c_str(),"%f %f %f %f",&tempResult.x,&tempResult.y,&tempResult.z,&tempResult.w);
  220. result.x = mFloor(tempResult.x);
  221. result.y = mFloor(tempResult.y);
  222. result.z = mFloor(tempResult.z);
  223. result.w = mFloor(tempResult.w);
  224. }
  225. else
  226. dSscanf(data.c_str(),"%d %d %d %d",&result.x,&result.y,&result.z,&result.w);
  227. return true;
  228. }
  229. bool default_print(String & result, const Point4I & data)
  230. {
  231. result = String::ToString("%d %d %d %d", data.x, data.y, data.z, data.w);
  232. return true;
  233. }
  234. //-----------------------------------------------------------------------------
  235. // Math - Rectangles and boxes
  236. //-----------------------------------------------------------------------------
  237. bool default_scan( const String &data, RectI & result )
  238. {
  239. // Handle passed as floating point from script
  240. if(data.find('.') != String::NPos)
  241. {
  242. RectF tempResult;
  243. dSscanf(data.c_str(),"%f %f %f %f",&tempResult.point.x,&tempResult.point.y,&tempResult.extent.x,&tempResult.extent.y);
  244. result.point.x = mFloor(tempResult.point.x);
  245. result.point.y = mFloor(tempResult.point.y);
  246. result.extent.x = mFloor(tempResult.extent.x);
  247. result.extent.y = mFloor(tempResult.extent.y);
  248. }
  249. else
  250. dSscanf(data.c_str(),"%d %d %d %d",&result.point.x,&result.point.y,&result.extent.x,&result.extent.y);
  251. return true;
  252. }
  253. bool default_print( String & result, const RectI & data )
  254. {
  255. result = String::ToString("%i %i %i %i",data.point.x,data.point.y,data.extent.x,data.extent.y);
  256. return true;
  257. }
  258. bool default_scan(const String &data, RectF & result)
  259. {
  260. dSscanf(data.c_str(),"%g %g %g %g",&result.point.x,&result.point.y,&result.extent.x,&result.extent.y);
  261. return true;
  262. }
  263. bool default_print(String & result, const RectF & data)
  264. {
  265. result = String::ToString("%g %g %g %g",data.point.x,data.point.y,data.extent.x,data.extent.y);
  266. return true;
  267. }
  268. bool default_scan(const String &data, Box3F & result)
  269. {
  270. dSscanf(data.c_str(),"%g %g %g %g %g %g",
  271. &result.minExtents.x,&result.minExtents.y,&result.minExtents.z,
  272. &result.maxExtents.x,&result.maxExtents.y,&result.maxExtents.z);
  273. return true;
  274. }
  275. bool default_print(String & result, const Box3F & data)
  276. {
  277. result = String::ToString("%g %g %g %g %g %g",
  278. data.minExtents.x,data.minExtents.y,data.minExtents.z,
  279. data.maxExtents.x,data.maxExtents.y,data.maxExtents.z);
  280. return true;
  281. }
  282. //-----------------------------------------------------------------------------
  283. bool default_scan( const String &data, AngAxisF & result )
  284. {
  285. if(StringUnit::getUnitCount(data," ") < 4)
  286. return false;
  287. dSscanf(data.c_str(),"%g %g %g %g", &result.axis.x,&result.axis.y,&result.axis.z,&result.angle);
  288. result.angle = mDegToRad(result.angle);
  289. return true;
  290. }
  291. bool default_print( String & result, const AngAxisF & data )
  292. {
  293. F32 angle = mRadToDeg(data.angle);
  294. angle = mFmod(angle + 360.0f,360.0f);
  295. result = String::ToString("%g %g %g %g", data.axis.x, data.axis.y, data.axis.z, angle);
  296. return true;
  297. }
  298. bool default_scan( const String &data, QuatF & result )
  299. {
  300. if(StringUnit::getUnitCount(data," ") < 4)
  301. return false;
  302. dSscanf(data.c_str(),"%g %g %g %g", &result.x,&result.y,&result.z,&result.w);
  303. return true;
  304. }
  305. bool default_print( String & result, const QuatF & data )
  306. {
  307. result = String::ToString("%g %g %g %g", data.x, data.y, data.z, data.w);
  308. return true;
  309. }
  310. bool default_scan( const String &data, MatrixF & result )
  311. {
  312. if(StringUnit::getUnitCount(data," ") < 16)
  313. return false;
  314. F32* m = result;
  315. dSscanf(data.c_str(),"%g %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g",
  316. &m[result.idx(0,0)], &m[result.idx(0,1)], &m[result.idx(0,2)], &m[result.idx(0,3)],
  317. &m[result.idx(1,0)], &m[result.idx(1,1)], &m[result.idx(1,2)], &m[result.idx(1,3)],
  318. &m[result.idx(2,0)], &m[result.idx(2,1)], &m[result.idx(2,2)], &m[result.idx(2,3)],
  319. &m[result.idx(3,0)], &m[result.idx(3,1)], &m[result.idx(3,2)], &m[result.idx(3,3)]);
  320. return true;
  321. }
  322. bool default_print( String & result, const MatrixF & data )
  323. {
  324. const F32* m = data;
  325. result = String::ToString("%g %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g",
  326. m[data.idx(0,0)], m[data.idx(0,1)], m[data.idx(0,2)], m[data.idx(0,3)],
  327. m[data.idx(1,0)], m[data.idx(1,1)], m[data.idx(1,2)], m[data.idx(1,3)],
  328. m[data.idx(2,0)], m[data.idx(2,1)], m[data.idx(2,2)], m[data.idx(2,3)],
  329. m[data.idx(3,0)], m[data.idx(3,1)], m[data.idx(3,2)], m[data.idx(3,3)]);
  330. return true;
  331. }
  332. //-----------------------------------------------------------------------------
  333. // Colors
  334. //-----------------------------------------------------------------------------
  335. bool default_scan(const String &data, LinearColorF & result)
  336. {
  337. if(StringUnit::getUnitCount(data," ") == 3)
  338. {
  339. dSscanf(data.c_str(),"%g %g %g",&result.red,&result.green,&result.blue);
  340. result.alpha = 1.0f;
  341. }
  342. else
  343. dSscanf(data.c_str(),"%g %g %g %g",&result.red,&result.green,&result.blue,&result.alpha);
  344. return true;
  345. }
  346. bool default_print(String & result, LinearColorF const & data)
  347. {
  348. if(data.alpha == 1.0f)
  349. result = String::ToString("%g %g %g",data.red,data.green,data.blue);
  350. else
  351. result = String::ToString("%g %g %g %g",data.red,data.green,data.blue,data.alpha);
  352. return true;
  353. }
  354. bool default_scan(const String &data, ColorI & result)
  355. {
  356. if(StringUnit::getUnitCount(data," ") == 3)
  357. {
  358. S32 r,g,b;
  359. dSscanf(data.c_str(),"%i %i %i",&r,&g,&b);
  360. result.set(r,g,b);
  361. }
  362. else
  363. {
  364. S32 r,g,b,a;
  365. dSscanf(data.c_str(),"%i %i %i %i",&r,&g,&b,&a);
  366. result.set(r,g,b,a);
  367. }
  368. return true;
  369. }
  370. bool default_print(String & result, const ColorI & data)
  371. {
  372. if(data.alpha == 255)
  373. result = String::ToString("%d %d %d",data.red,data.green,data.blue);
  374. else
  375. result = String::ToString("%d %d %d %d",data.red,data.green,data.blue,data.alpha);
  376. return true;
  377. }
  378. //-----------------------------------------------------------------------------
  379. // String
  380. //-----------------------------------------------------------------------------
  381. bool default_scan(const String &data, String & result)
  382. {
  383. result = data;
  384. return true;
  385. }
  386. bool default_print(String & result, const String & data)
  387. {
  388. result = data;
  389. return true;
  390. }
  391. //-----------------------------------------------------------------------------
  392. // FileName
  393. //-----------------------------------------------------------------------------
  394. bool default_scan(const String &data, FileName & result)
  395. {
  396. char buffer[1024];
  397. if(data.c_str()[0] == '$')
  398. {
  399. dStrncpy(buffer, data.c_str(), sizeof(buffer) - 1);
  400. buffer[sizeof(buffer)-1] = 0;
  401. }
  402. else if (!Con::expandScriptFilename(buffer, sizeof(buffer), data))
  403. {
  404. Con::warnf("(TypeFilename) illegal filename detected: %s", data.c_str());
  405. return false;
  406. }
  407. result = String(buffer);
  408. return true;
  409. }
  410. bool default_print(String & result, const FileName & data)
  411. {
  412. result = data;
  413. return true;
  414. }
  415. //-----------------------------------------------------------------------------
  416. // SimObject
  417. //-----------------------------------------------------------------------------
  418. bool default_scan(const String &data, SimObject * & result)
  419. {
  420. result = Sim::findObject(data);
  421. return result != NULL;
  422. }
  423. bool default_print(String & result, SimObject * const & data)
  424. {
  425. if(data)
  426. {
  427. if(String(data->getName()).isEmpty())
  428. result = data->getIdString();
  429. else
  430. result = data->getName();
  431. return true;
  432. }
  433. return false;
  434. }
  435. //-----------------------------------------------------------------------------
  436. // Print scan ints of various sizes as hex
  437. //-----------------------------------------------------------------------------
  438. //-------
  439. // 16 bit
  440. //-------
  441. bool hex_scan(const String & string, U32 & hex)
  442. {
  443. dSscanf(string.c_str(),"%i", &hex);
  444. return true;
  445. }
  446. bool hex_print(String & string, const U32 & hex)
  447. {
  448. string = String::ToString("0x%X",hex);
  449. return true;
  450. }
  451. bool hex_scan(const String & string, S32 & hex)
  452. {
  453. dSscanf(string.c_str(),"%i", &hex);
  454. return true;
  455. }
  456. bool hex_print(String & string, const S32 & hex)
  457. {
  458. string = String::ToString("0x%X",hex);
  459. return true;
  460. }
  461. //-------
  462. // 16 bit
  463. //-------
  464. bool hex_scan(const String & string, U16 & hex)
  465. {
  466. U32 tmp;
  467. bool ret = hex_scan(string,tmp);
  468. hex = tmp;
  469. return ret;
  470. }
  471. bool hex_print(String & string, const U16 & hex)
  472. {
  473. U32 tmp = hex;
  474. return hex_print(string,tmp);
  475. }
  476. bool hex_scan(const String & string, S16 & hex)
  477. {
  478. S32 tmp;
  479. bool ret = hex_scan(string,tmp);
  480. hex = tmp;
  481. return ret;
  482. }
  483. bool hex_print(String & string, const S16 & hex)
  484. {
  485. U32 tmp = hex;
  486. return hex_print(string,tmp);
  487. }
  488. //-------
  489. // 8 bit
  490. //-------
  491. bool hex_scan(const String & string, U8 & hex)
  492. {
  493. U32 tmp;
  494. bool ret = hex_scan(string,tmp);
  495. hex = tmp;
  496. return ret;
  497. }
  498. bool hex_print(String & string, const U8 & hex)
  499. {
  500. U32 tmp = hex;
  501. return hex_print(string,tmp);
  502. }
  503. bool hex_scan(const String & string, S8 & hex)
  504. {
  505. S32 tmp;
  506. bool ret = hex_scan(string,tmp);
  507. hex = tmp;
  508. return ret;
  509. }
  510. bool hex_print(String & string, const S8 & hex)
  511. {
  512. U32 tmp = hex;
  513. return hex_print(string,tmp);
  514. }
  515. }