PageRenderTime 90ms CodeModel.GetById 58ms RepoModel.GetById 0ms app.codeStats 1ms

/CSExtra/migrated/tags/PRE_EVENT_UNION_REMOVAL/walktestlight/src/command.cpp

#
C++ | 533 lines | 453 code | 25 blank | 55 comment | 154 complexity | 3bcbdbfc392ad37405e32764270a64aa MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, LGPL-2.0
  1. /*
  2. Copyright (C) 1998-2001 by Jorrit Tyberghein
  3. This library is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU Library General Public
  5. License as published by the Free Software Foundation; either
  6. version 2 of the License, or (at your option) any later version.
  7. This library is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  10. Library General Public License for more details.
  11. You should have received a copy of the GNU Library General Public
  12. License along with this library; if not, write to the Free
  13. Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  14. */
  15. /*
  16. * Command processor. There are now several sources of commands:
  17. * the console and the keyboard. This class ignores the sources but
  18. * just executes the commands. The respective source handlers should
  19. * then do whatever they need to recognize the command and send the
  20. * command to this class.
  21. */
  22. #include <string.h>
  23. #include "cssysdef.h"
  24. #include "csver.h"
  25. #include "command.h"
  26. #include "csutil/scanstr.h"
  27. #include "walktest.h"
  28. #include "qint.h"
  29. #include "ivideo/graph3d.h"
  30. #include "ivideo/graph2d.h"
  31. #include "ivaria/conout.h"
  32. #include "iutil/event.h"
  33. #include "iutil/eventq.h"
  34. #include "iutil/objreg.h"
  35. #include "iutil/eventh.h"
  36. #include "iutil/comp.h"
  37. #include "imesh/object.h"
  38. #include "iengine/mesh.h"
  39. #include "ivaria/reporter.h"
  40. #include "iutil/plugin.h"
  41. #if 0
  42. // Static csCommandProcessor variables
  43. iEngine* csCommandProcessor::engine = NULL;
  44. iCamera* csCommandProcessor::camera = NULL;
  45. iGraphics3D* csCommandProcessor::g3d = NULL;
  46. iConsoleOutput* csCommandProcessor::console = NULL;
  47. iObjectRegistry* csCommandProcessor::object_reg = NULL;
  48. csRef<iFile> csCommandProcessor::script;
  49. // Additional command handler
  50. csCommandProcessor::CmdHandler csCommandProcessor::ExtraHandler = NULL;
  51. SCF_IMPLEMENT_IBASE (csCommandProcessor::PerformCallback)
  52. SCF_IMPLEMENTS_INTERFACE (iConsoleExecCallback)
  53. SCF_IMPLEMENT_IBASE_END
  54. void csCommandProcessor::PerformCallback::Execute (const char* command)
  55. {
  56. csCommandProcessor::perform_line (command);
  57. }
  58. void csCommandProcessor::Initialize (iEngine* engine, iCamera* camera,
  59. iGraphics3D* g3d, iConsoleOutput* console, iObjectRegistry* objreg)
  60. {
  61. csCommandProcessor::engine = engine;
  62. csCommandProcessor::camera = camera;
  63. csCommandProcessor::g3d = g3d;
  64. csCommandProcessor::console = console;
  65. csCommandProcessor::object_reg = objreg;
  66. }
  67. bool csCommandProcessor::PerformLine (const char* line)
  68. {
  69. return perform_line (line);
  70. }
  71. static int value_choice (const char* arg, int old_value, const char* const* choices, int num)
  72. {
  73. if (!arg) return -1;
  74. int i = 0;
  75. if (!strcasecmp (arg, "next")) return (old_value+1)%num;
  76. if (!strcasecmp (arg, "prev")) return (old_value-1+num)%num;
  77. while (choices[i])
  78. {
  79. if (!strcasecmp (choices[i], arg)) return i;
  80. i++;
  81. }
  82. Sys->Report (CS_REPORTER_SEVERITY_NOTIFY, "Expected one of the following:");
  83. i = 0;
  84. while (choices[i])
  85. {
  86. Sys->Report (CS_REPORTER_SEVERITY_NOTIFY,
  87. " %s%s", choices[i], i == old_value ? " (current)" : "");
  88. i++;
  89. }
  90. Sys->Report (CS_REPORTER_SEVERITY_NOTIFY, " or 'next' or 'prev'");
  91. return -1;
  92. }
  93. static bool yes_or_no (const char* arg, bool old_value)
  94. {
  95. if (!arg) return false;
  96. if (*arg == '0' && *(arg+1) == 0) return false;
  97. if (*arg == '1' && *(arg+1) == 0) return true;
  98. if (!strcasecmp (arg, "yes") || !strcasecmp (arg, "true") || !strcasecmp (arg, "on")) return true;
  99. if (!strcasecmp (arg, "no") || !strcasecmp (arg, "false") || !strcasecmp (arg, "off")) return false;
  100. if (!strcasecmp (arg, "toggle")) return !old_value;
  101. Sys->Report (CS_REPORTER_SEVERITY_NOTIFY,
  102. "Expected: yes, true, on, 1, no, false, off, 0, or toggle!");
  103. return false;
  104. }
  105. static const char* say_on_or_off (int arg)
  106. {
  107. if (arg) return "on";
  108. return "off";
  109. }
  110. /*
  111. * Standard processing to change/display a boolean value setting.
  112. */
  113. void csCommandProcessor::change_boolean (const char* arg, bool* value, const char* what)
  114. {
  115. if (arg)
  116. {
  117. // Change value
  118. int v = yes_or_no (arg, *value);
  119. if (v != -1)
  120. {
  121. *value = v;
  122. Sys->Report (CS_REPORTER_SEVERITY_NOTIFY,
  123. "Set %s %s", what, say_on_or_off (*value));
  124. }
  125. }
  126. else
  127. {
  128. // Show value
  129. Sys->Report (CS_REPORTER_SEVERITY_NOTIFY,
  130. "Current %s is %s", what, say_on_or_off (*value));
  131. }
  132. }
  133. /*
  134. * Standard processing to change/display a multi-value setting.
  135. */
  136. void csCommandProcessor::change_choice (const char* arg, int* value, const char* what, const char* const* choices, int num)
  137. {
  138. if (arg)
  139. {
  140. // Change value
  141. int v = value_choice (arg, *value, choices, num);
  142. if (v != -1)
  143. {
  144. *value = v;
  145. Sys->Report (CS_REPORTER_SEVERITY_NOTIFY,
  146. "Set %s %s", what, choices[*value]);
  147. }
  148. }
  149. else
  150. {
  151. // Show value
  152. Sys->Report (CS_REPORTER_SEVERITY_NOTIFY,
  153. "Current %s is %s", what, choices[*value]);
  154. }
  155. }
  156. /*
  157. * Standard processing to change/display a floating point setting.
  158. * Return true if value changed.
  159. */
  160. bool csCommandProcessor::change_float (const char* arg, float* value, const char* what, float min, float max)
  161. {
  162. if (arg)
  163. {
  164. // Change value.
  165. float g;
  166. if ((*arg == '+' || *arg == '-') && *(arg+1) == *arg)
  167. {
  168. float dv;
  169. sscanf (arg+1, "%f", &dv);
  170. g = *value+dv;
  171. }
  172. else sscanf (arg, "%f", &g);
  173. if (g < min || g > max) Sys->Report (CS_REPORTER_SEVERITY_NOTIFY,
  174. "Bad value for %s (%f <= value <= %f)!", what, min, max);
  175. else
  176. {
  177. *value = g;
  178. Sys->Report (CS_REPORTER_SEVERITY_NOTIFY,
  179. "Set %s to %f", what, *value);
  180. return true;
  181. }
  182. }
  183. else
  184. {
  185. // Show value.
  186. Sys->Report (CS_REPORTER_SEVERITY_NOTIFY,
  187. "Current %s is %f", what, *value);
  188. }
  189. return false;
  190. }
  191. /*
  192. * Standard processing to change/display an integer setting.
  193. * Return true if value changed.
  194. */
  195. bool csCommandProcessor::change_int (const char* arg, int* value, const char* what, int min, int max)
  196. {
  197. if (arg)
  198. {
  199. // Change value.
  200. int g;
  201. if ((*arg == '+' || *arg == '-') && *(arg+1) == *arg)
  202. {
  203. int dv;
  204. sscanf (arg+1, "%d", &dv);
  205. g = *value+dv;
  206. }
  207. else sscanf (arg, "%d", &g);
  208. if (g < min || g > max)
  209. Sys->Report (CS_REPORTER_SEVERITY_NOTIFY,
  210. "Bad value for %s (%d <= value <= %d)!", what, min, max);
  211. else
  212. {
  213. *value = g;
  214. Sys->Report (CS_REPORTER_SEVERITY_NOTIFY,
  215. "Set %s to %d", what, *value);
  216. return true;
  217. }
  218. }
  219. else
  220. {
  221. // Show value.
  222. Sys->Report (CS_REPORTER_SEVERITY_NOTIFY,
  223. "Current %s is %d", what, *value);
  224. }
  225. return false;
  226. }
  227. /*
  228. * Standard processing to change/display a long setting.
  229. * Return true if value changed.
  230. */
  231. bool csCommandProcessor::change_long (const char* arg, long* value, const char* what, long min, long max)
  232. {
  233. if (arg)
  234. {
  235. // Change value.
  236. long g;
  237. if ((*arg == '+' || *arg == '-') && *(arg+1) == *arg)
  238. {
  239. long dv;
  240. sscanf (arg+1, "%ld", &dv);
  241. g = *value+dv;
  242. }
  243. else sscanf (arg, "%ld", &g);
  244. if (g < min || g > max) Sys->Report (CS_REPORTER_SEVERITY_NOTIFY,
  245. "Bad value for %s (%ld <= value <= %ld)!", what, min, max);
  246. else
  247. {
  248. *value = g;
  249. Sys->Report (CS_REPORTER_SEVERITY_NOTIFY,
  250. "Set %s to %ld", what, *value);
  251. return true;
  252. }
  253. }
  254. else
  255. {
  256. // Show value.
  257. Sys->Report (CS_REPORTER_SEVERITY_NOTIFY,
  258. "Current %s is %ld", what, *value);
  259. }
  260. return false;
  261. }
  262. bool csCommandProcessor::perform_line (const char* line)
  263. {
  264. char cmd[512], arg[255];
  265. if (*line == ';') return true; // Comment
  266. if (*line == 0) return true; // Empty line
  267. strcpy (cmd, line);
  268. char* space = strchr (cmd, ' ');
  269. if (space) { *space = 0; strcpy (arg, space+1); }
  270. else *arg = 0;
  271. return perform (cmd, *arg ? arg : (char*)NULL);
  272. }
  273. extern bool GetConfigOption (iBase* plugin, const char* optName, csVariant& optValue);
  274. extern void SetConfigOption (iBase* plugin, const char* optName, const char* optValue);
  275. extern void SetConfigOption (iBase* plugin, const char* optName, csVariant& optValue);
  276. bool csCommandProcessor::perform (const char* cmd, const char* arg)
  277. {
  278. if (ExtraHandler)
  279. {
  280. static bool inside = false;
  281. if (!inside)
  282. {
  283. inside = true;
  284. bool ret = ExtraHandler (cmd, arg);
  285. inside = false;
  286. if (ret) return true;
  287. }
  288. }
  289. if (!strcasecmp (cmd, "quit"))
  290. {
  291. csRef<iEventQueue> q (CS_QUERY_REGISTRY (object_reg, iEventQueue));
  292. if (q)
  293. q->GetEventOutlet()->Broadcast (cscmdQuit);
  294. }
  295. else if (!strcasecmp (cmd, "help"))
  296. {
  297. Sys->Report (CS_REPORTER_SEVERITY_NOTIFY, "-*- General commands -*-");
  298. Sys->Report (CS_REPORTER_SEVERITY_NOTIFY, " about, version, quit, help");
  299. Sys->Report (CS_REPORTER_SEVERITY_NOTIFY, " debug, db_maxpol, db_procpol");
  300. Sys->Report (CS_REPORTER_SEVERITY_NOTIFY, " console, facenorth, facesouth, faceeast");
  301. Sys->Report (CS_REPORTER_SEVERITY_NOTIFY, " facewest, faceup, facedown, turn, activate");
  302. Sys->Report (CS_REPORTER_SEVERITY_NOTIFY, " cls, exec, dnl, cmessage, dmessage");
  303. Sys->Report (CS_REPORTER_SEVERITY_NOTIFY, " portals, cosfact");
  304. Sys->Report (CS_REPORTER_SEVERITY_NOTIFY, " extension, lod, sprlight, coordset");
  305. }
  306. else if (!strcasecmp (cmd, "about"))
  307. {
  308. Sys->Report (CS_REPORTER_SEVERITY_NOTIFY, "Crystal Space version %s (%s).", CS_VERSION, CS_RELEASE_DATE);
  309. }
  310. else if (!strcasecmp (cmd, "version"))
  311. Sys->Report (CS_REPORTER_SEVERITY_NOTIFY, "%s", CS_VERSION);
  312. else if (!strcasecmp (cmd, "extension"))
  313. {
  314. iGraphics2D* g2d = g3d->GetDriver2D ();
  315. if (!g2d->PerformExtension (arg))
  316. Sys->Report (CS_REPORTER_SEVERITY_NOTIFY, "Extension '%s' not supported!", arg);
  317. }
  318. else if (!strcasecmp (cmd, "db_maxpol"))
  319. {
  320. long val = g3d->GetRenderState (G3DRENDERSTATE_MAXPOLYGONSTODRAW);
  321. int ival = (int)val;
  322. change_int (arg, &ival, "maximum polygons", 0, 2000000000);
  323. g3d->SetRenderState (G3DRENDERSTATE_MAXPOLYGONSTODRAW, (long)ival);
  324. }
  325. else if (!strcasecmp (cmd, "db_procpol"))
  326. {
  327. int val = csEngine::GetMaxProcessPolygons ();
  328. change_int (arg, &val, "maximum process polygons", 0, 2000000000);
  329. csEngine::SetMaxProcessPolygons (val);
  330. }
  331. else if (!strcasecmp (cmd, "cmessage"))
  332. {
  333. if (arg) Sys->Report (CS_REPORTER_SEVERITY_NOTIFY, "%s", arg);
  334. else Sys->Report (CS_REPORTER_SEVERITY_NOTIFY, "Argument expected!");
  335. }
  336. else if (!strcasecmp (cmd, "dmessage"))
  337. {
  338. if (arg) Sys->Report (CS_REPORTER_SEVERITY_DEBUG, "%s", arg);
  339. else Sys->Report (CS_REPORTER_SEVERITY_NOTIFY, "Argument expected!");
  340. }
  341. else if (!strcasecmp (cmd, "cosfact"))
  342. change_float (arg, &csPolyTexture::cfg_cosinus_factor, "cosinus factor", -1, 1);
  343. else if (!strcasecmp (cmd, "lod"))
  344. {
  345. csRef<iPluginManager> plugin_mgr (
  346. CS_QUERY_REGISTRY (object_reg, iPluginManager));
  347. csRef<iMeshObjectType> type (CS_QUERY_PLUGIN_CLASS (plugin_mgr,
  348. "crystalspace.mesh.object.sprite.3d", iMeshObjectType));
  349. csVariant lod_level;
  350. GetConfigOption (type, "sprlod", lod_level);
  351. float f = lod_level.GetFloat ();
  352. change_float (arg, &f, "LOD detail", -1, 1000000);
  353. lod_level.SetFloat (f);
  354. SetConfigOption (type, "sprlod", lod_level);
  355. }
  356. else if (!strcasecmp (cmd, "sprlight"))
  357. {
  358. csRef<iPluginManager> plugin_mgr (
  359. CS_QUERY_REGISTRY (object_reg, iPluginManager));
  360. csRef<iMeshObjectType> type (CS_QUERY_PLUGIN_CLASS (plugin_mgr,
  361. "crystalspace.mesh.object.sprite.3d", iMeshObjectType));
  362. csVariant lqual;
  363. GetConfigOption (type, "sprlq", lqual);
  364. long l = lqual.GetLong ();
  365. change_long (arg, &l, "sprite lighting quality", 0, 3);
  366. lqual.SetLong (l);
  367. SetConfigOption (type, "sprlq", lqual);
  368. }
  369. else if (!strcasecmp (cmd, "dnl"))
  370. Sys->Report (CS_REPORTER_SEVERITY_DEBUG, "");
  371. else if (!strcasecmp (cmd, "exec"))
  372. {
  373. if (arg)
  374. {
  375. if (start_script (arg) && console)
  376. console->SetVisible (true);
  377. }
  378. else Sys->Report (CS_REPORTER_SEVERITY_NOTIFY,
  379. "Please specify the name of the script!");
  380. }
  381. else if (!strcasecmp (cmd, "portals"))
  382. change_boolean (arg, &csSector::do_portals, "portals");
  383. else if (!strcasecmp (cmd, "cls"))
  384. {
  385. if (console)
  386. console->Clear ();
  387. }
  388. else if (!strcasecmp (cmd, "console"))
  389. {
  390. if (console)
  391. {
  392. bool active = console->GetVisible ();
  393. change_boolean (arg, &active, "console");
  394. if (active != console->GetVisible ())
  395. console->SetVisible (active);
  396. }
  397. }
  398. else if (!strcasecmp (cmd, "turn"))
  399. camera->GetTransform ().RotateThis (CS_VEC_ROT_RIGHT, PI);
  400. else if (!strcasecmp (cmd, "activate"))
  401. {
  402. Sys->Report (CS_REPORTER_SEVERITY_NOTIFY, "OBSOLETE");
  403. }
  404. else if (!strcasecmp (cmd, "coordset"))
  405. {
  406. if (!arg)
  407. {
  408. Sys->Report (CS_REPORTER_SEVERITY_NOTIFY, "Expected argument!");
  409. return false;
  410. }
  411. char sect[100];
  412. float x, y, z;
  413. if (csScanStr (arg, "%s,%f,%f,%f", sect, &x, &y, &z) != 4)
  414. {
  415. Sys->Report (CS_REPORTER_SEVERITY_NOTIFY,
  416. "Expected sector,x,y,z. Got something else!");
  417. return false;
  418. }
  419. iSector* s = engine->GetSectors ()->FindByName (sect);
  420. if (!s)
  421. {
  422. Sys->Report (CS_REPORTER_SEVERITY_NOTIFY, "Can't find this sector!");
  423. return false;
  424. }
  425. camera->SetSector (s);
  426. camera->GetTransform ().SetOrigin (csVector3(x,y,z));
  427. }
  428. else if (!strcasecmp (cmd, "facenorth"))
  429. camera->GetTransform ().SetO2T (csMatrix3() /* identity */ );
  430. else if (!strcasecmp (cmd, "facesouth"))
  431. camera->GetTransform ().SetO2T ( csMatrix3 ( -1, 0, 0,
  432. 0, 1, 0,
  433. 0, 0, -1 ) );
  434. else if (!strcasecmp (cmd, "facewest"))
  435. camera->GetTransform ().SetO2T ( csMatrix3 ( 0, 0, 1,
  436. 0, 1, 0,
  437. -1, 0, 0 ) );
  438. else if (!strcasecmp (cmd, "faceeast"))
  439. camera->GetTransform ().SetO2T ( csMatrix3 ( 0, 0, -1,
  440. 0, 1, 0,
  441. 1, 0, 0 ) );
  442. else if (!strcasecmp (cmd, "facedown"))
  443. camera->GetTransform ().SetO2T ( csMatrix3 ( 1, 0, 0,
  444. 0, 0, 1,
  445. 0, -1, 0 ) );
  446. else if (!strcasecmp (cmd, "faceup"))
  447. camera->GetTransform ().SetO2T ( csMatrix3 ( 1, 0, 0,
  448. 0, 0, -1,
  449. 0, 1, 0 ) );
  450. else
  451. {
  452. Sys->Report (CS_REPORTER_SEVERITY_NOTIFY, "Unknown command: `%s'", cmd);
  453. return false;
  454. }
  455. return true;
  456. }
  457. bool csCommandProcessor::start_script (const char* scr)
  458. {
  459. bool ok = false;
  460. csRef<iVFS> v (CS_QUERY_REGISTRY (object_reg, iVFS));
  461. if (v)
  462. {
  463. if (v->Exists (scr))
  464. {
  465. csRef<iFile> f (v->Open (scr, VFS_FILE_READ));
  466. if (!f)
  467. Sys->Report (CS_REPORTER_SEVERITY_NOTIFY,
  468. "Could not open script file '%s'!", scr);
  469. else
  470. {
  471. // Replace possible running script with this one.
  472. script = f;
  473. ok = true;
  474. }
  475. }
  476. }
  477. return ok;
  478. }
  479. bool csCommandProcessor::get_script_line (char* buf, int nbytes)
  480. {
  481. if (!script)
  482. return false;
  483. char c = '\n';
  484. while (c == '\n' || c == '\r')
  485. if (!script->Read(&c, 1))
  486. break;
  487. if (script->AtEOF())
  488. {
  489. script = NULL;
  490. return false;
  491. }
  492. char* p = buf;
  493. const char* plim = p + nbytes - 1;
  494. while (p < plim)
  495. {
  496. if (c == '\n' || c == '\r')
  497. break;
  498. *p++ = c;
  499. if (!script->Read(&c, 1))
  500. break;
  501. }
  502. *p = '\0';
  503. return true;
  504. }
  505. #endif