ReAntTweakBar.h 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867
  1. // ReAntTweakBar is a minimal wrapper for the AntTweakBar library that allows
  2. // "bars" to be saved and load from disk. Changing your existing app that users
  3. // AntTweakBar to use ReAntTweakBar is trivial.
  4. //
  5. // Many (but not all) variable types are supported. I'll try to keep track them
  6. // here:
  7. // TW_TYPE_BOOLCPP
  8. // TW_TYPE_QUAT4F
  9. // TW_TYPE_COLOR4F
  10. // TW_TYPE_COLOR3F
  11. // TW_TYPE_DIR3F
  12. // TW_TYPE_BOOL32
  13. // TW_TYPE_INT32
  14. // TW_TYPE_FLOAT
  15. // TW_TYPE_DOUBLE
  16. // and
  17. // custom TwTypes made with TwDefineEnum
  18. //
  19. // I'm working on adding the rest on an as-needed basis. Adding a new type only
  20. // requires changes in a few places...
  21. //
  22. //
  23. // Copyright Alec Jacobson, 2011
  24. //
  25. // This allows the user to have a non-global, static installation of
  26. // AntTweakBar
  27. #ifdef STATIC_ANTTWEAKBAR
  28. # include "AntTweakBar.h"
  29. #else
  30. # include <AntTweakBar.h>
  31. #endif
  32. #include <vector>
  33. #include <string>
  34. namespace igl
  35. {
  36. TwType ReTwDefineEnum(const char *name, const TwEnumVal *enumValues, unsigned int nbValues);
  37. struct ReTwRWItem
  38. {
  39. const char * name;
  40. TwType type;
  41. void * var;
  42. ReTwRWItem(
  43. const char * name,
  44. TwType type,
  45. void *var)
  46. {
  47. this->name = name;
  48. this->type = type;
  49. this->var = var;
  50. }
  51. };
  52. struct ReTwCBItem
  53. {
  54. const char * name;
  55. TwSetVarCallback setCallback;
  56. TwGetVarCallback getCallback;
  57. void * clientData;
  58. TwType type;
  59. ReTwCBItem(
  60. const char * name,
  61. TwType type,
  62. TwSetVarCallback setCallback,
  63. TwGetVarCallback getCallback,
  64. void * clientData)
  65. {
  66. this->name = name;
  67. this->type = type;
  68. this->setCallback = setCallback;
  69. this->getCallback = getCallback;
  70. this->clientData = clientData;
  71. }
  72. };
  73. class ReTwBar
  74. {
  75. // VARIABLES
  76. // Should be private, but seeing as I'm not going to implement all of the
  77. // AntTweakBar public functions right away, I'll expose this so that at
  78. // anytime AntTweakBar functions can be called directly on the bar
  79. public:
  80. TwBar * bar;
  81. private:
  82. std::vector<ReTwRWItem> rw_items;
  83. std::vector<ReTwCBItem> cb_items;
  84. // WRAPPERS FOR ANTTWEAKBAR FUNCTIONS
  85. public:
  86. void TwNewBar(const char *barName);
  87. int TwAddVarRW(
  88. const char *name,
  89. TwType type,
  90. void *var,
  91. const char *def,
  92. const bool record=true);
  93. int TwAddVarCB(
  94. const char *name,
  95. TwType type,
  96. TwSetVarCallback setCallback,
  97. TwGetVarCallback getCallback,
  98. void *clientData,
  99. const char *def,
  100. const bool record=true);
  101. // Wrappers for convenience (not recorded, just passed on)
  102. int TwAddVarRO(const char *name, TwType type, void *var, const char *def);
  103. int TwAddButton(
  104. const char *name,
  105. TwButtonCallback buttonCallback,
  106. void *clientData,
  107. const char *def);
  108. int TwSetParam(
  109. const char *varName,
  110. const char *paramName,
  111. TwParamValueType paramValueType,
  112. unsigned int inValueCount,
  113. const void *inValues);
  114. int TwGetParam(
  115. const char *varName,
  116. const char *paramName,
  117. TwParamValueType paramValueType,
  118. unsigned int outValueMaxCount,
  119. void *outValues);
  120. int TwRefreshBar();
  121. // IO FUNCTIONS
  122. public:
  123. // Save current items to file
  124. // Input:
  125. // file_name name of file to save data to, can be null which means print
  126. // to stdout
  127. // Return:
  128. // true only if there were no (fatal) errors
  129. bool save(const char *file_name);
  130. std::string get_value_as_string(
  131. void * var,
  132. TwType type);
  133. // Load into current items from file
  134. // Input:
  135. // file_name name of input file to load
  136. // Return:
  137. // true only if there were no (fatal) errors
  138. bool load(const char *file_name);
  139. // Get TwType from string
  140. // Input
  141. // type_str string of type
  142. // Output
  143. // type TwType converted from string
  144. // Returns
  145. // true only if string matched a valid type
  146. bool type_from_string(const char *type_str, TwType & type);
  147. // I realize that I mixing std::string and const char * all over the place.
  148. // What can you do...
  149. bool set_value_from_string(
  150. const char * name,
  151. TwType type,
  152. const char * value_str);
  153. };
  154. };
  155. // List of TwBar functions
  156. //TW_API TwBar * TW_CALL TwNewBar(const char *barName);
  157. //TW_API int TW_CALL TwDeleteBar(TwBar *bar);
  158. //TW_API int TW_CALL TwDeleteAllBars();
  159. //TW_API int TW_CALL TwSetTopBar(const TwBar *bar);
  160. //TW_API TwBar * TW_CALL TwGetTopBar();
  161. //TW_API int TW_CALL TwSetBottomBar(const TwBar *bar);
  162. //TW_API TwBar * TW_CALL TwGetBottomBar();
  163. //TW_API const char * TW_CALL TwGetBarName(TwBar *bar);
  164. //TW_API int TW_CALL TwGetBarCount();
  165. //TW_API TwBar * TW_CALL TwGetBarByIndex(int barIndex);
  166. //TW_API TwBar * TW_CALL TwGetBarByName(const char *barName);
  167. //TW_API int TW_CALL TwRefreshBar(TwBar *bar);
  168. //
  169. //TW_API int TW_CALL TwAddVarRW(TwBar *bar, const char *name, TwType type, void *var, const char *def);
  170. //TW_API int TW_CALL TwAddVarRO(TwBar *bar, const char *name, TwType type, const void *var, const char *def);
  171. //TW_API int TW_CALL TwAddVarCB(TwBar *bar, const char *name, TwType type, TwSetVarCallback setCallback, TwGetVarCallback getCallback, void *clientData, const char *def);
  172. //TW_API int TW_CALL TwAddButton(TwBar *bar, const char *name, TwButtonCallback callback, void *clientData, const char *def);
  173. //TW_API int TW_CALL TwAddSeparator(TwBar *bar, const char *name, const char *def);
  174. //TW_API int TW_CALL TwRemoveVar(TwBar *bar, const char *name);
  175. //TW_API int TW_CALL TwRemoveAllVars(TwBar *bar);
  176. // Implementation
  177. #include <cstdio>
  178. #include <sstream>
  179. #include <map>
  180. #define MAX_CB_VAR_SIZE 10
  181. // Max line size for reading files
  182. #define MAX_LINE 1000
  183. #define MAX_WORD 100
  184. // GLOBAL WRAPPERS
  185. namespace igl
  186. {
  187. std::map<TwType,std::pair<const char *,std::vector<TwEnumVal> > > ReTw_custom_types;
  188. }
  189. TwType igl::ReTwDefineEnum(
  190. const char *name,
  191. const TwEnumVal *enumValues,
  192. unsigned int nbValues)
  193. {
  194. // copy enum valus into vector
  195. std::vector<TwEnumVal> enum_vals;
  196. enum_vals.resize(nbValues);
  197. for(unsigned int j = 0; j<nbValues;j++)
  198. {
  199. enum_vals[j] = enumValues[j];
  200. }
  201. TwType type = TwDefineEnum(name,enumValues,nbValues);
  202. ReTw_custom_types[type] =
  203. std::pair<const char *,std::vector<TwEnumVal> >(name,enum_vals);
  204. return type;
  205. }
  206. namespace igl
  207. {
  208. struct ReTwTypeString
  209. {
  210. TwType type;
  211. const char * type_str;
  212. };
  213. #define RETW_NUM_DEFAULT_TYPE_STRINGS 23
  214. ReTwTypeString ReTwDefaultTypeStrings[RETW_NUM_DEFAULT_TYPE_STRINGS] =
  215. {
  216. {TW_TYPE_UNDEF,"TW_TYPE_UNDEF"},
  217. {TW_TYPE_BOOLCPP,"TW_TYPE_BOOLCPP"},
  218. {TW_TYPE_BOOL8,"TW_TYPE_BOOL8"},
  219. {TW_TYPE_BOOL16,"TW_TYPE_BOOL16"},
  220. {TW_TYPE_BOOL32,"TW_TYPE_BOOL32"},
  221. {TW_TYPE_CHAR,"TW_TYPE_CHAR"},
  222. {TW_TYPE_INT8,"TW_TYPE_INT8"},
  223. {TW_TYPE_UINT8,"TW_TYPE_UINT8"},
  224. {TW_TYPE_INT16,"TW_TYPE_INT16"},
  225. {TW_TYPE_UINT16,"TW_TYPE_UINT16"},
  226. {TW_TYPE_INT32,"TW_TYPE_INT32"},
  227. {TW_TYPE_UINT32,"TW_TYPE_UINT32"},
  228. {TW_TYPE_FLOAT,"TW_TYPE_FLOAT"},
  229. {TW_TYPE_DOUBLE,"TW_TYPE_DOUBLE"},
  230. {TW_TYPE_COLOR32,"TW_TYPE_COLOR32"},
  231. {TW_TYPE_COLOR3F,"TW_TYPE_COLOR3F"},
  232. {TW_TYPE_COLOR4F,"TW_TYPE_COLOR4F"},
  233. {TW_TYPE_CDSTRING,"TW_TYPE_CDSTRING"},
  234. {TW_TYPE_STDSTRING,"TW_TYPE_STDSTRING"},
  235. {TW_TYPE_QUAT4F,"TW_TYPE_QUAT4F"},
  236. {TW_TYPE_QUAT4D,"TW_TYPE_QUAT4D"},
  237. {TW_TYPE_DIR3F,"TW_TYPE_DIR3F"},
  238. {TW_TYPE_DIR3D,"TW_TYPE_DIR3D"}
  239. };
  240. }
  241. // BAR WRAPPERS
  242. void igl::ReTwBar::TwNewBar(const char *barName)
  243. {
  244. // double colon without anything in front of it means look for this in the
  245. // global namespace... I hope...
  246. this->bar = ::TwNewBar(barName);
  247. }
  248. int igl::ReTwBar::TwAddVarRW(
  249. const char *name,
  250. TwType type,
  251. void *var,
  252. const char *def,
  253. const bool record)
  254. {
  255. int ret = ::TwAddVarRW(this->bar,name,type,var,def);
  256. if(ret && record)
  257. {
  258. rw_items.push_back(ReTwRWItem(name,type,var));
  259. }
  260. return ret;
  261. }
  262. int igl::ReTwBar::TwAddVarCB(
  263. const char *name,
  264. TwType type,
  265. TwSetVarCallback setCallback,
  266. TwGetVarCallback getCallback,
  267. void *clientData,
  268. const char *def,
  269. const bool record)
  270. {
  271. int ret =
  272. ::TwAddVarCB(this->bar,name,type,setCallback,getCallback,clientData,def);
  273. if(ret && record)
  274. {
  275. cb_items.push_back(ReTwCBItem(name,type,setCallback,getCallback,clientData));
  276. }
  277. return ret;
  278. }
  279. int igl::ReTwBar::TwAddVarRO(
  280. const char *name,
  281. TwType type,
  282. void *var,
  283. const char *def)
  284. {
  285. int ret = ::TwAddVarRO(this->bar,name,type,var,def);
  286. // Read only variables are not recorded
  287. //if(ret)
  288. //{
  289. // rw_items.push_back(ReTwRWItem(name,type,var));
  290. //}
  291. return ret;
  292. }
  293. int igl::ReTwBar::TwAddButton(
  294. const char *name,
  295. TwButtonCallback buttonCallback,
  296. void *clientData,
  297. const char *def)
  298. {
  299. int ret =
  300. ::TwAddButton(this->bar,name,buttonCallback,clientData,def);
  301. // buttons are not recorded
  302. //if(ret)
  303. //{
  304. // cb_items.push_back(ReTwCBItem(name,type,setCallback,getCallback,clientData));
  305. //}
  306. return ret;
  307. }
  308. int igl::ReTwBar::TwSetParam(
  309. const char *varName,
  310. const char *paramName,
  311. TwParamValueType paramValueType,
  312. unsigned int inValueCount,
  313. const void *inValues)
  314. {
  315. // For now just pass these along
  316. return
  317. ::TwSetParam(
  318. this->bar,
  319. varName,
  320. paramName,
  321. paramValueType,
  322. inValueCount,
  323. inValues);
  324. }
  325. int igl::ReTwBar::TwGetParam(
  326. const char *varName,
  327. const char *paramName,
  328. TwParamValueType paramValueType,
  329. unsigned int outValueMaxCount,
  330. void *outValues)
  331. {
  332. return
  333. ::TwGetParam(
  334. this->bar,
  335. varName,
  336. paramName,
  337. paramValueType,
  338. outValueMaxCount,
  339. outValues);
  340. }
  341. int igl::ReTwBar::TwRefreshBar()
  342. {
  343. return ::TwRefreshBar(this->bar);
  344. }
  345. bool igl::ReTwBar::save(const char *file_name)
  346. {
  347. FILE * fp;
  348. if(file_name == NULL)
  349. {
  350. fp = stdout;
  351. }else
  352. {
  353. fp = fopen(file_name,"w");
  354. }
  355. if(fp == NULL)
  356. {
  357. printf("ERROR: not able to open %s for writing...\n",file_name);
  358. return false;
  359. }
  360. // Print all RW variables
  361. for(
  362. std::vector<ReTwRWItem>::iterator it = rw_items.begin();
  363. it != rw_items.end();
  364. it++)
  365. {
  366. const char * name = (*it).name;
  367. TwType type = (*it).type;
  368. void * var = (*it).var;
  369. fprintf(fp,"%s: %s\n",
  370. name,
  371. get_value_as_string(var,type).c_str());
  372. }
  373. char var[MAX_CB_VAR_SIZE];
  374. // Print all CB variables
  375. for(
  376. std::vector<ReTwCBItem>::iterator it = cb_items.begin();
  377. it != cb_items.end();
  378. it++)
  379. {
  380. const char * name = it->name;
  381. TwType type = it->type;
  382. //TwSetVarCallback setCallback = it->setCallback;
  383. TwGetVarCallback getCallback = it->getCallback;
  384. void * clientData = it->clientData;
  385. // I'm not sure how to do what I want to do. getCallback needs to be sure
  386. // that it can write to var. So var needs to point to a valid and big
  387. // enough chunk of memory
  388. getCallback(var,clientData);
  389. fprintf(fp,"%s: %s\n",
  390. name,
  391. get_value_as_string(var,type).c_str());
  392. }
  393. fprintf(fp,"\n");
  394. if(file_name != NULL)
  395. {
  396. fclose(fp);
  397. }
  398. // everything succeeded
  399. return true;
  400. }
  401. std::string igl::ReTwBar::get_value_as_string(
  402. void * var,
  403. TwType type)
  404. {
  405. std::stringstream sstr;
  406. switch(type)
  407. {
  408. case TW_TYPE_BOOLCPP:
  409. {
  410. sstr << "TW_TYPE_BOOLCPP" << " ";
  411. sstr << *(static_cast<bool*>(var));
  412. break;
  413. }
  414. case TW_TYPE_QUAT4F:
  415. {
  416. sstr << "TW_TYPE_QUAT4F" << " ";
  417. // Q: Why does casting to float* work? shouldn't I have to cast to
  418. // float**?
  419. float * q = static_cast<float*>(var);
  420. sstr << q[0] << " " << q[1] << " " << q[2] << " " << q[3];
  421. break;
  422. }
  423. case TW_TYPE_COLOR4F:
  424. {
  425. sstr << "TW_TYPE_COLOR4F" << " ";
  426. float * c = static_cast<float*>(var);
  427. sstr << c[0] << " " << c[1] << " " << c[2] << " " << c[3];
  428. break;
  429. }
  430. case TW_TYPE_COLOR3F:
  431. {
  432. sstr << "TW_TYPE_COLOR3F" << " ";
  433. float * c = static_cast<float*>(var);
  434. sstr << c[0] << " " << c[1] << " " << c[2];
  435. break;
  436. }
  437. case TW_TYPE_DIR3F:
  438. {
  439. sstr << "TW_TYPE_DIR3F" << " ";
  440. float * d = static_cast<float*>(var);
  441. sstr << d[0] << " " << d[1] << " " << d[2];
  442. break;
  443. }
  444. case TW_TYPE_BOOL32:
  445. {
  446. sstr << "TW_TYPE_BOOL32" << " ";
  447. sstr << *(static_cast<int*>(var));
  448. break;
  449. }
  450. case TW_TYPE_INT32:
  451. {
  452. sstr << "TW_TYPE_INT32" << " ";
  453. sstr << *(static_cast<int*>(var));
  454. break;
  455. }
  456. case TW_TYPE_FLOAT:
  457. {
  458. sstr << "TW_TYPE_FLOAT" << " ";
  459. sstr << *(static_cast<float*>(var));
  460. break;
  461. }
  462. case TW_TYPE_DOUBLE:
  463. {
  464. sstr << "TW_TYPE_DOUBLE" << " ";
  465. sstr << *(static_cast<double*>(var));
  466. break;
  467. }
  468. default:
  469. {
  470. std::map<TwType,std::pair<const char *,std::vector<TwEnumVal> > >::iterator iter =
  471. ReTw_custom_types.find(type);
  472. if(iter != ReTw_custom_types.end())
  473. {
  474. sstr << (*iter).second.first << " ";
  475. int enum_val = *(static_cast<int*>(var));
  476. // try find display name for enum value
  477. std::vector<TwEnumVal>::iterator eit = (*iter).second.second.begin();
  478. bool found = false;
  479. for(;eit<(*iter).second.second.end();eit++)
  480. {
  481. if(enum_val == eit->Value)
  482. {
  483. sstr << eit->Label;
  484. found = true;
  485. break;
  486. }
  487. }
  488. if(!found)
  489. {
  490. sstr << "ERROR_ENUM_VALUE_NOT_DEFINED";
  491. }
  492. }else
  493. {
  494. sstr << "ERROR_TYPE_NOT_SUPPORTED";
  495. }
  496. break;
  497. }
  498. }
  499. return sstr.str();
  500. }
  501. bool igl::ReTwBar::load(const char *file_name)
  502. {
  503. FILE * fp;
  504. fp = fopen(file_name,"r");
  505. if(fp == NULL)
  506. {
  507. printf("ERROR: not able to open %s for reading...\n",file_name);
  508. return false;
  509. }
  510. // go through file line by line
  511. char line[MAX_LINE];
  512. bool still_comments;
  513. char name[MAX_WORD];
  514. char type_str[MAX_WORD];
  515. char value_str[MAX_WORD];
  516. // line number
  517. int j = 0;
  518. bool finished = false;
  519. while(true)
  520. {
  521. // Eat comments
  522. still_comments = true;
  523. while(still_comments)
  524. {
  525. if(fgets(line,MAX_LINE,fp) == NULL)
  526. {
  527. finished = true;
  528. break;
  529. }
  530. // Blank lines and lines that begin with # are comments
  531. still_comments = (line[0] == '#' || line[0] == '\n');
  532. j++;
  533. }
  534. if(finished)
  535. {
  536. break;
  537. }
  538. sscanf(line,"%[^:]: %s %[^\n]",name,type_str,value_str);
  539. //printf("%s: %s %s\n",name, type_str,value_str);
  540. TwType type;
  541. if(!type_from_string(type_str,type))
  542. {
  543. printf("ERROR: %s type not found... Skipping...\n",type_str);
  544. continue;
  545. }
  546. set_value_from_string(name,type,value_str);
  547. }
  548. fclose(fp);
  549. // everything succeeded
  550. return true;
  551. }
  552. bool igl::ReTwBar::type_from_string(const char *type_str, TwType & type)
  553. {
  554. // first check default types
  555. for(int j = 0; j < RETW_NUM_DEFAULT_TYPE_STRINGS; j++)
  556. {
  557. if(strcmp(type_str,ReTwDefaultTypeStrings[j].type_str) == 0)
  558. {
  559. type = ReTwDefaultTypeStrings[j].type;
  560. return true;
  561. break;
  562. }
  563. }
  564. // then check custom types
  565. std::map<TwType,std::pair<const char *,std::vector<TwEnumVal> > >::iterator iter =
  566. ReTw_custom_types.begin();
  567. for(;iter != ReTw_custom_types.end(); iter++)
  568. {
  569. if(strcmp((*iter).second.first,type_str)==0)
  570. {
  571. type = (*iter).first;
  572. return true;
  573. }
  574. }
  575. return false;
  576. }
  577. bool igl::ReTwBar::set_value_from_string(
  578. const char * name,
  579. TwType type,
  580. const char * value_str)
  581. {
  582. void * value = NULL;
  583. // possible value slots
  584. int i;
  585. float v;
  586. double dv;
  587. float f[4];
  588. bool b;
  589. // First try to get value from default types
  590. switch(type)
  591. {
  592. case TW_TYPE_BOOLCPP:
  593. {
  594. int ib;
  595. if(sscanf(value_str," %d",&ib) == 1)
  596. {
  597. b = ib!=0;
  598. value = &b;
  599. }else
  600. {
  601. printf("ERROR: Bad value format...\n");
  602. return false;
  603. }
  604. break;
  605. }
  606. case TW_TYPE_QUAT4F:
  607. case TW_TYPE_COLOR4F:
  608. {
  609. if(sscanf(value_str," %f %f %f %f",&f[0],&f[1],&f[2],&f[3]) == 4)
  610. {
  611. value = &f;
  612. }else
  613. {
  614. printf("ERROR: Bad value format...\n");
  615. return false;
  616. }
  617. break;
  618. }
  619. case TW_TYPE_COLOR3F:
  620. case TW_TYPE_DIR3F:
  621. {
  622. if(sscanf(value_str," %f %f %f",&f[0],&f[1],&f[2]) == 3)
  623. {
  624. value = &f;
  625. }else
  626. {
  627. printf("ERROR: Bad value format...\n");
  628. return false;
  629. }
  630. break;
  631. }
  632. case TW_TYPE_BOOL32:
  633. case TW_TYPE_INT32:
  634. {
  635. if(sscanf(value_str," %d",&i) == 1)
  636. {
  637. value = &i;
  638. }else
  639. {
  640. printf("ERROR: Bad value format...\n");
  641. return false;
  642. }
  643. break;
  644. }
  645. case TW_TYPE_FLOAT:
  646. {
  647. if(sscanf(value_str," %f",&v) == 1)
  648. {
  649. value = &v;
  650. }else
  651. {
  652. printf("ERROR: Bad value format...\n");
  653. return false;
  654. }
  655. break;
  656. }
  657. case TW_TYPE_DOUBLE:
  658. {
  659. if(sscanf(value_str," %lf",&dv) == 1)
  660. {
  661. value = &dv;
  662. }else
  663. {
  664. printf("ERROR: Bad value format...\n");
  665. return false;
  666. }
  667. break;
  668. }
  669. default:
  670. // Try to find type in custom enum types
  671. std::map<TwType,std::pair<const char *,std::vector<TwEnumVal> > >::iterator iter =
  672. ReTw_custom_types.find(type);
  673. if(iter != ReTw_custom_types.end())
  674. {
  675. std::vector<TwEnumVal>::iterator eit = (*iter).second.second.begin();
  676. bool found = false;
  677. for(;eit<(*iter).second.second.end();eit++)
  678. {
  679. if(strcmp(value_str,eit->Label) == 0)
  680. {
  681. i = eit->Value;
  682. value = &i;
  683. found = true;
  684. break;
  685. }
  686. }
  687. if(!found)
  688. {
  689. printf("ERROR_ENUM_VALUE_NOT_DEFINED");
  690. }
  691. }else
  692. {
  693. printf("ERROR_TYPE_NOT_SUPPORTED\n");
  694. }
  695. break;
  696. }
  697. // Find variable based on name
  698. // First look in RW items
  699. bool item_found = false;
  700. for(
  701. std::vector<ReTwRWItem>::iterator it = rw_items.begin();
  702. it != rw_items.end();
  703. it++)
  704. {
  705. if(strcmp(it->name,name) == 0)
  706. {
  707. void * var = it->var;
  708. switch(type)
  709. {
  710. case TW_TYPE_BOOLCPP:
  711. {
  712. bool * bvar = static_cast<bool*>(var);
  713. bool * bvalue = static_cast<bool*>(value);
  714. *bvar = *bvalue;
  715. break;
  716. }
  717. case TW_TYPE_QUAT4F:
  718. case TW_TYPE_COLOR4F:
  719. {
  720. float * fvar = static_cast<float*>(var);
  721. float * fvalue = static_cast<float*>(value);
  722. fvar[0] = fvalue[0];
  723. fvar[1] = fvalue[1];
  724. fvar[2] = fvalue[2];
  725. fvar[3] = fvalue[3];
  726. break;
  727. }
  728. case TW_TYPE_COLOR3F:
  729. case TW_TYPE_DIR3F:
  730. {
  731. float * fvar = static_cast<float*>(var);
  732. float * fvalue = static_cast<float*>(value);
  733. fvar[0] = fvalue[0];
  734. fvar[1] = fvalue[1];
  735. fvar[2] = fvalue[2];
  736. break;
  737. }
  738. case TW_TYPE_BOOL32:
  739. case TW_TYPE_INT32:
  740. {
  741. int * ivar = static_cast<int*>(var);
  742. int * ivalue = static_cast<int*>(value);
  743. *ivar = *ivalue;
  744. break;
  745. }
  746. case TW_TYPE_FLOAT:
  747. {
  748. float * fvar = static_cast<float*>(var);
  749. float * fvalue = static_cast<float*>(value);
  750. *fvar = *fvalue;
  751. break;
  752. }
  753. case TW_TYPE_DOUBLE:
  754. {
  755. double * dvar = static_cast<double*>(var);
  756. double * fvalue = static_cast<double*>(value);
  757. *dvar = *fvalue;
  758. break;
  759. }
  760. default:
  761. // Try to find type in custom enum types
  762. std::map<TwType,std::pair<const char *,std::vector<TwEnumVal> > >::iterator iter =
  763. ReTw_custom_types.find(type);
  764. if(iter != ReTw_custom_types.end())
  765. {
  766. int * ivar = static_cast<int*>(var);
  767. std::vector<TwEnumVal>::iterator eit = (*iter).second.second.begin();
  768. bool found = false;
  769. for(;eit<(*iter).second.second.end();eit++)
  770. {
  771. if(strcmp(value_str,eit->Label) == 0)
  772. {
  773. *ivar = eit->Value;
  774. found = true;
  775. break;
  776. }
  777. }
  778. if(!found)
  779. {
  780. printf("ERROR_ENUM_VALUE_NOT_DEFINED");
  781. }
  782. }else
  783. {
  784. printf("ERROR_TYPE_NOT_SUPPORTED\n");
  785. }
  786. break;
  787. }
  788. item_found = true;
  789. break;
  790. }
  791. }
  792. // Try looking in CB items
  793. if(!item_found)
  794. {
  795. for(
  796. std::vector<ReTwCBItem>::iterator it = cb_items.begin();
  797. it != cb_items.end();
  798. it++)
  799. {
  800. if(strcmp(it->name,name) == 0)
  801. {
  802. it->setCallback(value,it->clientData);
  803. item_found = true;
  804. break;
  805. }
  806. }
  807. }
  808. if(!item_found)
  809. {
  810. printf("ERROR: item not found\n");
  811. }
  812. return true;
  813. }