Browse Source

Merge pull request #1532 from GarageGames/pr/1143

[CLONE] More consolefunctions #1143
Anis 9 years ago
parent
commit
794f1b9536

+ 20 - 0
Engine/source/app/game.cpp

@@ -202,6 +202,26 @@ DefineConsoleFunction( getRealTime, S32, (), , "()"
    return Platform::getRealMilliseconds();
    return Platform::getRealMilliseconds();
 }
 }
 
 
+ConsoleFunction( getLocalTime, const char *, 1, 1, "Return the current local time as: weekday month day year hour min sec.\n\n"
+                "Local time is platform defined.")
+{
+   Platform::LocalTime lt;
+   Platform::getLocalTime(lt);
+
+   static const U32 bufSize = 128;
+   char *retBuffer = Con::getReturnBuffer(bufSize);
+   dSprintf(retBuffer, bufSize, "%d %d %d %d %02d %02d %02d",
+      lt.weekday,
+      lt.month + 1,
+      lt.monthday,
+      lt.year + 1900,
+      lt.hour,
+      lt.min,
+      lt.sec);
+
+   return retBuffer;
+}
+
 ConsoleFunctionGroupEnd(Platform);
 ConsoleFunctionGroupEnd(Platform);
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------

+ 472 - 0
Engine/source/console/consoleFunctions.cpp

@@ -25,6 +25,11 @@
 #include "console/consoleInternal.h"
 #include "console/consoleInternal.h"
 #include "console/engineAPI.h"
 #include "console/engineAPI.h"
 #include "console/ast.h"
 #include "console/ast.h"
+
+#ifndef _CONSOLFUNCTIONS_H_
+#include "console/consoleFunctions.h"
+#endif
+
 #include "core/strings/findMatch.h"
 #include "core/strings/findMatch.h"
 #include "core/strings/stringUnit.h"
 #include "core/strings/stringUnit.h"
 #include "core/strings/unicode.h"
 #include "core/strings/unicode.h"
@@ -32,6 +37,7 @@
 #include "console/compiler.h"
 #include "console/compiler.h"
 #include "platform/platformInput.h"
 #include "platform/platformInput.h"
 #include "core/util/journal/journal.h"
 #include "core/util/journal/journal.h"
+#include "gfx/gfxEnums.h"
 #include "core/util/uuid.h"
 #include "core/util/uuid.h"
 
 
 // This is a temporary hack to get tools using the library to
 // This is a temporary hack to get tools using the library to
@@ -41,6 +47,132 @@ bool LinkConsoleFunctions = false;
 // Buffer for expanding script filenames.
 // Buffer for expanding script filenames.
 static char scriptFilenameBuffer[1024];
 static char scriptFilenameBuffer[1024];
 
 
+bool isInt(const char* str)
+{
+   int len = dStrlen(str);
+   if(len <= 0)
+      return false;
+
+   // Ignore whitespace
+   int start = 0;
+   for(int i = start; i < len; i++)
+      if(str[i] != ' ')
+      {
+         start = i;
+         break;
+      }
+
+      for(int i = start; i < len; i++)
+         switch(str[i])
+      {
+         case '+': case '-':
+            if(i != 0)
+               return false;
+            break;
+         case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '0': 
+            break;
+         case ' ': // ignore whitespace
+            for(int j = i+1; j < len; j++)
+               if(str[j] != ' ')
+                  return false;
+            return true;
+            break;
+         default:
+            return false;
+      }
+      return true;
+}
+
+bool isFloat(const char* str, bool sciOk = false)
+{
+   int len = dStrlen(str);
+   if(len <= 0)
+      return false;
+
+   // Ingore whitespace
+   int start = 0;
+   for(int i = start; i < len; i++)
+      if(str[i] != ' ')
+      {
+         start = i;
+         break;
+      }
+
+      bool seenDot = false;
+      int eLoc = -1;
+      for(int i = 0; i < len; i++)
+         switch(str[i])
+      {
+         case '+': case '-':
+            if(sciOk)
+            {
+               //Haven't found e or scientific notation symbol
+               if(eLoc == -1)
+               {
+                  //only allowed in beginning
+                  if(i != 0)
+                     return false;
+               }
+               else
+               {
+                  //if not right after the e
+                  if(i != (eLoc + 1))
+                     return false;
+               }
+            }
+            else
+            {
+               //only allowed in beginning
+               if(i != 0)
+                  return false;
+            }
+            break;
+         case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '0': 
+            break;
+         case 'e': case 'E':
+            if(!sciOk)
+               return false;
+            else
+            {
+               //already saw it so can't have 2
+               if(eLoc != -1)
+                  return false;
+
+               eLoc = i;
+            }
+            break;
+         case '.':
+            if(seenDot | (sciOk && eLoc != -1))
+               return false;
+            seenDot = true;
+            break;
+         case ' ': // ignore whitespace
+            for(int j = i+1; j < len; j++)
+               if(str[j] != ' ')
+                  return false;
+            return true;
+            break;
+         default:
+            return false;
+      }
+      return true;
+}
+
+bool isValidIP(const char* ip)
+{
+   unsigned b1, b2, b3, b4;
+   unsigned char c;
+   int rc = dSscanf(ip, "%3u.%3u.%3u.%3u%c", &b1, &b2, &b3, &b4, &c);
+   if (rc != 4 && rc != 5) return false;
+   if ((b1 | b2 | b3 | b4) > 255) return false;
+   if (dStrspn(ip, "0123456789.") < dStrlen(ip)) return false;
+   return true;
+}
+
+bool isValidPort(U16 port)
+{
+   return (port >= 0 && port <=65535);
+}
 
 
 //=============================================================================
 //=============================================================================
 //    String Functions.
 //    String Functions.
