PageRenderTime 25ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/Core/Dependencies/PhysX-3.2.1_PC_SDK_Core/Samples/SampleBase/SampleConsole.cpp

https://bitbucket.org/barakianc/nvidia-physx-and-apex-in-gge
C++ | 623 lines | 472 code | 76 blank | 75 comment | 80 complexity | f1d37c65975416054543b0a8ff49c6a1 MD5 | raw file
  1. // This code contains NVIDIA Confidential Information and is disclosed to you
  2. // under a form of NVIDIA software license agreement provided separately to you.
  3. //
  4. // Notice
  5. // NVIDIA Corporation and its licensors retain all intellectual property and
  6. // proprietary rights in and to this software and related documentation and
  7. // any modifications thereto. Any use, reproduction, disclosure, or
  8. // distribution of this software and related documentation without an express
  9. // license agreement from NVIDIA Corporation is strictly prohibited.
  10. //
  11. // ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
  12. // NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
  13. // THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
  14. // MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
  15. //
  16. // Information and code furnished is believed to be accurate and reliable.
  17. // However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
  18. // information or for any infringement of patents or other rights of third parties that may
  19. // result from its use. No license is granted by implication or otherwise under any patent
  20. // or patent rights of NVIDIA Corporation. Details are subject to change without notice.
  21. // This code supersedes and replaces all information previously supplied.
  22. // NVIDIA Corporation products are not authorized for use as critical
  23. // components in life support devices or systems without express written approval of
  24. // NVIDIA Corporation.
  25. //
  26. // Copyright (c) 2008-2012 NVIDIA Corporation. All rights reserved.
  27. // Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
  28. // Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
  29. #include <ctype.h>
  30. #include "SamplePreprocessor.h"
  31. #include "SampleConsole.h"
  32. #include "RendererMemoryMacros.h"
  33. #include "Renderer.h"
  34. #include "PsString.h"
  35. #include "SampleBaseInputEventIds.h"
  36. #include <SampleUserInputIds.h>
  37. #include "SampleUserInputDefines.h"
  38. using namespace SampleRenderer;
  39. using namespace SampleFramework;
  40. #define NB_LINES 14
  41. // EXIT: a basic command to hide the console
  42. // Usage: exit
  43. static void BasicCmdexit(Console* console, const char* text, void* user_data)
  44. {
  45. console->setActive(false);
  46. }
  47. // CLS: a basic command to clear the console
  48. // Usage: cls
  49. static void BasicCmdcls(Console* console, const char* text, void* user_data)
  50. {
  51. console->clear();
  52. }
  53. // PROMPT: a basic command to set the prompt
  54. // Usage: prompt [text]
  55. static void BasicCmdSetPrompt(Console* console, const char* text, void* user_data)
  56. {
  57. console->setPrompt(text);
  58. }
  59. // CMDLIST: a basic command to display a list of all possible commands
  60. // Usage: cmdlist <= display all possible commands
  61. // cmdlist [command] <= check whether a command exists or not
  62. static void BasicCmdcmdlist(Console* console, const char* text, void* user_data)
  63. {
  64. ConsoleCommand* pcmd;
  65. if(!text)
  66. {
  67. for(int i=0;i<256;i++)
  68. {
  69. pcmd = console->mCmds[i];
  70. while(pcmd)
  71. {
  72. console->out(pcmd->fullcmd);
  73. pcmd = pcmd->next;
  74. }
  75. }
  76. }
  77. else
  78. {
  79. int i = text[0];
  80. if( (i >= 'A') && (i<='Z') )
  81. i -= 'A' - 'a';
  82. pcmd = console->mCmds[i];
  83. while(pcmd)
  84. {
  85. if(strncmp(pcmd->fullcmd, text, strlen(text)) == 0)
  86. console->out(pcmd->fullcmd);
  87. pcmd = pcmd->next;
  88. }
  89. }
  90. }
  91. // CMDHIST: a basic command to display command history
  92. // Usage: cmdhist
  93. static void BasicCmdcmdhist(Console* console, const char* text, void* user_data)
  94. {
  95. int index = console->mNewcmd - console->mNumcmdhist;
  96. for(int i=0;i<console->mNumcmdhist;i++)
  97. {
  98. if( index > CONSOLE_MAX_HIST )
  99. index -= CONSOLE_MAX_HIST;
  100. console->out(console->mCmdhist[index] );
  101. index++;
  102. }
  103. }
  104. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  105. /**
  106. * Constructor.
  107. */
  108. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  109. Console::Console(SampleFramework::SamplePlatform* plt) :
  110. mViewBottom (0),
  111. mNewline (0),
  112. mIsActive (false),
  113. m_Platform(plt)
  114. {
  115. strcpy(mLastChar, "-");
  116. strcpy(mPrompt, ">");
  117. resetCol();
  118. mNbCmds = 0;
  119. mNewcmd = 0;
  120. mNumcmdhist = 0;
  121. mCurcmd = 0;
  122. mUserData = 0;
  123. for(PxU32 i=0;i<CONSOLE_MAX_COMMAND_NB;i++)
  124. mCmds[i] = NULL;
  125. // Create console
  126. addCmd("exit", BasicCmdexit);
  127. addCmd("cmdlist", BasicCmdcmdlist);
  128. addCmd("cls", BasicCmdcls);
  129. addCmd("cmdhist", BasicCmdcmdhist);
  130. addCmd("prompt", BasicCmdSetPrompt);
  131. clear();
  132. cmdClear();
  133. out("PhysX Samples console");
  134. out("");
  135. out("Type cmdlist to display all possible commands.");
  136. out("Use PageUp / PageDown to scroll the window.");
  137. out("Use arrow keys to recall old commands.");
  138. out("Use ESC to exit.");
  139. out("");
  140. advance();
  141. strcpy(mBuffer[mNewline].mText, mPrompt);
  142. strcat(mBuffer[mNewline].mText, mLastChar);
  143. }
  144. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  145. /**
  146. * Destructor.
  147. */
  148. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  149. Console::~Console()
  150. {
  151. destroy();
  152. }
  153. void Console::resetCol()
  154. {
  155. mCol = (PxI32)strlen(mPrompt);
  156. }
  157. void Console::setPrompt(const char* text)
  158. {
  159. if(!text)
  160. return;
  161. const PxU32 Length = (PxU32)strlen(text);
  162. if(Length>255)
  163. return;
  164. strcpy(mPrompt, text);
  165. }
  166. // Advance the console one line
  167. void Console::advance()
  168. {
  169. mNewline--;
  170. if(mNewline<0)
  171. mNewline += CONSOLE_MAX_ROW;
  172. mBuffer[mNewline].mText[0] = '\0';
  173. mViewBottom = mNewline;
  174. }
  175. // Clear the console text buffer
  176. void Console::clear()
  177. {
  178. for(PxU32 i=0;i<CONSOLE_MAX_ROW;i++)
  179. {
  180. for(PxU32 j=0;j<CONSOLE_MAX_COL;j++)
  181. mBuffer[i].mText[j] = '\0';
  182. mBuffer[i].mColor = RendererColor(255,255,255);
  183. }
  184. mNewline = 0;
  185. mViewBottom = 0;
  186. }
  187. // Clear the console text buffer
  188. void Console::cmdClear()
  189. {
  190. for(PxU32 i=0;i<CONSOLE_MAX_HIST;i++)
  191. for(PxU32 j=0;j<CONSOLE_MAX_COL;j++)
  192. mCmdhist[i][j] = '\0';
  193. mNewcmd = 0;
  194. mNumcmdhist = 0;
  195. mCurcmd = 0;
  196. }
  197. // Write a string to the console
  198. void Console::out(const char* string)
  199. {
  200. advance();
  201. if(string)
  202. {
  203. size_t Length = strlen(string);
  204. if(Length>=CONSOLE_MAX_COL-1)
  205. {
  206. PX_ASSERT(0);
  207. strcpy(mBuffer[mNewline].mText, "CONSOLE LINE TOO LONG!");
  208. }
  209. else
  210. strcpy(mBuffer[mNewline].mText, string);
  211. }
  212. }
  213. // Scroll the console up/down
  214. void Console::scroll(const SampleFramework::InputEvent& ie)
  215. {
  216. if(ie.m_Id== CONSOLE_SCROLL_UP)
  217. {
  218. mViewBottom++;
  219. if(mViewBottom >= CONSOLE_MAX_ROW) mViewBottom -= CONSOLE_MAX_ROW;
  220. if(mViewBottom == mNewline - NB_LINES) mViewBottom--;
  221. }
  222. else if(ie.m_Id== CONSOLE_SCROLL_DOWN)
  223. {
  224. mViewBottom--;
  225. if(mViewBottom < 0) mViewBottom += CONSOLE_MAX_ROW;
  226. if(mViewBottom == mNewline-1) mViewBottom = mNewline;
  227. }
  228. }
  229. // Process an instruction
  230. // called after the user hits enter
  231. void Console::process()
  232. {
  233. // Discard prompt
  234. char cmd[1024];
  235. long Index = (long)strlen(mPrompt);
  236. strcpy(cmd, &mBuffer[mNewline].mText[Index]);
  237. // Keep track of command in history buffer
  238. strcpy(mCmdhist[mNewcmd], cmd);
  239. mNewcmd = mNewcmd++ % CONSOLE_MAX_HIST;
  240. mCurcmd = 0;
  241. mNumcmdhist++;
  242. if(mNumcmdhist>CONSOLE_MAX_HIST) mNumcmdhist = CONSOLE_MAX_HIST;
  243. mBuffer[mNewline].mColor = 0xffeeeeee;
  244. // Extract param and execute command
  245. char* cmdparam;
  246. cmdparam = strchr(cmd, ' ');
  247. if(cmdparam)
  248. {
  249. *cmdparam=0;
  250. cmdparam++;
  251. }
  252. if(!execCmd(cmd, cmdparam))
  253. out("Invalid command");
  254. }
  255. // Called from winmain
  256. // up and down arrow
  257. // for command history
  258. void Console::cmdHistory(const SampleFramework::InputEvent& ie)
  259. {
  260. if(ie.m_Id== CONSOLE_LIST_COMMAND_UP)
  261. {
  262. mCurcmd++;
  263. if( mCurcmd > mNumcmdhist )
  264. mCurcmd = mNumcmdhist;
  265. }
  266. else if(ie.m_Id== CONSOLE_LIST_COMMAND_DOWN)
  267. {
  268. mCurcmd--;
  269. if( mCurcmd <= 0 )
  270. mCurcmd = 0;
  271. }
  272. if( mCurcmd != -1 )
  273. {
  274. char buf[256];
  275. long cmdnum;
  276. strcpy(buf, mPrompt);
  277. cmdnum = mNewcmd - mCurcmd;
  278. if( cmdnum < 0 )
  279. cmdnum += CONSOLE_MAX_HIST;
  280. strcat(buf, mCmdhist[cmdnum]);
  281. strcat(buf, mLastChar);
  282. strcpy(mBuffer[mNewline].mText, buf);
  283. mCol = (PxI32)strlen(buf)-1;
  284. }
  285. }
  286. bool Console::findBestCommand(char* best_command, const char* text, PxU32& tabIndex) const
  287. {
  288. if(!text || !best_command)
  289. return false;
  290. const size_t length = strlen(text);
  291. if(length>1023)
  292. return false;
  293. char tmp[1024];
  294. strcpy(tmp, text);
  295. physx::string::strlwr(tmp);
  296. const char i = tmp[0];
  297. ConsoleCommand* FirstCommand = NULL;
  298. ConsoleCommand* BestCommand = NULL;
  299. ConsoleCommand* pcmd = mCmds[i];
  300. PxU32 currentIndex = 0;
  301. while(pcmd && !BestCommand)
  302. {
  303. char tmp2[1024];
  304. strcpy(tmp2, pcmd->fullcmd);
  305. physx::string::strlwr(tmp2);
  306. if(strncmp(tmp, tmp2, length)== 0)
  307. {
  308. if(!currentIndex)
  309. FirstCommand = pcmd;
  310. if(currentIndex>=tabIndex)
  311. BestCommand = pcmd;
  312. currentIndex++;
  313. }
  314. pcmd = pcmd->next;
  315. }
  316. if(BestCommand)
  317. {
  318. tabIndex++;
  319. strcpy(best_command, BestCommand->fullcmd);
  320. return true;
  321. }
  322. tabIndex = 0;
  323. if(currentIndex && FirstCommand)
  324. {
  325. tabIndex++;
  326. strcpy(best_command, FirstCommand->fullcmd);
  327. return true;
  328. }
  329. return false;
  330. }
  331. // Try to execute a command
  332. bool Console::execCmd(const char* cmd, const char* param)
  333. {
  334. if(!cmd)
  335. return false;
  336. long HashIndex = cmd[0];
  337. HashIndex = tolower(HashIndex);
  338. ConsoleCommand* pcmd = mCmds[HashIndex];
  339. while(pcmd)
  340. {
  341. if(physx::string::stricmp(cmd, pcmd->fullcmd) == 0)
  342. {
  343. pcmd->function(this, param, mUserData);
  344. return true;
  345. }
  346. else pcmd = pcmd->next;
  347. }
  348. return false;
  349. }
  350. // Destroy the console
  351. void Console::destroy()
  352. {
  353. // clean up command list
  354. for(PxU32 i=0;i<256;i++)
  355. {
  356. if(mCmds[i])
  357. {
  358. ConsoleCommand* pcmd = mCmds[i];
  359. while(pcmd)
  360. {
  361. ConsoleCommand* next = pcmd->next;
  362. DELETESINGLE(pcmd);
  363. pcmd = next;
  364. }
  365. }
  366. }
  367. }
  368. // Add a command
  369. void Console::addCmd(const char* full_cmd, void (*function)(Console*, const char *, void*))
  370. {
  371. if(!full_cmd) return; // Command must be defined
  372. if(!function) return; // Function must be defines
  373. if(strlen(full_cmd)>=CONSOLE_MAX_COMMAND_LENGTH) return;
  374. if(mNbCmds==CONSOLE_MAX_COMMAND_NB) return;
  375. mNbCmds++;
  376. long HashIndex = full_cmd[0];
  377. HashIndex = tolower(HashIndex);
  378. ConsoleCommand* pcmd = mCmds[HashIndex];
  379. if(!pcmd)
  380. {
  381. mCmds[HashIndex] = SAMPLE_NEW(ConsoleCommand);
  382. pcmd = mCmds[HashIndex];
  383. }
  384. else
  385. {
  386. while(pcmd->next)
  387. {
  388. pcmd = pcmd->next;
  389. }
  390. pcmd->next = SAMPLE_NEW(ConsoleCommand);
  391. pcmd = pcmd->next;
  392. }
  393. strcpy(pcmd->fullcmd, full_cmd);
  394. pcmd->function = function;
  395. pcmd->next = NULL;
  396. }
  397. bool Console::render(Renderer* rnd)
  398. {
  399. if(!rnd)
  400. return false;
  401. if(!mIsActive)
  402. return true;
  403. const PxU32 NbLines = NB_LINES;
  404. const PxU32 FntHeight = 14;
  405. PxU32 width, height;
  406. rnd->getWindowSize(width, height);
  407. const RendererColor backColor(3, 3, 39);
  408. ScreenQuad sq;
  409. sq.mX0 = 0.0f;
  410. sq.mY0 = 20.0f/float(height);
  411. sq.mX1 = 1.0f;
  412. sq.mY1 = (20.0f + float((NbLines+2)*FntHeight))/float(height);
  413. sq.mLeftUpColor = backColor;
  414. sq.mRightUpColor = backColor;
  415. sq.mLeftDownColor = backColor;
  416. sq.mRightDownColor = backColor;
  417. sq.mAlpha = 0.8f;
  418. rnd->drawScreenQuad(sq);
  419. PxU32 TextY = 24 + NbLines*FntHeight;
  420. const PxReal scale = 0.4f;
  421. const PxReal shadowOffset = 0.0f;
  422. long temp = mViewBottom;
  423. for(PxU32 i=0;i<NbLines;i++)
  424. {
  425. rnd->print(10, TextY, mBuffer[temp].mText, scale, shadowOffset, mBuffer[temp].mColor);
  426. temp = (temp + 1) % CONSOLE_MAX_ROW;
  427. TextY -= FntHeight; //size should come from renderer
  428. }
  429. return true;
  430. }
  431. // Process a single character
  432. static bool gTabMode = false;
  433. static PxU32 gTabIndex = 0;
  434. static char gTabCmd[1024];
  435. void Console::in(PxU32 wparam)
  436. {
  437. if(!mIsActive)
  438. return;
  439. switch(wparam)
  440. {
  441. case 178:
  442. gTabMode = false;
  443. break;
  444. case '\b':
  445. gTabMode = false;
  446. if(mCol>(long)strlen(mPrompt))
  447. {
  448. mBuffer[mNewline].mText[mCol] = '\0';
  449. mBuffer[mNewline].mText[mCol-1] = mLastChar[0];
  450. mCol--;
  451. }
  452. break;
  453. // Return/Enter
  454. case '\n':
  455. case '\r':
  456. gTabMode = false;
  457. mBuffer[mNewline].mText[mCol] = '\0';
  458. process();
  459. advance();
  460. strcpy(mBuffer[mNewline].mText, mPrompt);
  461. strcat(mBuffer[mNewline].mText, mLastChar);
  462. resetCol();
  463. break;
  464. // Tab
  465. case '\t':
  466. {
  467. if(!gTabMode)
  468. {
  469. gTabMode = true;
  470. // Discard last character
  471. mBuffer[mNewline].mText[mCol] = '\0';
  472. // Discard prompt
  473. long Index = (long)strlen(mPrompt);
  474. strcpy(gTabCmd, &mBuffer[mNewline].mText[Index]);
  475. }
  476. char BestCmd[1024];
  477. if(findBestCommand(BestCmd, gTabCmd, gTabIndex))
  478. {
  479. strcpy(mBuffer[mNewline].mText, mPrompt);
  480. strcat(mBuffer[mNewline].mText, BestCmd);
  481. strcat(mBuffer[mNewline].mText, mLastChar);
  482. mCol = PxI32(strlen(mPrompt) + strlen(BestCmd));
  483. }
  484. else
  485. {
  486. gTabMode = false;
  487. mBuffer[mNewline].mText[mCol] = mLastChar[0]; // Append cursor
  488. mBuffer[mNewline].mText[mCol+1] = '\0';
  489. }
  490. }
  491. break;
  492. case '\x1B': // Escape
  493. gTabMode = false;
  494. mCol=0;
  495. mBuffer[mNewline].mText[mCol]=mLastChar[0];
  496. break;
  497. default:
  498. gTabMode = false;
  499. if(mCol >= CONSOLE_MAX_COL-2) // We need 2 extra characters for the cursor and the final 0
  500. break;
  501. mBuffer[mNewline].mText[mCol++] = (char)wparam; // Append new character
  502. mBuffer[mNewline].mText[mCol] = mLastChar[0]; // Append cursor
  503. mBuffer[mNewline].mText[mCol+1] = '\0';
  504. break;
  505. }
  506. }
  507. void Console::collectInputEvents(std::vector<const SampleFramework::InputEvent*>& inputEvents)
  508. {
  509. //digital keyboard events
  510. DIGITAL_INPUT_EVENT_DEF(CONSOLE_ESCAPE, WKEY_ESCAPE, XKEY_ESCAPE, PS3KEY_ESCAPE, AKEY_UNKNOWN, OSXKEY_ESCAPE, PSP2KEY_UNKNOWN, IKEY_UNKNOWN, LINUXKEY_ESCAPE);
  511. DIGITAL_INPUT_EVENT_DEF(CONSOLE_LIST_COMMAND_UP, WKEY_UP, XKEY_UP, PS3KEY_UP, AKEY_UNKNOWN, OSXKEY_UP, PSP2KEY_UNKNOWN, IKEY_UNKNOWN, LINUXKEY_UP);
  512. DIGITAL_INPUT_EVENT_DEF(CONSOLE_LIST_COMMAND_DOWN, WKEY_DOWN, XKEY_DOWN, PS3KEY_DOWN, AKEY_UNKNOWN, OSXKEY_DOWN, PSP2KEY_UNKNOWN, IKEY_UNKNOWN, LINUXKEY_DOWN);
  513. DIGITAL_INPUT_EVENT_DEF(CONSOLE_SCROLL_UP, WKEY_PRIOR, XKEY_PRIOR, PS3KEY_PRIOR, AKEY_UNKNOWN, OSXKEY_PRIOR, PSP2KEY_UNKNOWN, IKEY_UNKNOWN, LINUXKEY_PRIOR);
  514. DIGITAL_INPUT_EVENT_DEF(CONSOLE_SCROLL_DOWN, WKEY_NEXT, XKEY_NEXT, PS3KEY_NEXT, AKEY_UNKNOWN, OSXKEY_NEXT, PSP2KEY_UNKNOWN, IKEY_UNKNOWN, LINUXKEY_NEXT);
  515. }
  516. bool Console::onDigitalInputEvent(const SampleFramework::InputEvent& ie, bool val)
  517. {
  518. if(val)
  519. {
  520. if(ie.m_Id == CONSOLE_LIST_COMMAND_UP || ie.m_Id == CONSOLE_LIST_COMMAND_DOWN)
  521. {
  522. cmdHistory(ie);
  523. return true;
  524. }
  525. else if(ie.m_Id == CONSOLE_SCROLL_UP || ie.m_Id == CONSOLE_SCROLL_DOWN)
  526. {
  527. scroll(ie);
  528. return true;
  529. }
  530. }
  531. else
  532. {
  533. if(ie.m_Id == CONSOLE_ESCAPE)
  534. {
  535. mIsActive = false;
  536. return false;
  537. }
  538. }
  539. return true;
  540. }
  541. void Console::onKeyDown(SampleFramework::SampleUserInput::KeyCode keyCode, PxU32 param)
  542. {
  543. //sschirm doesn't compile on snc
  544. //const int keyparam = (int)param;
  545. if(param)
  546. in(param);
  547. }