Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

809 lines
17 KiB

  1. //========= Copyright c 1996-2008, Valve Corporation, All rights reserved. ============//
  2. #include "tier0/platform.h"
  3. #include "tier0/dbg.h"
  4. #include "mathlib/mathlib.h"
  5. #include "mathlib/noise.h"
  6. #include "mathlib/vector.h"
  7. #include "mathlib/expressioncalculator.h"
  8. #include <ctype.h>
  9. // memdbgon must be the last include file in a .cpp file!!!
  10. #include "tier0/memdbgon.h"
  11. //-----------------------------------------------------------------------------
  12. // Parsing helper methods
  13. //-----------------------------------------------------------------------------
  14. bool ParseLiteral( const char *&expr, float &value )
  15. {
  16. const char *startExpr = expr;
  17. value = ( float )strtod( startExpr, const_cast< char** >( &expr ) );
  18. return ( startExpr != expr );
  19. }
  20. bool ParseString( const char *&expr, const char *str )
  21. {
  22. const char *startExpr = expr;
  23. while ( ( *expr == ' ' ) || ( *expr == '\t' ) )
  24. expr++; // skip whitespace
  25. expr = StringAfterPrefix( expr, str );
  26. if ( expr )
  27. return true;
  28. expr = startExpr;
  29. return false;
  30. }
  31. bool ParseStringList( const char *&expr, const char **pOps, int &nOp )
  32. {
  33. while ( nOp-- )
  34. {
  35. if ( ParseString( expr, pOps[ nOp ] ) )
  36. return true;
  37. }
  38. return false;
  39. }
  40. bool ParseStringList( const char *&expr, const CUtlVector< CUtlString > &strings, int &nOp )
  41. {
  42. while ( nOp-- )
  43. {
  44. if ( ParseString( expr, strings[ nOp ] ) )
  45. return true;
  46. }
  47. return false;
  48. }
  49. int FindString( const CUtlVector< CUtlString > &strings, const char *str )
  50. {
  51. uint sn = strings.Count();
  52. for ( uint si = 0; si < sn; ++si )
  53. {
  54. if ( !Q_strcmp( str, strings[ si ] ) )
  55. return si;
  56. }
  57. return -1;
  58. }
  59. class ParseState_t
  60. {
  61. public:
  62. ParseState_t( const CUtlStack<float> &stack, const char *expr )
  63. : m_stacksize( stack.Count() ), m_startingExpr( expr ) {}
  64. void Reset( CUtlStack<float> &stack, const char *&expr )
  65. {
  66. Assert( m_stacksize <= stack.Count() );
  67. stack.PopMultiple( stack.Count() - m_stacksize );
  68. expr = m_startingExpr;
  69. }
  70. private:
  71. int m_stacksize;
  72. const char* m_startingExpr;
  73. };
  74. void CExpressionCalculator::SetVariable( int nVariableIndex, float value )
  75. {
  76. m_varValues[ nVariableIndex ] = value;
  77. }
  78. void CExpressionCalculator::SetVariable( const char *var, float value )
  79. {
  80. int vi = FindString( m_varNames, var );
  81. if ( vi >= 0 )
  82. {
  83. m_varValues[ vi ] = value;
  84. }
  85. else
  86. {
  87. m_varNames.AddToTail( var );
  88. m_varValues.AddToTail( value );
  89. }
  90. }
  91. void CExpressionCalculator::ModifyVariable( const char *var, float value )
  92. {
  93. int vi = FindString( m_varNames, var );
  94. if ( vi >= 0 )
  95. {
  96. m_varValues[ vi ] += value;
  97. }
  98. else
  99. {
  100. SetVariable( var, value );
  101. }
  102. }
  103. int CExpressionCalculator::FindVariableIndex( const char *var )
  104. {
  105. return FindString( m_varNames, var );
  106. }
  107. bool CExpressionCalculator::Evaluate( float &value )
  108. {
  109. m_bIsBuildingArgumentList = false;
  110. m_stack.PopMultiple( m_stack.Count() );
  111. const char *pExpr = m_expr.Get();
  112. bool success = ParseExpr( pExpr );
  113. if ( success && m_stack.Count() == 1 )
  114. {
  115. value = m_stack.Top();
  116. return true;
  117. }
  118. value = 0.0f;
  119. return false;
  120. }
  121. //-----------------------------------------------------------------------------
  122. // Builds a list of variable names from the expression
  123. //-----------------------------------------------------------------------------
  124. bool CExpressionCalculator::BuildVariableListFromExpression( )
  125. {
  126. m_bIsBuildingArgumentList = true;
  127. m_stack.PopMultiple( m_stack.Count() );
  128. const char *pExpr = m_expr.Get();
  129. bool bSuccess = ParseExpr( pExpr );
  130. m_bIsBuildingArgumentList = false;
  131. if ( !bSuccess || m_stack.Count() != 1 )
  132. {
  133. m_varNames.RemoveAll();
  134. return false;
  135. }
  136. return true;
  137. }
  138. //-----------------------------------------------------------------------------
  139. // Iterate over variables
  140. //-----------------------------------------------------------------------------
  141. int CExpressionCalculator::VariableCount()
  142. {
  143. return m_varNames.Count();
  144. }
  145. const char *CExpressionCalculator::VariableName( int nIndex )
  146. {
  147. return m_varNames[nIndex];
  148. }
  149. bool CExpressionCalculator::ParseExpr( const char *&expr )
  150. {
  151. return ( expr != NULL ) && ParseConditional( expr );
  152. }
  153. bool CExpressionCalculator::ParseConditional( const char *&expr )
  154. {
  155. ParseState_t ps0( m_stack, expr );
  156. if ( !ParseOr( expr ) )
  157. {
  158. ps0.Reset( m_stack, expr );
  159. return false; // nothing matched
  160. }
  161. ParseState_t ps1( m_stack, expr );
  162. if ( ParseString( expr, "?" ) &&
  163. ParseExpr( expr ) &&
  164. ParseString( expr, ":" ) &&
  165. ParseExpr( expr ) )
  166. {
  167. float f3 = m_stack.Top();
  168. m_stack.Pop();
  169. float f2 = m_stack.Top();
  170. m_stack.Pop();
  171. float f1 = m_stack.Top();
  172. m_stack.Pop();
  173. m_stack.Push( f1 != 0.0f ? f2 : f3 );
  174. return true; // and matched
  175. }
  176. ps1.Reset( m_stack, expr );
  177. return true; // equality (or lower) matched
  178. }
  179. bool CExpressionCalculator::ParseOr( const char *&expr )
  180. {
  181. ParseState_t ps0( m_stack, expr );
  182. if ( !ParseAnd( expr ) )
  183. {
  184. ps0.Reset( m_stack, expr );
  185. return false; // nothing matched
  186. }
  187. ParseState_t ps1( m_stack, expr );
  188. if ( ParseString( expr, "||" ) &&
  189. ParseOr( expr ) )
  190. {
  191. float f2 = m_stack.Top();
  192. m_stack.Pop();
  193. float f1 = m_stack.Top();
  194. m_stack.Pop();
  195. m_stack.Push( ( f1 != 0.0f ) || ( f2 != 0.0f ) ? 1 : 0 );
  196. return true; // and matched
  197. }
  198. ps1.Reset( m_stack, expr );
  199. return true; // equality (or lower) matched
  200. }
  201. bool CExpressionCalculator::ParseAnd( const char *&expr )
  202. {
  203. ParseState_t ps0( m_stack, expr );
  204. if ( !ParseEquality( expr ) )
  205. {
  206. ps0.Reset( m_stack, expr );
  207. return false; // nothing matched
  208. }
  209. ParseState_t ps1( m_stack, expr );
  210. if ( ParseString( expr, "&&" ) &&
  211. ParseAnd( expr ) )
  212. {
  213. float f2 = m_stack.Top();
  214. m_stack.Pop();
  215. float f1 = m_stack.Top();
  216. m_stack.Pop();
  217. m_stack.Push( ( f1 != 0.0f ) && ( f2 != 0.0f ) ? 1 : 0 );
  218. return true; // and matched
  219. }
  220. ps1.Reset( m_stack, expr );
  221. return true; // equality (or lower) matched
  222. }
  223. bool CExpressionCalculator::ParseEquality( const char *&expr )
  224. {
  225. ParseState_t ps0( m_stack, expr );
  226. if ( !ParseLessGreater( expr ) )
  227. {
  228. ps0.Reset( m_stack, expr );
  229. return false; // nothing matched
  230. }
  231. const char *pOps[] = { "==", "!=" };
  232. int nOp = 2;
  233. ParseState_t ps1( m_stack, expr );
  234. if ( ParseStringList( expr, pOps, nOp ) &&
  235. ParseEquality( expr ) )
  236. {
  237. float f2 = m_stack.Top();
  238. m_stack.Pop();
  239. float f1 = m_stack.Top();
  240. m_stack.Pop();
  241. switch ( nOp )
  242. {
  243. case 0: // ==
  244. m_stack.Push( f1 == f2 ? 1 : 0 );
  245. break;
  246. case 1: // !=
  247. m_stack.Push( f1 != f2 ? 1 : 0 );
  248. break;
  249. }
  250. return true; // equality matched
  251. }
  252. ps1.Reset( m_stack, expr );
  253. return true; // lessgreater (or lower) matched
  254. }
  255. bool CExpressionCalculator::ParseLessGreater( const char *&expr )
  256. {
  257. ParseState_t ps0( m_stack, expr );
  258. if ( !ParseAddSub( expr ) )
  259. {
  260. ps0.Reset( m_stack, expr );
  261. return false; // nothing matched
  262. }
  263. const char *pOps[] = { "<", ">", "<=", ">=" };
  264. int nOp = 4;
  265. ParseState_t ps1( m_stack, expr );
  266. if ( ParseStringList( expr, pOps, nOp ) &&
  267. ParseLessGreater( expr ) )
  268. {
  269. float f2 = m_stack.Top();
  270. m_stack.Pop();
  271. float f1 = m_stack.Top();
  272. m_stack.Pop();
  273. switch ( nOp )
  274. {
  275. case 0: // <
  276. m_stack.Push( f1 < f2 ? 1 : 0 );
  277. break;
  278. case 1: // >
  279. m_stack.Push( f1 > f2 ? 1 : 0 );
  280. break;
  281. case 2: // <=
  282. m_stack.Push( f1 <= f2 ? 1 : 0 );
  283. break;
  284. case 3: // >=
  285. m_stack.Push( f1 >= f2 ? 1 : 0 );
  286. break;
  287. }
  288. return true; // inequality matched
  289. }
  290. ps1.Reset( m_stack, expr );
  291. return true; // addsub (or lower) matched
  292. }
  293. bool CExpressionCalculator::ParseAddSub( const char *&expr )
  294. {
  295. ParseState_t ps0( m_stack, expr );
  296. if ( !ParseDivMul( expr ) )
  297. {
  298. ps0.Reset( m_stack, expr );
  299. return false; // nothing matched
  300. }
  301. const char *pOps[] = { "+", "-" };
  302. int nOp = 2;
  303. ParseState_t ps1( m_stack, expr );
  304. if ( ParseStringList( expr, pOps, nOp ) &&
  305. ParseAddSub( expr ) )
  306. {
  307. float f2 = m_stack.Top();
  308. m_stack.Pop();
  309. float f1 = m_stack.Top();
  310. m_stack.Pop();
  311. switch ( nOp )
  312. {
  313. case 0: // +
  314. m_stack.Push( f1 + f2 );
  315. break;
  316. case 1: // -
  317. m_stack.Push( f1 - f2 );
  318. break;
  319. }
  320. return true; // addsub matched
  321. }
  322. ps1.Reset( m_stack, expr );
  323. return true; // divmul (or lower) matched
  324. }
  325. bool CExpressionCalculator::ParseDivMul( const char *&expr )
  326. {
  327. ParseState_t ps0( m_stack, expr );
  328. if ( !ParseUnary( expr ) )
  329. {
  330. ps0.Reset( m_stack, expr );
  331. return false; // nothing matched
  332. }
  333. const char *pOps[] = { "*", "/", "%" };
  334. int nOp = 3;
  335. ParseState_t ps1( m_stack, expr );
  336. if ( ParseStringList( expr, pOps, nOp ) &&
  337. ParseDivMul( expr ) )
  338. {
  339. float f2 = m_stack.Top();
  340. m_stack.Pop();
  341. float f1 = m_stack.Top();
  342. m_stack.Pop();
  343. switch ( nOp )
  344. {
  345. case 0: // *
  346. m_stack.Push( f1 * f2 );
  347. break;
  348. case 1: // /
  349. m_stack.Push( f1 / f2 );
  350. break;
  351. case 2: // %
  352. m_stack.Push( fmod( f1, f2 ) );
  353. break;
  354. }
  355. return true; // divmul matched
  356. }
  357. ps1.Reset( m_stack, expr );
  358. return true; // unary (or lower) matched
  359. }
  360. bool CExpressionCalculator::ParseUnary( const char *&expr )
  361. {
  362. ParseState_t ps( m_stack, expr );
  363. const char *pOps[] = { "+", "-", "!" };
  364. int nOp = 3;
  365. if ( ParseStringList( expr, pOps, nOp ) &&
  366. ParseUnary( expr ) )
  367. {
  368. float f1 = m_stack.Top();
  369. m_stack.Pop();
  370. switch ( nOp )
  371. {
  372. case 0: // +
  373. m_stack.Push( f1 );
  374. break;
  375. case 1: // -
  376. m_stack.Push( -f1 );
  377. break;
  378. case 2: // !
  379. m_stack.Push( f1 == 0 ? 1 : 0 );
  380. break;
  381. }
  382. return true;
  383. }
  384. ps.Reset( m_stack, expr );
  385. if ( ParsePrimary( expr ) )
  386. return true;
  387. ps.Reset( m_stack, expr );
  388. return false;
  389. }
  390. bool CExpressionCalculator::ParsePrimary( const char *&expr )
  391. {
  392. ParseState_t ps( m_stack, expr );
  393. float value = 0.0f;
  394. if ( ParseLiteral( expr, value ) )
  395. {
  396. m_stack.Push( value );
  397. return true;
  398. }
  399. ps.Reset( m_stack, expr );
  400. int nVar = m_varNames.Count();
  401. if ( ParseStringList( expr, m_varNames, nVar) )
  402. {
  403. m_stack.Push( m_varValues[ nVar ] );
  404. return true;
  405. }
  406. ps.Reset( m_stack, expr );
  407. if ( ParseString( expr, "(" ) &&
  408. ParseExpr( expr ) &&
  409. ParseString( expr, ")" ) )
  410. {
  411. return true;
  412. }
  413. ps.Reset( m_stack, expr );
  414. if ( Parse1ArgFunc( expr ) ||
  415. Parse2ArgFunc( expr ) ||
  416. Parse3ArgFunc( expr ) ||
  417. // Parse4ArgFunc( expr ) ||
  418. Parse5ArgFunc( expr ) )
  419. {
  420. return true;
  421. }
  422. // If we're parsing it to discover names of variable names, add them here
  423. if ( !m_bIsBuildingArgumentList )
  424. return false;
  425. // Variables can't start with a number
  426. if ( V_isdigit( *expr ) )
  427. return false;
  428. const char *pStart = expr;
  429. while ( V_isalnum( *expr ) || *expr == '_' )
  430. {
  431. ++expr;
  432. }
  433. size_t nLen = (size_t)expr - (size_t)pStart;
  434. char *pVariableName = (char*)stackalloc( nLen+1 );
  435. memcpy( pVariableName, pStart, nLen );
  436. pVariableName[nLen] = 0;
  437. SetVariable( pVariableName, 0.0f );
  438. m_stack.Push( 0.0f );
  439. return true;
  440. }
  441. /*
  442. dtor(d) : converts degrees to radians
  443. rtod(r) : converts radians to degrees
  444. abs(a) : absolute value
  445. floor(a) : rounds down to the nearest integer
  446. ceiling(a) : rounds up to the nearest integer
  447. round(a) : rounds to the nearest integer
  448. sgn(a) : if a < 0 returns -1 else 1
  449. sqr(a) : returns a * a
  450. sqrt(a) : returns sqrt(a)
  451. sin(a) : sin(a), a is in degrees
  452. asin(a) : asin(a) returns degrees
  453. cos(a) : cos(a), a is in degrees
  454. acos(a) : acos(a) returns degrees
  455. tan(a) : tan(a), a is in degrees
  456. exp(a) : returns the exponential function of a
  457. log(a) : returns the natural logaritm of a
  458. */
  459. bool CExpressionCalculator::Parse1ArgFunc( const char *&expr )
  460. {
  461. ParseState_t ps( m_stack, expr );
  462. const char *pFuncs[] =
  463. {
  464. "abs", "sqr", "sqrt", "sin", "asin", "cos", "acos", "tan",
  465. "exp", "log", "dtor", "rtod", "floor", "ceiling", "round", "sign"
  466. };
  467. int nFunc = 16;
  468. if ( ParseStringList( expr, pFuncs, nFunc ) &&
  469. ParseString( expr, "(" ) &&
  470. ParseExpr( expr ) &&
  471. ParseString( expr, ")" ) )
  472. {
  473. float f1 = m_stack.Top();
  474. m_stack.Pop();
  475. switch ( nFunc )
  476. {
  477. case 0: // abs
  478. m_stack.Push( fabs( f1 ) );
  479. break;
  480. case 1: // sqr
  481. m_stack.Push( f1 * f1 );
  482. break;
  483. case 2: // sqrt
  484. m_stack.Push( sqrt( f1 ) );
  485. break;
  486. case 3: // sin
  487. m_stack.Push( sin( f1 ) );
  488. break;
  489. case 4: // asin
  490. m_stack.Push( asin( f1 ) );
  491. break;
  492. case 5: // cos
  493. m_stack.Push( cos( f1 ) );
  494. break;
  495. case 6: // acos
  496. m_stack.Push( acos( f1 ) );
  497. break;
  498. case 7: // tan
  499. m_stack.Push( tan( f1 ) );
  500. break;
  501. case 8: // exp
  502. m_stack.Push( exp( f1 ) );
  503. break;
  504. case 9: // log
  505. m_stack.Push( log( f1 ) );
  506. break;
  507. case 10: // dtor
  508. m_stack.Push( DEG2RAD( f1 ) );
  509. break;
  510. case 11: // rtod
  511. m_stack.Push( RAD2DEG( f1 ) );
  512. break;
  513. case 12: // floor
  514. m_stack.Push( floor( f1 ) );
  515. break;
  516. case 13: // ceiling
  517. m_stack.Push( ceil( f1 ) );
  518. break;
  519. case 14: // round
  520. m_stack.Push( floor( f1 + 0.5f ) );
  521. break;
  522. case 15: // sign
  523. m_stack.Push( f1 >= 0.0f ? 1.0f : -1.0f );
  524. break;
  525. }
  526. return true;
  527. }
  528. return false;
  529. }
  530. /*
  531. min(a,b) : if a<b returns a else b
  532. max(a,b) : if a>b returns a else b
  533. atan2(a,b) : atan2(a/b) returns degrees
  534. pow(a,b) : function returns a raised to the power of b
  535. */
  536. bool CExpressionCalculator::Parse2ArgFunc( const char *&expr )
  537. {
  538. ParseState_t ps( m_stack, expr );
  539. const char *pFuncs[] = { "min", "max", "atan2", "pow" };
  540. int nFunc = 4;
  541. if ( ParseStringList( expr, pFuncs, nFunc ) &&
  542. ParseString( expr, "(" ) &&
  543. ParseExpr( expr ) &&
  544. ParseString( expr, "," ) &&
  545. ParseExpr( expr ) &&
  546. ParseString( expr, ")" ) )
  547. {
  548. float f2 = m_stack.Top();
  549. m_stack.Pop();
  550. float f1 = m_stack.Top();
  551. m_stack.Pop();
  552. switch ( nFunc )
  553. {
  554. case 0: // min
  555. m_stack.Push( MIN( f1, f2 ) );
  556. break;
  557. case 1: // max
  558. m_stack.Push( MAX( f1, f2 ) );
  559. break;
  560. case 2: // atan2
  561. m_stack.Push( atan2( f1, f2 ) );
  562. break;
  563. case 3: // pow
  564. m_stack.Push( pow( f1, f2 ) );
  565. break;
  566. }
  567. return true;
  568. }
  569. return false;
  570. }
  571. /*
  572. inrange(x,a,b) : if x is between a and b, returns 1 else returns 0
  573. clamp(x,a,b) : see bound() above
  574. ramp(value,a,b) : returns 0 -> 1 as value goes from a to b
  575. lerp(factor,a,b) : returns a -> b as value goes from 0 to 1
  576. cramp(value,a,b) : clamp(ramp(value,a,b),0,1)
  577. clerp(factor,a,b) : clamp(lerp(factor,a,b),a,b)
  578. elerp(x,a,b) : ramp( 3*x*x - 2*x*x*x, a, b)
  579. //elerp(factor,a,b) : lerp(lerp(sind(clerp(factor,-90,90)),0.5,1.0),a,b)
  580. noise(a,b,c) : { solid noise pattern (improved perlin noise) indexed with three numbers }
  581. */
  582. float ramp( float x, float a, float b )
  583. {
  584. return ( x - a ) / ( b - a );
  585. }
  586. float lerp( float x, float a, float b )
  587. {
  588. return a + x * ( b - a );
  589. }
  590. float smoothstep( float x )
  591. {
  592. return 3*x*x - 2*x*x*x;
  593. }
  594. bool CExpressionCalculator::Parse3ArgFunc( const char *&expr )
  595. {
  596. ParseState_t ps( m_stack, expr );
  597. const char *pFuncs[] = { "inrange", "clamp", "ramp", "lerp", "cramp", "clerp", "elerp", "noise" };
  598. int nFunc = 8;
  599. if ( ParseStringList( expr, pFuncs, nFunc ) &&
  600. ParseString( expr, "(" ) &&
  601. ParseExpr( expr ) &&
  602. ParseString( expr, "," ) &&
  603. ParseExpr( expr ) &&
  604. ParseString( expr, "," ) &&
  605. ParseExpr( expr ) &&
  606. ParseString( expr, ")" ) )
  607. {
  608. float f3 = m_stack.Top();
  609. m_stack.Pop();
  610. float f2 = m_stack.Top();
  611. m_stack.Pop();
  612. float f1 = m_stack.Top();
  613. m_stack.Pop();
  614. switch ( nFunc )
  615. {
  616. case 0: // inrange
  617. m_stack.Push( ( f1 >= f2 ) && ( f1 <= f3 ) ? 1.0f : 0.0f );
  618. break;
  619. case 1: // clamp
  620. m_stack.Push( clamp( f1, f2, f3 ) );
  621. break;
  622. case 2: // ramp
  623. m_stack.Push( ramp( f1, f2, f3 ) );
  624. break;
  625. case 3: // lerp
  626. m_stack.Push( lerp( f1, f2, f3 ) );
  627. break;
  628. case 4: // cramp
  629. m_stack.Push( clamp( ramp( f1, f2, f3 ), 0, 1 ) );
  630. break;
  631. case 5: // clerp
  632. m_stack.Push( clamp( lerp( f1, f2, f3 ), f2, f3 ) );
  633. break;
  634. case 6: // elerp
  635. m_stack.Push( lerp( smoothstep( f1 ), f2, f3 ) );
  636. break;
  637. case 7: // noise
  638. m_stack.Push( ImprovedPerlinNoise( Vector( f1, f2, f3 ) ) );
  639. break;
  640. }
  641. return true;
  642. }
  643. return false;
  644. }
  645. //bool CExpressionCalculator::Parse4ArgFunc( const char *&expr );
  646. /*
  647. rescale (X,Xa,Xb,Ya,Yb) : lerp(ramp(X,Xa,Xb),Ya,Yb)
  648. crescale(X,Xa,Xb,Ya,Yb) : clamp(rescale(X,Xa,Xb,Ya,Yb),Ya,Yb)
  649. */
  650. float rescale( float x, float a, float b, float c, float d )
  651. {
  652. return lerp( ramp( x, a, b ), c, d );
  653. }
  654. bool CExpressionCalculator::Parse5ArgFunc( const char *&expr )
  655. {
  656. ParseState_t ps( m_stack, expr );
  657. const char *pFuncs[] = { "rescale", "crescale" };
  658. int nFunc = 2;
  659. if ( ParseStringList( expr, pFuncs, nFunc ) &&
  660. ParseString( expr, "(" ) &&
  661. ParseExpr( expr ) &&
  662. ParseString( expr, "," ) &&
  663. ParseExpr( expr ) &&
  664. ParseString( expr, "," ) &&
  665. ParseExpr( expr ) &&
  666. ParseString( expr, "," ) &&
  667. ParseExpr( expr ) &&
  668. ParseString( expr, "," ) &&
  669. ParseExpr( expr ) &&
  670. ParseString( expr, ")" ) )
  671. {
  672. float f5 = m_stack.Top();
  673. m_stack.Pop();
  674. float f4 = m_stack.Top();
  675. m_stack.Pop();
  676. float f3 = m_stack.Top();
  677. m_stack.Pop();
  678. float f2 = m_stack.Top();
  679. m_stack.Pop();
  680. float f1 = m_stack.Top();
  681. m_stack.Pop();
  682. switch ( nFunc )
  683. {
  684. case 0: // rescale
  685. m_stack.Push( rescale( f1, f2, f3, f4, f5 ) );
  686. break;
  687. case 1: // crescale
  688. m_stack.Push( clamp( rescale( f1, f2, f3, f4, f5 ), f4, f5 ) );
  689. break;
  690. }
  691. return true;
  692. }
  693. return false;
  694. }
  695. CExpressionCalculator::CExpressionCalculator( const CExpressionCalculator& x )
  696. {
  697. *this = x;
  698. }
  699. CExpressionCalculator& CExpressionCalculator::operator=( const CExpressionCalculator& x )
  700. {
  701. m_expr = x.m_expr;
  702. m_varNames = x.m_varNames;
  703. m_varValues = x.m_varValues;
  704. m_stack.CopyFrom( x.m_stack );
  705. m_bIsBuildingArgumentList = x.m_bIsBuildingArgumentList;
  706. return *this;
  707. }
  708. float EvaluateExpression( char const *pExpr, float flValueToReturnIfFailure )
  709. {
  710. CExpressionCalculator myEvaluator( pExpr );
  711. float flResult;
  712. bool bSuccess = myEvaluator.Evaluate( flResult );
  713. return ( bSuccess ) ? flResult : flValueToReturnIfFailure;
  714. }