@@ -235,6 +367,40 @@ DefineConsoleFunction( strlen, S32, ( const char* str ),,
    return dStrlen( str );
    return dStrlen( str );
 }
 }
 
 
+//-----------------------------------------------------------------------------
+DefineConsoleFunction( strlenskip, S32, ( const char* str, const char* first, const char* last ),,
+   "Calculate the length of a string in characters, skipping everything between and including first and last.\n"
+   "@param str A string.\n"
+   "@param first First character to look for to skip block of text.\n"
+   "@param last Second character to look for to skip block of text.\n"
+   "@return The length of the given string skipping blocks of text between characters.\n"
+   "@ingroup Strings" )
+{
+   const UTF8* pos = str;
+   U32 size = 0;
+   U32 length = dStrlen(str);
+   bool count = true;
+
+   //loop through each character counting each character, skipping tags (anything with < followed by >)
+   for(U32 i = 0; i < length; i++, pos++)
+   {
+      if(count)
+      {
+         if(*pos == first[0])
+            count = false;
+         else
+            size++;
+      }
+      else
+      {
+         if(*pos == last[0])
+            count = true;
+      }
+   }
+
+   return S32(size);
+}
+
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
 DefineConsoleFunction( strstr, S32, ( const char* string, const char* substring ),,
 DefineConsoleFunction( strstr, S32, ( const char* string, const char* substring ),,
@@ -281,6 +447,33 @@ DefineConsoleFunction( strpos, S32, ( const char* haystack, const char* needle,
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
+DefineConsoleFunction( strposr, S32, ( const char* haystack, const char* needle, S32 offset ), ( 0 ),
+   "Find the start of @a needle in @a haystack searching from right to left beginning at the given offset.\n"
+   "@param haystack The string to search.\n"
+   "@param needle The string to search for.\n"
+   "@return The index at which the first occurrence of @a needle was found in @a heystack or -1 if no match was found.\n\n"
+   "@tsexample\n"
+   "strposr( \"b ab\", \"b\", 1 ) // Returns 2.\n"
+   "@endtsexample\n"
+   "@ingroup Strings" )
+{
+   U32 sublen = dStrlen( needle );
+   U32 strlen = dStrlen( haystack );
+   S32 start = strlen - offset;
+   	
+   if(start < 0 || start > strlen)
+      return -1;
+   
+   if (start + sublen > strlen)
+	  start = strlen - sublen;
+   for(; start >= 0; start--)
+      if(!dStrncmp(haystack + start, needle, sublen))
+         return start;
+   return -1;
+}
+
+//-----------------------------------------------------------------------------
+
 DefineConsoleFunction( ltrim, const char*, ( const char* str ),,
 DefineConsoleFunction( ltrim, const char*, ( const char* str ),,
    "Remove leading whitespace from the string.\n"
    "Remove leading whitespace from the string.\n"
    "@param str A string.\n"
    "@param str A string.\n"
@@ -627,6 +820,18 @@ DefineConsoleFunction( stripTrailingNumber, String, ( const char* str ),,
    return String::GetTrailingNumber( str, suffix );
    return String::GetTrailingNumber( str, suffix );
 }
 }
 
 
+//-----------------------------------------------------------------------------
+
+DefineConsoleFunction( getFirstNumber, String, ( const char* str ),,
+   "Get the first occuring number from @a str.\n"
+   "@param str The string from which to read out the first number.\n"
+   "@return String representation of the number or "" if no number.\n\n")
+{
+   U32 start;
+   U32 end;
+   return String::GetFirstNumber(str, start, end);
+}
+
 //----------------------------------------------------------------
 //----------------------------------------------------------------
 
 
 DefineConsoleFunction( isspace, bool, ( const char* str, S32 index ),,
 DefineConsoleFunction( isspace, bool, ( const char* str, S32 index ),,
@@ -811,6 +1016,110 @@ DefineConsoleFunction( strrchrpos, S32, ( const char* str, const char* chr, S32
    return index;
    return index;
 }
 }
 
 
+//----------------------------------------------------------------
+
+DefineConsoleFunction( strToggleCaseToWords, const char*, ( const char* str ),,
+   "Parse a Toggle Case word into separate words.\n"
+   "@param str The string to parse.\n"
+   "@return new string space separated.\n\n"
+   "@tsexample\n"
+   "strToggleCaseToWords( \"HelloWorld\" ) // Returns \"Hello World\".\n"
+   "@endtsexample\n"
+   "@ingroup Strings" )
+{
+   String newStr;
+   for(S32 i = 0; str[i]; i++)
+   {
+      //If capitol add a space
+      if(i != 0 && str[i] >= 65 && str[i] <= 90)
+         newStr += " "; 
+
+      newStr += str[i]; 
+   }
+
+   return Con::getReturnBuffer(newStr);
+}
+
+//----------------------------------------------------------------
+
+// Warning: isInt and isFloat are very 'strict' and might need to be adjusted to allow other values. //seanmc
+DefineConsoleFunction( isInt, bool, ( const char* str),,
+   "Returns true if the string is an integer.\n"
+   "@param str The string to test.\n"
+   "@return true if @a str is an integer and false if not\n\n"
+   "@tsexample\n"
+   "isInt( \"13\" ) // Returns true.\n"
+   "@endtsexample\n"
+   "@ingroup Strings" )
+{
+   return isInt(str);
+}
+
+//----------------------------------------------------------------
+
+DefineConsoleFunction( isFloat, bool, ( const char* str, bool sciOk), (false),
+   "Returns true if the string is a float.\n"
+   "@param str The string to test.\n"
+   "@param sciOk Test for correct scientific notation and accept it (ex. 1.2e+14)"
+   "@return true if @a str is a float and false if not\n\n"
+   "@tsexample\n"
+   "isFloat( \"13.5\" ) // Returns true.\n"
+   "@endtsexample\n"
+   "@ingroup Strings" )
+{
+   return isFloat(str, sciOk);
+}
+
+//----------------------------------------------------------------
+
+DefineConsoleFunction( isValidPort, bool, ( const char* str),,
+   "Returns true if the string is a valid port number.\n"
+   "@param str The string to test.\n"
+   "@return true if @a str is a port and false if not\n\n"
+   "@tsexample\n"
+   "isValidPort( \"8080\" ) // Returns true.\n"
+   "@endtsexample\n"
+   "@ingroup Strings" )
+{
+   if(isInt(str))
+   {
+      U16 port = dAtous(str);
+      return isValidPort(port);
+   }
+   else
+      return false;
+}
+
+//----------------------------------------------------------------
+
+DefineConsoleFunction( isValidIP, bool, ( const char* str),,
+   "Returns true if the string is a valid ip address, excepts localhost.\n"
+   "@param str The string to test.\n"
+   "@return true if @a str is a valid ip address and false if not\n\n"
+   "@tsexample\n"
+   "isValidIP( \"localhost\" ) // Returns true.\n"
+   "@endtsexample\n"
+   "@ingroup Strings" )
+{
+   if(dStrcmp(str, "localhost") == 0)
+   {
+      return true;
+   }
+   else
+      return isValidIP(str);
+}
+
+//----------------------------------------------------------------
+
+// Torque won't normally add another string if it already exists with another casing,
+// so this forces the addition. It should be called once near the start, such as in main.cs.
+ConsoleFunction(addCaseSensitiveStrings,void,2,0,"[string1, string2, ...]"
+                "Adds case sensitive strings to the StringTable.")
+{
+	for(int i = 1; i < argc; i++)
+		StringTable->insert(argv[i], true);
+}
+
 //=============================================================================
 //=============================================================================
 //    Field Manipulators.
 //    Field Manipulators.
 //=============================================================================
 //=============================================================================
@@ -829,6 +1138,7 @@ DefineConsoleFunction( getWord, const char*, ( const char* text, S32 index ),,
    "@endtsexample\n\n"
    "@endtsexample\n\n"
    "@see getWords\n"
    "@see getWords\n"
    "@see getWordCount\n"
    "@see getWordCount\n"
+   "@see getToken\n"
    "@see getField\n"
    "@see getField\n"
    "@see getRecord\n"
    "@see getRecord\n"
    "@ingroup FieldManip" )
    "@ingroup FieldManip" )
@@ -852,6 +1162,7 @@ DefineConsoleFunction( getWords, const char*, ( const char* text, S32 startIndex
    "@endtsexample\n\n"
    "@endtsexample\n\n"
    "@see getWord\n"
    "@see getWord\n"
    "@see getWordCount\n"
    "@see getWordCount\n"
+   "@see getTokens\n"
    "@see getFields\n"
    "@see getFields\n"
    "@see getRecords\n"
    "@see getRecords\n"
    "@ingroup FieldManip" )
    "@ingroup FieldManip" )
@@ -876,6 +1187,7 @@ DefineConsoleFunction( setWord, const char*, ( const char* text, S32 index, cons
       "setWord( \"a b c d\", 2, \"f\" ) // Returns \"a b f d\"\n"
       "setWord( \"a b c d\", 2, \"f\" ) // Returns \"a b f d\"\n"
    "@endtsexample\n\n"
    "@endtsexample\n\n"
    "@see getWord\n"
    "@see getWord\n"
+   "@see setToken\n"
    "@see setField\n"
    "@see setField\n"
    "@see setRecord\n"
    "@see setRecord\n"
    "@ingroup FieldManip" )
    "@ingroup FieldManip" )
@@ -895,6 +1207,7 @@ DefineConsoleFunction( removeWord, const char*, ( const char* text, S32 index ),
    "@tsexample\n"
    "@tsexample\n"
       "removeWord( \"a b c d\", 2 ) // Returns \"a b d\"\n"
       "removeWord( \"a b c d\", 2 ) // Returns \"a b d\"\n"
    "@endtsexample\n\n"
    "@endtsexample\n\n"
+   "@see removeToken\n"
    "@see removeField\n"
    "@see removeField\n"
    "@see removeRecord\n"
    "@see removeRecord\n"
    "@ingroup FieldManip" )
    "@ingroup FieldManip" )
@@ -912,6 +1225,7 @@ DefineConsoleFunction( getWordCount, S32, ( const char* text ),,
    "@tsexample\n"
    "@tsexample\n"
       "getWordCount( \"a b c d e\" ) // Returns 5\n"
       "getWordCount( \"a b c d e\" ) // Returns 5\n"
    "@endtsexample\n\n"
    "@endtsexample\n\n"
+   "@see getTokenCount\n"
    "@see getFieldCount\n"
    "@see getFieldCount\n"
    "@see getRecordCount\n"
    "@see getRecordCount\n"
    "@ingroup FieldManip" )
    "@ingroup FieldManip" )
@@ -921,6 +1235,49 @@ DefineConsoleFunction( getWordCount, S32, ( const char* text ),,
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
+DefineEngineFunction( monthNumToStr, String, ( S32 num, bool abbreviate ), (false),
+   "@brief returns month as a word given a number or \"\" if number is bad"
+   "@return month as a word given a number or \"\" if number is bad"
+   "@ingroup FileSystem")
+{
+   switch(num)
+   {
+      case 1: return abbreviate ? "Jan" : "January"; break;
+      case 2: return abbreviate ? "Feb" : "February"; break;
+      case 3: return abbreviate ? "Mar" : "March"; break;
+      case 4: return abbreviate ? "Apr" : "April"; break;
+      case 5: return "May"; break;
+      case 6: return abbreviate ? "Jun" : "June"; break;
+      case 7: return abbreviate ? "Jul" : "July"; break;
+      case 8: return abbreviate ? "Aug" : "August"; break;
+      case 9: return abbreviate ? "Sep" : "September"; break;
+      case 10: return abbreviate ? "Oct" : "October"; break;
+      case 11: return abbreviate ? "Nov" : "November"; break;
+      case 12: return abbreviate ? "Dec" : "December"; break;
+      default: return "";
+   }
+}
+
+DefineEngineFunction( weekdayNumToStr, String, ( S32 num, bool abbreviate ), (false),
+   "@brief returns weekday as a word given a number or \"\" if number is bad"
+   "@return weekday as a word given a number or \"\" if number is bad"
+   "@ingroup FileSystem")
+{
+   switch(num)
+   {
+      case 0: return abbreviate ? "Sun" : "Sunday"; break;
+      case 1: return abbreviate ? "Mon" : "Monday"; break;
+      case 2: return abbreviate ? "Tue" : "Tuesday"; break;
+      case 3: return abbreviate ? "Wed" : "Wednesday"; break;
+      case 4: return abbreviate ? "Thu" : "Thursday"; break;
+      case 5: return abbreviate ? "Fri" : "Friday"; break;
+      case 6: return abbreviate ? "Sat" : "Saturday"; break;
+      default: return "";
+   }
+}
+
+//-----------------------------------------------------------------------------
+
 DefineConsoleFunction( getField, const char*, ( const char* text, S32 index ),,
 DefineConsoleFunction( getField, const char*, ( const char* text, S32 index ),,
    "Extract the field at the given @a index in the newline and/or tab separated list in @a text.\n"
    "Extract the field at the given @a index in the newline and/or tab separated list in @a text.\n"
    "Fields in @a text must be separated by newlines and/or tabs.\n"
    "Fields in @a text must be separated by newlines and/or tabs.\n"
@@ -1242,6 +1599,114 @@ DefineConsoleFunction( nextToken, const char*, ( const char* str1, const char* t
    return ret;
    return ret;
 }
 }
 
 
+//-----------------------------------------------------------------------------
+
+DefineConsoleFunction( getToken, const char*, ( const char* text, const char* delimiters, S32 index ),,
+   "Extract the substring at the given @a index in the @a delimiters separated list in @a text.\n"
+   "@param text A @a delimiters list of substrings.\n"
+   "@param delimiters Character or characters that separate the list of substrings in @a text.\n"
+   "@param index The zero-based index of the substring to extract.\n"
+   "@return The substring at the given index or \"\" if the index is out of range.\n\n"
+   "@tsexample\n"
+      "getToken( \"a b c d\", \" \", 2 ) // Returns \"c\"\n"
+   "@endtsexample\n\n"
+   "@see getTokens\n"
+   "@see getTokenCount\n"
+   "@see getWord\n"
+   "@see getField\n"
+   "@see getRecord\n"
+   "@ingroup FieldManip" )
+{
+   return Con::getReturnBuffer( StringUnit::getUnit(text, index, delimiters));
+}
+
+//-----------------------------------------------------------------------------
+
+DefineConsoleFunction( getTokens, const char*, ( const char* text, const char* delimiters, S32 startIndex, S32 endIndex ), ( -1 ),
+   "Extract a range of substrings separated by @a delimiters at the given @a startIndex onwards thru @a endIndex.\n"
+   "@param text A @a delimiters list of substrings.\n"
+   "@param delimiters Character or characters that separate the list of substrings in @a text.\n"
+   "@param startIndex The zero-based index of the first substring to extract from @a text.\n"
+   "@param endIndex The zero-based index of the last substring to extract from @a text.  If this is -1, all words beginning "
+      "with @a startIndex are extracted from @a text.\n"
+   "@return A string containing the specified range of substrings from @a text or \"\" if @a startIndex "
+      "is out of range or greater than @a endIndex.\n\n"
+   "@tsexample\n"
+      "getTokens( \"a b c d\", \" \", 1, 2, ) // Returns \"b c\"\n"
+   "@endtsexample\n\n"
+   "@see getToken\n"
+   "@see getTokenCount\n"
+   "@see getWords\n"
+   "@see getFields\n"
+   "@see getRecords\n"
+   "@ingroup FieldManip" )
+{
+   if( endIndex < 0 )
+      endIndex = 1000000;
+
+   return Con::getReturnBuffer( StringUnit::getUnits( text, startIndex, endIndex, delimiters ) );
+}
+
+//-----------------------------------------------------------------------------
+
+DefineConsoleFunction( setToken, const char*, ( const char* text, const char* delimiters, S32 index, const char* replacement ),,
+   "Replace the substring in @a text separated by @a delimiters at the given @a index with @a replacement.\n"
+   "@param text A @a delimiters list of substrings.\n"
+   "@param delimiters Character or characters that separate the list of substrings in @a text.\n"
+   "@param index The zero-based index of the substring to replace.\n"
+   "@param replacement The string with which to replace the substring.\n"
+   "@return A new string with the substring at the given @a index replaced by @a replacement or the original "
+      "string if @a index is out of range.\n\n"
+   "@tsexample\n"
+      "setToken( \"a b c d\", \" \", 2, \"f\" ) // Returns \"a b f d\"\n"
+   "@endtsexample\n\n"
+   "@see getToken\n"
+   "@see setWord\n"
+   "@see setField\n"
+   "@see setRecord\n"
+   "@ingroup FieldManip" )
+{
+   return Con::getReturnBuffer( StringUnit::setUnit( text, index, replacement, delimiters) );
+}
+
+//-----------------------------------------------------------------------------
+
+DefineConsoleFunction( removeToken, const char*, ( const char* text, const char* delimiters, S32 index ),,
+   "Remove the substring in @a text separated by @a delimiters at the given @a index.\n"
+   "@param text A @a delimiters list of substrings.\n"
+   "@param delimiters Character or characters that separate the list of substrings in @a text.\n"
+   "@param index The zero-based index of the word in @a text.\n"
+   "@return A new string with the substring at the given index removed or the original string if @a index is "
+      "out of range.\n\n"
+   "@tsexample\n"
+      "removeToken( \"a b c d\", \" \", 2 ) // Returns \"a b d\"\n"
+   "@endtsexample\n\n"
+   "@see removeWord\n"
+   "@see removeField\n"
+   "@see removeRecord\n"
+   "@ingroup FieldManip" )
+{
+   return Con::getReturnBuffer( StringUnit::removeUnit( text, index, delimiters ) );
+}
+
+//-----------------------------------------------------------------------------
+
+DefineConsoleFunction( getTokenCount, S32, ( const char* text, const char* delimiters),,
+   "Return the number of @a delimiters substrings in @a text.\n"
+   "@param text A @a delimiters list of substrings.\n"
+   "@param delimiters Character or characters that separate the list of substrings in @a text.\n"
+   "@return The number of @a delimiters substrings in @a text.\n\n"
+   "@tsexample\n"
+      "getTokenCount( \"a b c d e\", \" \" ) // Returns 5\n"
+   "@endtsexample\n\n"
+   "@see getWordCount\n"
+   "@see getFieldCount\n"
+   "@see getRecordCount\n"
+   "@ingroup FieldManip" )
+{
+   return StringUnit::getUnitCount( text, delimiters );
+}
+
 //=============================================================================
 //=============================================================================
 //    Tagged Strings.
 //    Tagged Strings.
 //=============================================================================
 //=============================================================================
@@ -2597,3 +3062,10 @@ DefineEngineFunction( isToolBuild, bool, (),,
    return false;
    return false;
 #endif
 #endif
 }
 }
+
+DefineEngineFunction( getMaxDynamicVerts, S32, (),,
+	"Get max number of allowable dynamic vertices in a single vertex buffer.\n\n"
+	"@return the max number of allowable dynamic vertices in a single vertex buffer" )
+{
+   return MAX_DYNAMIC_VERTS / 2;
+}

+ 16 - 0
Engine/source/console/consoleFunctions.h

@@ -0,0 +1,16 @@
+#ifndef _CONSOLFUNCTIONS_H_
+#define _CONSOLFUNCTIONS_H_
+
+#ifndef _STRINGFUNCTIONS_H_
+#include "core/strings/stringFunctions.h"
+#endif
+
+bool isInt(const char* str);
+
+bool isFloat(const char* str);
+
+bool isValidIP(const char* ip);
+
+bool isValidPort(U16 port);
+
+#endif

+ 9 - 0
Engine/source/core/strings/stringFunctions.h

@@ -152,11 +152,20 @@ inline U32 dAtoui(const char *str, U32 base = 10)
    return strtoul(str, NULL, base);
    return strtoul(str, NULL, base);
 }
 }
 
 
+inline U16 dAtous(const char *str, U32 base = 10)
+{
+   return strtoul(str, NULL, base);
+}
+
 inline F32 dAtof(const char *str)
 inline F32 dAtof(const char *str)
 {
 {
    return strtof(str, NULL);
    return strtof(str, NULL);
 }
 }
 
 
+inline F64 dAtod(const char *str)
+{
+   return strtod(str, NULL);
+}
 
 
 inline char dToupper(const char c)
 inline char dToupper(const char c)
 {
 {

+ 100 - 0
Engine/source/core/util/str.cpp

@@ -1628,3 +1628,103 @@ String String::GetTrailingNumber(const char* str, S32& number)
 
 
    return base.substr(0, p - base.c_str());
    return base.substr(0, p - base.c_str());
 }
 }
+
+String String::GetFirstNumber(const char* str, U32& startPos, U32& endPos)
+{
+   // Check for trivial strings
+   if (!str || !str[0])
+      return String::EmptyString;
+
+   // Find the number at the end of the string
+   String base(str);
+   const char* p = base.c_str();
+   const char* end = base.c_str() + base.length() - 1;
+   bool dec = false;
+   startPos = 0;
+
+   //Check if we are just a digit
+   if(p == end && isdigit(*p))
+      return base;
+
+   //Look for the first digit
+   while ((p != end) && (dIsspace(*p) || !isdigit(*p)))
+   {
+      p++;
+      startPos++;
+   }
+
+   //Handle if we are at the end and found nothing
+   if(p == end && !isdigit(*p))
+      return "";
+
+   //update our end position at least to the start of our number
+   endPos = startPos;
+
+   //Backup our ptr
+   const char* backup = p;
+
+   //Check for any negative or decimal values
+   if(startPos > 0)
+   {
+      p--;
+      startPos--;
+      if(*p == '.')
+      {
+         dec = true;
+
+         //ignore any duplicate periods
+         while ((p != base.c_str()) && (*p == '.'))
+         {
+            p--;
+            startPos--;
+         }
+
+         //Found a decimal lets still check for negative sign
+         if(startPos > 0)
+         {
+            p--;
+            startPos--;
+            if((*p != '-') && (*p != '_'))
+            {
+               startPos++;
+               p++;
+            }
+         }
+      }
+      else if((*p != '-') && (*p != '_'))
+      {
+         //go back to where we where cause no decimal or negative sign found
+         startPos++;
+         p++;
+      }
+   }
+
+   //Restore where we were
+   p = backup;
+
+   //look for the end of the digits
+   bool justFoundDec = false;
+   while (p != end)
+   {
+      if(*p == '.')
+      {
+         if(dec && !justFoundDec)
+            break;
+         else
+         {
+            dec = true;
+            justFoundDec = true;
+         }
+      }
+      else if(!isdigit(*p))
+         break;
+      else if(justFoundDec)
+         justFoundDec = false;
+
+      p++;
+      endPos++;
+   }
+
+   U32 len = (!isdigit(*p)) ? endPos - startPos : (endPos + 1) - startPos;
+   return base.substr(startPos, len);
+}

+ 1 - 0
Engine/source/core/util/str.h

@@ -191,6 +191,7 @@ public:
    static String ToUpper(const String &string);
    static String ToUpper(const String &string);
 
 
    static String GetTrailingNumber(const char* str, S32& number);
    static String GetTrailingNumber(const char* str, S32& number);
+   static String GetFirstNumber(const char* str, U32& startPos, U32& endPos);
 
 
    /// @}
    /// @}
 
 

+ 88 - 0
Engine/source/math/mathTypes.cpp

@@ -660,6 +660,66 @@ DefineConsoleFunction( VectorScale, VectorF, ( VectorF a, F32 scalar ),,
 {
 {
    return a * scalar;
    return a * scalar;
 }
 }
+DefineConsoleFunction( VectorMul, VectorF, ( VectorF a, VectorF b ),,
+   "Multiplies two vectors.\n"
+   "@param a The first vector.\n"
+   "@param b The second vector.\n"
+   "@return The vector @a a * @a b.\n\n"
+   "@tsexample\n"
+	"//-----------------------------------------------------------------------------\n"
+	"//\n"
+	"// VectorMul( %a, %b );\n"
+	"//\n"
+	"// The multiplication of vector a, (ax, ay, az), and vector b, (bx, by, bz) is:\n"
+	"//\n"
+	"//     a * b = ( ax * bx, ay * by, az * bz )\n"
+	"//\n"
+	"//-----------------------------------------------------------------------------\n\n"
+
+	"%a = \"1 0 0\";\n"
+	"%b = \"0 1 0\";\n\n"
+
+	"// %r = \"( 1 * 0, 0 * 1, 0 * 0 )\";\n"
+	"// %r = \"0 0 0\";\n"
+	"%r = VectorMul( %a, %b );\n"
+   "@endtsexample\n\n"
+   "@ingroup Vectors" )
+{
+   return a * b;
+}
+
+DefineConsoleFunction( VectorDiv, VectorF, ( VectorF a, VectorF b ),,
+   "Divide two vectors.\n"
+   "@param a The first vector.\n"
+   "@param b The second vector.\n"
+   "@return The vector @a a / @a b.\n\n"
+   "@tsexample\n"
+	"//-----------------------------------------------------------------------------\n"
+	"//\n"
+	"// VectorDiv( %a, %b );\n"
+	"//\n"
+	"// The division of vector a, (ax, ay, az), and vector b, (bx, by, bz) is:\n"
+	"//\n"
+	"//     a * b = ( ax / bx, ay / by, az / bz )\n"
+	"//\n"
+	"//-----------------------------------------------------------------------------\n\n"
+
+	"%a = \"1 1 1\";\n"
+	"%b = \"2 2 2\";\n\n"
+
+	"// %r = \"( 1 / 2, 1 / 2, 1 / 2 )\";\n"
+	"// %r = \"0.5 0.5 0.5\";\n"
+	"%r = VectorDiv( %a, %b );\n"
+   "@endtsexample\n\n"
+   "@ingroup Vectors" )
+{
+   //this is kind of bad, but so is dividing by 0
+   if(b.x == 0) b.x = 0.000001f;
+   if(b.y == 0) b.y = 0.000001f;
+   if(b.z == 0) b.z = 0.000001f;
+   
+   return a / b;
+}
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
@@ -790,6 +850,34 @@ DefineConsoleFunction( VectorDist, F32, ( VectorF a, VectorF b ),,
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
+DefineConsoleFunction( VectorMidPoint, VectorF, ( VectorF a, VectorF b ),,
+   "Gets the midpoint between the two vectors.\n"
+   "@param a The first vector.\n"
+   "@param b The second vector.\n"
+   "@return The vector (@a a + @a b) / 2.\n\n"
+   "@tsexample\n"
+      "//-----------------------------------------------------------------------------\n"
+      "//\n"
+      "// VectorMidPoint( %a, %b );\n"
+      "//\n"
+      "// The midpoint of vector a, (ax, ay, az), and vector b, (bx, by, bz) is:\n"
+      "//\n"
+	  "//     (a + b)/2 = ( (ax + bx) /2, ay + by) /2, (az + bz) /2 )\n"
+      "//\n"
+      "//-----------------------------------------------------------------------------\n"
+//      "%a = \"1 0 0\";\n"
+//      "%b = \"0 1 0\";\n\n"
+//      "// %r = \"( 1 + 0, 0 + 1, 0 + 0 )\";\n"
+//      "// %r = \"1 1 0\";\n"
+//      "%r = VectorAdd( %a, %b );\n"
+   "@endtsexample\n\n"
+   "@ingroup Vectors")
+{
+   return (a + b)/2.0f;
+}
+
+//-----------------------------------------------------------------------------
+
 DefineConsoleFunction( VectorLen, F32, ( VectorF v ),,
 DefineConsoleFunction( VectorLen, F32, ( VectorF v ),,
    "Calculate the magnitude of the given vector.\n"
    "Calculate the magnitude of the given vector.\n"
    "@param v A vector.\n"
    "@param v A vector.\n"