From 39d5563a8c543e11fb1232d9b70fffcc0c993bd5 Mon Sep 17 00:00:00 2001 From: Nathan Bowhay Date: Thu, 29 Jan 2015 11:40:45 -0800 Subject: [PATCH 01/33] Added type checking functions added some type checking functions to TorqueScript. --- Engine/source/console/consoleFunctions.cpp | 200 +++++++++++++++++++++ Engine/source/console/consoleFunctions.h | 16 ++ 2 files changed, 216 insertions(+) create mode 100644 Engine/source/console/consoleFunctions.h diff --git a/Engine/source/console/consoleFunctions.cpp b/Engine/source/console/consoleFunctions.cpp index a5ea49f33..8d54ae076 100644 --- a/Engine/source/console/consoleFunctions.cpp +++ b/Engine/source/console/consoleFunctions.cpp @@ -25,6 +25,11 @@ #include "console/consoleInternal.h" #include "console/engineAPI.h" #include "console/ast.h" + +#ifndef _CONSOLFUNCTIONS_H_ +#include "console/consoleFunctions.h" +#endif + #include "core/strings/findMatch.h" #include "core/strings/stringUnit.h" #include "core/strings/unicode.h" @@ -45,6 +50,132 @@ bool LinkConsoleFunctions = false; // Buffer for expanding script filenames. static char scriptFilenameBuffer[1024]; +bool isInt(const char* str) +{ + 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; + } + + 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. @@ -815,6 +946,75 @@ DefineConsoleFunction( strrchrpos, S32, ( const char* str, const char* chr, S32 return index; } +//---------------------------------------------------------------- + +// 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); +} + //============================================================================= // Field Manipulators. //============================================================================= diff --git a/Engine/source/console/consoleFunctions.h b/Engine/source/console/consoleFunctions.h new file mode 100644 index 000000000..1cb19d1df --- /dev/null +++ b/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 \ No newline at end of file From 14037a742a41eba97b65f01cb9094c1e60291f19 Mon Sep 17 00:00:00 2001 From: Nathan Bowhay Date: Thu, 29 Jan 2015 11:48:15 -0800 Subject: [PATCH 02/33] Added string manipulation functions added some string manipulation functions, some are slightly different versions of existing functions. --- Engine/source/console/consoleFunctions.cpp | 97 ++++++++++++++++++++++ 1 file changed, 97 insertions(+) diff --git a/Engine/source/console/consoleFunctions.cpp b/Engine/source/console/consoleFunctions.cpp index 8d54ae076..47a57ecdb 100644 --- a/Engine/source/console/consoleFunctions.cpp +++ b/Engine/source/console/consoleFunctions.cpp @@ -370,6 +370,40 @@ DefineConsoleFunction( strlen, S32, ( const char* 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 ),, @@ -416,6 +450,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 ),, "Remove leading whitespace from the string.\n" "@param str A string.\n" @@ -762,6 +823,18 @@ DefineConsoleFunction( stripTrailingNumber, String, ( const char* str ),, 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 ),, @@ -948,6 +1021,30 @@ DefineConsoleFunction( strrchrpos, S32, ( const char* str, const char* chr, S32 //---------------------------------------------------------------- +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" From 2d7472d16067f1a03c3d76bfa05e6b7871042549 Mon Sep 17 00:00:00 2001 From: Nathan Bowhay Date: Thu, 29 Jan 2015 11:51:05 -0800 Subject: [PATCH 03/33] add case sensitive strings Added case sensitive strings function to add them to the string table. --- Engine/source/console/consoleFunctions.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Engine/source/console/consoleFunctions.cpp b/Engine/source/console/consoleFunctions.cpp index 47a57ecdb..f08ad2ac4 100644 --- a/Engine/source/console/consoleFunctions.cpp +++ b/Engine/source/console/consoleFunctions.cpp @@ -1112,6 +1112,17 @@ DefineConsoleFunction( isValidIP, bool, ( const char* str),, 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. //============================================================================= From 6a5fd4eceb5e14209cebb303a7d2eae790a3b748 Mon Sep 17 00:00:00 2001 From: Nathan Bowhay Date: Thu, 29 Jan 2015 11:53:25 -0800 Subject: [PATCH 04/33] date number to string added month and week number to string console functions. --- Engine/source/console/consoleFunctions.cpp | 43 ++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/Engine/source/console/consoleFunctions.cpp b/Engine/source/console/consoleFunctions.cpp index f08ad2ac4..9fe5708fd 100644 --- a/Engine/source/console/consoleFunctions.cpp +++ b/Engine/source/console/consoleFunctions.cpp @@ -1233,6 +1233,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 ),, "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" From 55b91606e6d6fce1805bf341bbc042025aba4dd6 Mon Sep 17 00:00:00 2001 From: Nathan Bowhay Date: Thu, 29 Jan 2015 11:54:44 -0800 Subject: [PATCH 05/33] Added more token functions Added a bunch more token functions and added comments to word equivalents to let you know about the token version. --- Engine/source/console/consoleFunctions.cpp | 113 +++++++++++++++++++++ 1 file changed, 113 insertions(+) diff --git a/Engine/source/console/consoleFunctions.cpp b/Engine/source/console/consoleFunctions.cpp index 9fe5708fd..f7680a82c 100644 --- a/Engine/source/console/consoleFunctions.cpp +++ b/Engine/source/console/consoleFunctions.cpp @@ -1141,6 +1141,7 @@ DefineConsoleFunction( getWord, const char*, ( const char* text, S32 index ),, "@endtsexample\n\n" "@see getWords\n" "@see getWordCount\n" + "@see getToken\n" "@see getField\n" "@see getRecord\n" "@ingroup FieldManip" ) @@ -1164,6 +1165,7 @@ DefineConsoleFunction( getWords, const char*, ( const char* text, S32 startIndex "@endtsexample\n\n" "@see getWord\n" "@see getWordCount\n" + "@see getTokens\n" "@see getFields\n" "@see getRecords\n" "@ingroup FieldManip" ) @@ -1188,6 +1190,7 @@ DefineConsoleFunction( setWord, const char*, ( const char* text, S32 index, cons "setWord( \"a b c d\", 2, \"f\" ) // Returns \"a b f d\"\n" "@endtsexample\n\n" "@see getWord\n" + "@see setToken\n" "@see setField\n" "@see setRecord\n" "@ingroup FieldManip" ) @@ -1207,6 +1210,7 @@ DefineConsoleFunction( removeWord, const char*, ( const char* text, S32 index ), "@tsexample\n" "removeWord( \"a b c d\", 2 ) // Returns \"a b d\"\n" "@endtsexample\n\n" + "@see removeToken\n" "@see removeField\n" "@see removeRecord\n" "@ingroup FieldManip" ) @@ -1224,6 +1228,7 @@ DefineConsoleFunction( getWordCount, S32, ( const char* text ),, "@tsexample\n" "getWordCount( \"a b c d e\" ) // Returns 5\n" "@endtsexample\n\n" + "@see getTokenCount\n" "@see getFieldCount\n" "@see getRecordCount\n" "@ingroup FieldManip" ) @@ -1597,6 +1602,114 @@ DefineConsoleFunction( nextToken, const char*, ( const char* str1, const char* t 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. //============================================================================= From 5cfcb0cd4547a183f5f5924a3cc9c0f7dc19f8a4 Mon Sep 17 00:00:00 2001 From: Nathan Bowhay Date: Thu, 29 Jan 2015 11:59:06 -0800 Subject: [PATCH 06/33] fixed comment added path param documentation to display splash window. --- Engine/source/console/consoleFunctions.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Engine/source/console/consoleFunctions.cpp b/Engine/source/console/consoleFunctions.cpp index f7680a82c..c15c6c944 100644 --- a/Engine/source/console/consoleFunctions.cpp +++ b/Engine/source/console/consoleFunctions.cpp @@ -2062,6 +2062,7 @@ DefineEngineFunction( gotoWebPage, void, ( const char* address ),, DefineEngineFunction( displaySplashWindow, bool, (const char* path), ("art/gui/splash.bmp"), "Display a startup splash window suitable for showing while the engine still starts up.\n\n" "@note This is currently only implemented on Windows.\n\n" + "@param path relative path to splash screen image to display.\n" "@return True if the splash window could be successfully initialized.\n\n" "@ingroup Platform" ) { From df2ca75b13d3edc9a3fa180ce0c96b30675005a9 Mon Sep 17 00:00:00 2001 From: Nathan Bowhay Date: Thu, 29 Jan 2015 12:02:40 -0800 Subject: [PATCH 07/33] get max dynamic verts in script you can now get the max dynamic vertices in script. --- Engine/source/console/consoleFunctions.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Engine/source/console/consoleFunctions.cpp b/Engine/source/console/consoleFunctions.cpp index c15c6c944..1d5403818 100644 --- a/Engine/source/console/consoleFunctions.cpp +++ b/Engine/source/console/consoleFunctions.cpp @@ -37,6 +37,7 @@ #include "console/compiler.h" #include "platform/platformInput.h" #include "core/util/journal/journal.h" +#include "gfx/gfxEnums.h" #include "core/util/uuid.h" #ifdef TORQUE_DEMO_PURCHASE @@ -3065,3 +3066,10 @@ DefineEngineFunction( isToolBuild, bool, (),, return false; #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; +} \ No newline at end of file From c98e95e6ff9f0a22adee57544805701a81b71c39 Mon Sep 17 00:00:00 2001 From: Nathan Bowhay Date: Thu, 29 Jan 2015 15:09:41 -0800 Subject: [PATCH 08/33] Forgot supporting method Added string manipulation functions upload, requires these changes to compile. --- Engine/source/core/util/str.cpp | 100 ++++++++++++++++++++++++++++++++ Engine/source/core/util/str.h | 1 + 2 files changed, 101 insertions(+) diff --git a/Engine/source/core/util/str.cpp b/Engine/source/core/util/str.cpp index 3f4f3d8f9..59fd0ab46 100644 --- a/Engine/source/core/util/str.cpp +++ b/Engine/source/core/util/str.cpp @@ -1624,3 +1624,103 @@ String String::GetTrailingNumber(const char* str, S32& number) 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); +} diff --git a/Engine/source/core/util/str.h b/Engine/source/core/util/str.h index 009484451..33fdb819d 100644 --- a/Engine/source/core/util/str.h +++ b/Engine/source/core/util/str.h @@ -190,6 +190,7 @@ public: static String ToUpper(const String &string); static String GetTrailingNumber(const char* str, S32& number); + static String GetFirstNumber(const char* str, U32& startPos, U32& endPos); /// @} From e03c3bb34fb7a2bdac847a23f10277285d9abf61 Mon Sep 17 00:00:00 2001 From: Ben Payne Date: Mon, 2 Feb 2015 18:17:37 -0500 Subject: [PATCH 09/33] Fix TORQUE_UNUSED for recent versions of MSVC Since there's now apparently no way to suppress the warning for a particular variable without adding at least some extra size to the executable, just turn the warning off in release builds. We leave it on in debug since it can sometimes help catch bugs, and we don't care about a little extra code in that configuration. --- Engine/source/platform/types.visualc.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Engine/source/platform/types.visualc.h b/Engine/source/platform/types.visualc.h index e383c1ea7..36d075d07 100644 --- a/Engine/source/platform/types.visualc.h +++ b/Engine/source/platform/types.visualc.h @@ -32,6 +32,16 @@ typedef signed _int64 S64; typedef unsigned _int64 U64; +// The types.h version of TORQUE_UNUSED no longer works for recent versions of MSVC. +// Since it appears that MS has made this impossible to do in a zero-overhead way, +// just turn the warning off in release builds. +#undef TORQUE_UNUSED +#ifdef TORQUE_DEBUG +#define TORQUE_UNUSED(var) ((0,0) ? (void)(var) : (void)0) +#else +#pragma warning(disable: 4189) // local variable is initialized but not referenced +#define TORQUE_UNUSED(var) ((void)0) +#endif //-------------------------------------- // Compiler Version From c19a70814c270d51dd768b0ffdfa45ec9cd42f39 Mon Sep 17 00:00:00 2001 From: Ben Payne Date: Mon, 2 Feb 2015 18:24:01 -0500 Subject: [PATCH 10/33] Tidy up and fix the various Assert macros Rephrase the macros so that they can be used in expressions, and properly require semicolons. And add the semicolons where missing. --- Engine/source/T3D/fx/fxFoliageReplicator.cpp | 6 +-- Engine/source/T3D/fx/fxShapeReplicator.cpp | 2 +- Engine/source/console/codeBlock.cpp | 2 +- Engine/source/core/idGenerator.h | 2 +- Engine/source/environment/timeOfDay.cpp | 4 +- .../source/gfx/bitmap/loaders/bitmapTga.cpp | 2 +- Engine/source/gui/core/guiCanvas.cpp | 3 +- Engine/source/platform/platformAssert.h | 53 +++++++++---------- Engine/source/sim/netGhost.cpp | 4 +- Engine/source/util/catmullRom.cpp | 2 +- Engine/source/util/catmullRom.h | 4 +- 11 files changed, 40 insertions(+), 44 deletions(-) diff --git a/Engine/source/T3D/fx/fxFoliageReplicator.cpp b/Engine/source/T3D/fx/fxFoliageReplicator.cpp index 7e88b174f..ec17c2f18 100644 --- a/Engine/source/T3D/fx/fxFoliageReplicator.cpp +++ b/Engine/source/T3D/fx/fxFoliageReplicator.cpp @@ -426,7 +426,7 @@ void fxFoliageReplicator::CreateFoliage(void) Point3F MaxPoint( 0.5, 0.5, 0.5 ); // Check Host. - AssertFatal(isClientObject(), "Trying to create Foliage on Server, this is bad!") + AssertFatal(isClientObject(), "Trying to create Foliage on Server, this is bad!"); // Cannot continue without Foliage Texture! if (dStrlen(mFieldData.mFoliageFile) == 0) @@ -1134,7 +1134,7 @@ void fxFoliageReplicator::ProcessQuadrant(fxFoliageQuadrantNode* pParentNode, fx void fxFoliageReplicator::SyncFoliageReplicators(void) { // Check Host. - AssertFatal(isServerObject(), "We *MUST* be on server when Synchronising Foliage!") + AssertFatal(isServerObject(), "We *MUST* be on server when Synchronising Foliage!"); // Find the Replicator Set. SimSet *fxFoliageSet = dynamic_cast(Sim::findObject("fxFoliageSet")); @@ -1196,7 +1196,7 @@ void fxFoliageReplicator::DestroyFoliageItems() void fxFoliageReplicator::DestroyFoliage(void) { // Check Host. - AssertFatal(isClientObject(), "Trying to destroy Foliage on Server, this is bad!") + AssertFatal(isClientObject(), "Trying to destroy Foliage on Server, this is bad!"); // Destroy Quad-tree. mPotentialFoliageNodes = 0; diff --git a/Engine/source/T3D/fx/fxShapeReplicator.cpp b/Engine/source/T3D/fx/fxShapeReplicator.cpp index 908212716..6093fa0d5 100644 --- a/Engine/source/T3D/fx/fxShapeReplicator.cpp +++ b/Engine/source/T3D/fx/fxShapeReplicator.cpp @@ -224,7 +224,7 @@ void fxShapeReplicator::CreateShapes(void) } // Check Shapes. - AssertFatal(mCurrentShapeCount==0,"Shapes already present, this should not be possible!") + AssertFatal(mCurrentShapeCount==0,"Shapes already present, this should not be possible!"); // Check that we have a shape... if (!mFieldData.mShapeFile) return; diff --git a/Engine/source/console/codeBlock.cpp b/Engine/source/console/codeBlock.cpp index 05a2ab798..9b87a5ed3 100644 --- a/Engine/source/console/codeBlock.cpp +++ b/Engine/source/console/codeBlock.cpp @@ -61,7 +61,7 @@ CodeBlock::CodeBlock() CodeBlock::~CodeBlock() { // Make sure we aren't lingering in the current code block... - AssertFatal(smCurrentCodeBlock != this, "CodeBlock::~CodeBlock - Caught lingering in smCurrentCodeBlock!") + AssertFatal(smCurrentCodeBlock != this, "CodeBlock::~CodeBlock - Caught lingering in smCurrentCodeBlock!"); if(name) removeFromCodeList(); diff --git a/Engine/source/core/idGenerator.h b/Engine/source/core/idGenerator.h index a0ddc74ed..8c3467673 100644 --- a/Engine/source/core/idGenerator.h +++ b/Engine/source/core/idGenerator.h @@ -74,7 +74,7 @@ public: void free(U32 id) { - AssertFatal(id >= mIdBlockBase, "IdGenerator::alloc: invalid id, id does not belong to this IdGenerator.") + AssertFatal(id >= mIdBlockBase, "IdGenerator::alloc: invalid id, id does not belong to this IdGenerator."); if(id == mNextId - 1) { mNextId--; diff --git a/Engine/source/environment/timeOfDay.cpp b/Engine/source/environment/timeOfDay.cpp index 49b069b64..a0ae2fc83 100644 --- a/Engine/source/environment/timeOfDay.cpp +++ b/Engine/source/environment/timeOfDay.cpp @@ -402,7 +402,7 @@ void TimeOfDay::_getSunColor( ColorF *outColor ) const //simple check if ( mColorTargets[0].elevation != 0.0f ) { - AssertFatal(0, "TimeOfDay::GetColor() - First elevation must be 0.0 radians") + AssertFatal(0, "TimeOfDay::GetColor() - First elevation must be 0.0 radians"); outColor->set(1.0f, 1.0f, 1.0f); //mBandMod = 1.0f; //mCurrentBandColor = color; @@ -411,7 +411,7 @@ void TimeOfDay::_getSunColor( ColorF *outColor ) const if ( mColorTargets[mColorTargets.size()-1].elevation != M_PI_F ) { - AssertFatal(0, "Celestails::GetColor() - Last elevation must be PI") + AssertFatal(0, "Celestails::GetColor() - Last elevation must be PI"); outColor->set(1.0f, 1.0f, 1.0f); //mBandMod = 1.0f; //mCurrentBandColor = color; diff --git a/Engine/source/gfx/bitmap/loaders/bitmapTga.cpp b/Engine/source/gfx/bitmap/loaders/bitmapTga.cpp index 15812ff9b..dff46bf03 100644 --- a/Engine/source/gfx/bitmap/loaders/bitmapTga.cpp +++ b/Engine/source/gfx/bitmap/loaders/bitmapTga.cpp @@ -483,7 +483,7 @@ static bool sReadTGA(Stream &stream, GBitmap *bitmap) static bool sWriteTGA(GBitmap *bitmap, Stream &stream, U32 compressionLevel) { - AssertISV(false, "GBitmap::writeTGA - doesn't support writing tga files!") + AssertISV(false, "GBitmap::writeTGA - doesn't support writing tga files!"); return false; } diff --git a/Engine/source/gui/core/guiCanvas.cpp b/Engine/source/gui/core/guiCanvas.cpp index 4dba87310..6c68e410c 100644 --- a/Engine/source/gui/core/guiCanvas.cpp +++ b/Engine/source/gui/core/guiCanvas.cpp @@ -712,7 +712,8 @@ bool GuiCanvas::processMouseEvent(InputEventInfo &inputEvent) // Need to query platform for specific things AssertISV(mPlatformWindow, "GuiCanvas::processMouseEvent - no window present!"); PlatformCursorController *pController = mPlatformWindow->getCursorController(); - AssertFatal(pController != NULL, "GuiCanvas::processInputEvent - No Platform Controller Found") + AssertFatal(pController != NULL, "GuiCanvas::processInputEvent - No Platform Controller Found"); + //copy the modifier into the new event mLastEvent.modifier = inputEvent.modifier; diff --git a/Engine/source/platform/platformAssert.h b/Engine/source/platform/platformAssert.h index c26f255c0..86ccb1b23 100644 --- a/Engine/source/platform/platformAssert.h +++ b/Engine/source/platform/platformAssert.h @@ -64,19 +64,17 @@ public: #ifdef TORQUE_ENABLE_ASSERTS - /*! - Assert that the statement x is true, and continue processing. +/*! + Assert that the statement x is true, and continue processing. - If the statment x is true, continue processing. + If the statment x is true, continue processing. - If the statement x is false, log the file and line where the assert occured, - the message y and continue processing. + If the statement x is false, log the file and line where the assert occured, + the message y and continue processing. - These asserts are only present in DEBUG builds. - */ - #define AssertWarn(x, y) \ - { if ((x)==0) \ - ::PlatformAssert::processAssert(::PlatformAssert::Warning, __FILE__, __LINE__, y); } + These asserts are only present in DEBUG builds. + */ +#define AssertWarn(x, y) (void)(!!(x) || ::PlatformAssert::processAssert(::PlatformAssert::Warning, __FILE__, __LINE__, y)) /*! Helper macro called when AssertFatal failed. @@ -86,27 +84,27 @@ public: #define ON_FAIL_ASSERTFATAL #endif - /*! - Assert that the statement x is true, otherwise halt. +/*! + Assert that the statement x is true, otherwise halt. - If the statement x is true, continue processing. + If the statement x is true, continue processing. - If the statement x is false, log the file and line where the assert occured, - the message y and displaying a dialog containing the message y. The user then - has the option to halt or continue causing the debugger to break. + If the statement x is false, log the file and line where the assert occured, + the message y and displaying a dialog containing the message y. The user then + has the option to halt or continue causing the debugger to break. - These asserts are only present in DEBUG builds. + These asserts are only present in DEBUG builds. - This assert is very useful for verifying data as well as function entry and - exit conditions. - */ - #define AssertFatal(x, y) \ - { if (((bool)(x))==false) \ - { if ( ::PlatformAssert::processAssert(::PlatformAssert::Fatal, __FILE__, __LINE__, y) ) { ::Platform::debugBreak(); } } } + This assert is very useful for verifying data as well as function entry and + exit conditions. + */ +#define AssertFatal(x, y) ((!(x) && ::PlatformAssert::processAssert(::PlatformAssert::Fatal, __FILE__, __LINE__, y)) ? ::Platform::debugBreak() : (void)0) \ #else - #define AssertFatal(x, y) { TORQUE_UNUSED(x); TORQUE_UNUSED(y); } - #define AssertWarn(x, y) { TORQUE_UNUSED(x); TORQUE_UNUSED(y); } + +#define AssertFatal(x, y) TORQUE_UNUSED(x) +#define AssertWarn(x, y) TORQUE_UNUSED(x) + #endif /*! @@ -121,10 +119,7 @@ public: This assert should only be used for rare conditions where the application cannot continue execution without seg-faulting and you want to display a nice exit message. */ -#define AssertISV(x, y) \ - { if ((x)==0) \ -{ if ( ::PlatformAssert::processAssert(::PlatformAssert::Fatal_ISV, __FILE__, __LINE__, y) ) { ::Platform::debugBreak(); } } } - +#define AssertISV(x, y) ((!(x) && ::PlatformAssert::processAssert(::PlatformAssert::Fatal_ISV, __FILE__, __LINE__, y)) ? ::Platform::debugBreak() : (void)0) \ /*! Sprintf style string formating into a fixed temporary buffer. diff --git a/Engine/source/sim/netGhost.cpp b/Engine/source/sim/netGhost.cpp index 13acfc7e3..9ea42fc06 100644 --- a/Engine/source/sim/netGhost.cpp +++ b/Engine/source/sim/netGhost.cpp @@ -958,7 +958,7 @@ void NetConnection::activateGhosting() // Iterate through the scope always objects... for (j = mGhostZeroUpdateIndex - 1; j >= 0; j--) { - AssertFatal((mGhostArray[j]->flags & GhostInfo::ScopeAlways) != 0, "NetConnection::activateGhosting: Non-scope always in the scope always list.") + AssertFatal((mGhostArray[j]->flags & GhostInfo::ScopeAlways) != 0, "NetConnection::activateGhosting: Non-scope always in the scope always list."); // Clear the ghost update mask and flags appropriately. mGhostArray[j]->updateMask = 0; @@ -1009,7 +1009,7 @@ void NetConnection::activateGhosting() // Iterate through the scope always objects... for (j = mGhostZeroUpdateIndex - 1; j >= 0; j--) { - AssertFatal((mGhostArray[j]->flags & GhostInfo::ScopeAlways) != 0, "NetConnection::activateGhosting: Non-scope always in the scope always list.") + AssertFatal((mGhostArray[j]->flags & GhostInfo::ScopeAlways) != 0, "NetConnection::activateGhosting: Non-scope always in the scope always list."); // Clear the ghost update mask and flags appropriately. mGhostArray[j]->updateMask = 0; diff --git a/Engine/source/util/catmullRom.cpp b/Engine/source/util/catmullRom.cpp index 10452c18c..7ac676a15 100644 --- a/Engine/source/util/catmullRom.cpp +++ b/Engine/source/util/catmullRom.cpp @@ -48,7 +48,7 @@ CatmullRomBase::CatmullRomBase() void CatmullRomBase::_initialize( U32 count, const F32 *times ) { //AssertFatal( times, "CatmullRomBase::_initialize() - Got null position!" ) - AssertFatal( count > 1, "CatmullRomBase::_initialize() - Must have more than 2 points!" ) + AssertFatal( count > 1, "CatmullRomBase::_initialize() - Must have more than 2 points!" ); // set up arrays mTimes = new F32[count]; diff --git a/Engine/source/util/catmullRom.h b/Engine/source/util/catmullRom.h index f4c9decb0..84bb272aa 100644 --- a/Engine/source/util/catmullRom.h +++ b/Engine/source/util/catmullRom.h @@ -142,8 +142,8 @@ inline void CatmullRom::clear() template inline void CatmullRom::initialize( U32 count, const TYPE *positions, const F32 *times ) { - AssertFatal( positions, "CatmullRom::initialize - Got null position!" ) - AssertFatal( count > 1, "CatmullRom::initialize - Must have more than 2 points!" ) + AssertFatal( positions, "CatmullRom::initialize - Got null position!" ); + AssertFatal( count > 1, "CatmullRom::initialize - Must have more than 2 points!" ); // Clean up any previous state. clear(); From 222be2bb723f6536bf33ce139e352dfc52c45e6f Mon Sep 17 00:00:00 2001 From: Ben Payne Date: Mon, 2 Feb 2015 19:11:20 -0500 Subject: [PATCH 11/33] Remove dead function --- Engine/source/platform/platformAssert.cpp | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/Engine/source/platform/platformAssert.cpp b/Engine/source/platform/platformAssert.cpp index 7e1d3b93a..f1a2b2957 100644 --- a/Engine/source/platform/platformAssert.cpp +++ b/Engine/source/platform/platformAssert.cpp @@ -69,24 +69,6 @@ bool PlatformAssert::displayMessageBox(const char *title, const char *message, b } static const char *typeName[] = { "Unknown", "Fatal-ISV", "Fatal", "Warning" }; -//------------------------------------------------------------------------------ -static bool askToEnterDebugger(const char* message ) -{ - static bool haveAsked = false; - static bool useDebugger = true; - if(!haveAsked ) - { - static char tempBuff[1024]; - dSprintf( tempBuff, 1024, "Torque has encountered an assertion with message\n\n" - "%s\n\n" - "Would you like to use the debugger? If you cancel, you won't be asked" - " again until you restart Torque.", message); - - useDebugger = Platform::AlertOKCancel("Use debugger?", tempBuff ); - haveAsked = true; - } - return useDebugger; -} //-------------------------------------- From 2efe1a9c0a0b420a10742235c7bdcfe7b599cbc1 Mon Sep 17 00:00:00 2001 From: Nathan Bowhay Date: Tue, 3 Feb 2015 10:59:32 -0800 Subject: [PATCH 12/33] Added More Vector math functions Added VectorMul (vector multiply), VectorDiv (vector divide, and VectorMidPoint to find the midpoint of two vectors. --- Engine/source/math/mathTypes.cpp | 88 ++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) diff --git a/Engine/source/math/mathTypes.cpp b/Engine/source/math/mathTypes.cpp index ce0f198d1..807e3bc60 100644 --- a/Engine/source/math/mathTypes.cpp +++ b/Engine/source/math/mathTypes.cpp @@ -659,6 +659,66 @@ DefineConsoleFunction( VectorScale, VectorF, ( VectorF a, F32 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; +} //----------------------------------------------------------------------------- @@ -789,6 +849,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 ),, "Calculate the magnitude of the given vector.\n" "@param v A vector.\n" From 686b9fced931833fc30e043472e92a6709cdccbf Mon Sep 17 00:00:00 2001 From: Nathan Bowhay Date: Tue, 3 Feb 2015 11:52:06 -0800 Subject: [PATCH 13/33] Round function can now round to number of digits Changed round function to support optional n parameter to round to that many digits. --- Engine/source/math/mConsoleFunctions.cpp | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/Engine/source/math/mConsoleFunctions.cpp b/Engine/source/math/mConsoleFunctions.cpp index 1a11fe23e..f9b352c28 100644 --- a/Engine/source/math/mConsoleFunctions.cpp +++ b/Engine/source/math/mConsoleFunctions.cpp @@ -94,13 +94,18 @@ DefineConsoleFunction( mFloor, S32, ( F32 v ),, return (S32)mFloor( v ); } -DefineConsoleFunction( mRound, S32, ( F32 v ),, - "Round v to the nth decimal place or the nearest whole number by default." - "@param v Value to roundn" - "@return The rounded value as a S32." - "@ingroup Math" ) + +DefineConsoleFunction( mRound, F32, ( F32 v, S32 n ), (0), + "Round v to the nth decimal place or the nearest whole number by default." + "@param v Value to round\n" + "@param n Number of decimal places to round to, 0 by default\n" + "@return The rounded value as a S32." + "@ingroup Math" ) { - return mRound(v); + if(n <= 0) + return mRound(v); + else + return mRound(v, n); } DefineConsoleFunction( mCeil, S32, ( F32 v ),, From 7ef3a6495784c19824fbb0e414a54dd2ba54f761 Mon Sep 17 00:00:00 2001 From: Nathan Bowhay Date: Thu, 5 Feb 2015 11:28:19 -0800 Subject: [PATCH 14/33] Added getLocalTime console function Add getLocalTime console function so that script has access to the local time. --- Engine/source/app/game.cpp | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/Engine/source/app/game.cpp b/Engine/source/app/game.cpp index 4579b4819..2f0e30c77 100644 --- a/Engine/source/app/game.cpp +++ b/Engine/source/app/game.cpp @@ -202,6 +202,26 @@ DefineConsoleFunction( getRealTime, S32, (), , "()" 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); //----------------------------------------------------------------------------- From a0250e6c6bd3b9c88858c0fc35a3f5da6a5807df Mon Sep 17 00:00:00 2001 From: Nathan Bowhay Date: Thu, 5 Feb 2015 11:41:44 -0800 Subject: [PATCH 15/33] Added callback when we read all lines Added a script callback when all lines have been read. --- Engine/source/app/net/tcpObject.cpp | 6 ++++++ Engine/source/app/net/tcpObject.h | 1 + 2 files changed, 7 insertions(+) diff --git a/Engine/source/app/net/tcpObject.cpp b/Engine/source/app/net/tcpObject.cpp index f2818b426..6d1ccaa49 100644 --- a/Engine/source/app/net/tcpObject.cpp +++ b/Engine/source/app/net/tcpObject.cpp @@ -138,6 +138,10 @@ IMPLEMENT_CALLBACK(TCPObject, onLine, void, (const char* line), (line), "@param line Data sent from the server.\n" ); +IMPLEMENT_CALLBACK(TCPObject, onEndReceive, void, (), (), + "@brief Called when we are done reading all lines.\n\n" + ); + IMPLEMENT_CALLBACK(TCPObject, onDNSResolved, void, (),(), "Called whenever the DNS has been resolved.\n" ); @@ -499,6 +503,8 @@ void processConnectedReceiveEvent(NetSocket sock, RawData incomingData) size -= ret; buffer += ret; } + + tcpo->onEndReceive_callback(); } void processConnectedAcceptEvent(NetSocket listeningPort, NetSocket newConnection, NetAddress originatingAddress) diff --git a/Engine/source/app/net/tcpObject.h b/Engine/source/app/net/tcpObject.h index 9c4582eab..9d14868ad 100644 --- a/Engine/source/app/net/tcpObject.h +++ b/Engine/source/app/net/tcpObject.h @@ -36,6 +36,7 @@ public: DECLARE_CALLBACK(void, onConnectionRequest, (const char* address, const char* ID)); DECLARE_CALLBACK(void, onLine, (const char* line)); + DECLARE_CALLBACK(void, onEndReceive, ()); DECLARE_CALLBACK(void, onDNSResolved,()); DECLARE_CALLBACK(void, onDNSFailed, ()); DECLARE_CALLBACK(void, onConnected, ()); From 5f0b3984fc0137382560f74dffdec90468b2c290 Mon Sep 17 00:00:00 2001 From: Nathan Bowhay Date: Thu, 5 Feb 2015 11:43:56 -0800 Subject: [PATCH 16/33] Added sendFile method Added a method to send an entire file over tcp. --- Engine/source/app/net/tcpObject.cpp | 33 +++++++++++++++++++++++++++++ Engine/source/app/net/tcpObject.h | 6 ++++++ 2 files changed, 39 insertions(+) diff --git a/Engine/source/app/net/tcpObject.cpp b/Engine/source/app/net/tcpObject.cpp index 6d1ccaa49..b156bfa04 100644 --- a/Engine/source/app/net/tcpObject.cpp +++ b/Engine/source/app/net/tcpObject.cpp @@ -27,6 +27,7 @@ #include "console/consoleInternal.h" #include "core/strings/stringUnit.h" #include "console/engineAPI.h" +#include "core/stream/fileStream.h" TCPObject *TCPObject::table[TCPObject::TableSize] = {0, }; @@ -404,6 +405,29 @@ void TCPObject::send(const U8 *buffer, U32 len) Net::sendtoSocket(mTag, buffer, S32(len)); } +bool TCPObject::sendFile(const char* fileName) +{ + //Open the file for reading + FileStream readFile; + if(!readFile.open(fileName, Torque::FS::File::Read)) + { + return false; + } + + //Read each byte into our buffer + Vector buffer(readFile.getStreamSize()); + U8 byte; + while(readFile.read(&byte)) + { + buffer.push_back(byte); + } + + //Send the buffer + send(buffer.address(), buffer.size()); + + return true; +} + DefineEngineMethod(TCPObject, send, void, (const char *data),, "@brief Transmits the data string to the connected computer.\n\n" @@ -425,6 +449,15 @@ DefineEngineMethod(TCPObject, send, void, (const char *data),, object->send( (const U8*)data, dStrlen(data) ); } +DefineEngineMethod(TCPObject, sendFile, bool, (const char *fileName),, + "@brief Transmits the file in binary to the connected computer.\n\n" + + "@param fileName The filename of the file to transfer.\n") +{ + return object->sendFile(fileName); +} + + DefineEngineMethod(TCPObject, listen, void, (U32 port),, "@brief Start listening on the specified port for connections.\n\n" diff --git a/Engine/source/app/net/tcpObject.h b/Engine/source/app/net/tcpObject.h index 9d14868ad..39b9464ba 100644 --- a/Engine/source/app/net/tcpObject.h +++ b/Engine/source/app/net/tcpObject.h @@ -82,6 +82,12 @@ public: bool processArguments(S32 argc, ConsoleValueRef *argv); void send(const U8 *buffer, U32 bufferLen); + + ///Send an entire file over tcp + ///@arg fileName Full path to file you want to send + ///@return true if file was sent, false if not (file doesn't exist) + bool sendFile(const char* fileName); + void addToTable(NetSocket newTag); void removeFromTable(); From 0a768090928d07912c14af10cde2bdc86d323f51 Mon Sep 17 00:00:00 2001 From: Nathan Bowhay Date: Thu, 5 Feb 2015 11:44:32 -0800 Subject: [PATCH 17/33] Opened finishLastLine to script Opened finishLastLine to script so you can eat the rest of the lines in script. --- Engine/source/app/net/tcpObject.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Engine/source/app/net/tcpObject.cpp b/Engine/source/app/net/tcpObject.cpp index b156bfa04..28e91ba45 100644 --- a/Engine/source/app/net/tcpObject.cpp +++ b/Engine/source/app/net/tcpObject.cpp @@ -457,6 +457,11 @@ DefineEngineMethod(TCPObject, sendFile, bool, (const char *fileName),, return object->sendFile(fileName); } +DefineEngineMethod(TCPObject, finishLastLine, void, (),, + "@brief Eat the rest of the lines.\n") +{ + object->finishLastLine(); +} DefineEngineMethod(TCPObject, listen, void, (U32 port),, "@brief Start listening on the specified port for connections.\n\n" From 02f859c150d69e6339a59bd41a6035115a66cdb7 Mon Sep 17 00:00:00 2001 From: Nathan Bowhay Date: Wed, 11 Feb 2015 10:53:34 -0800 Subject: [PATCH 18/33] Fixed spacing to fit GG standards. Fixed tabs to 3 spaces. --- Engine/source/console/consoleFunctions.cpp | 364 ++++++++++----------- Engine/source/core/util/str.cpp | 166 +++++----- Engine/source/math/mConsoleFunctions.cpp | 18 +- 3 files changed, 274 insertions(+), 274 deletions(-) diff --git a/Engine/source/console/consoleFunctions.cpp b/Engine/source/console/consoleFunctions.cpp index 1d5403818..4c12f2550 100644 --- a/Engine/source/console/consoleFunctions.cpp +++ b/Engine/source/console/consoleFunctions.cpp @@ -53,129 +53,129 @@ static char scriptFilenameBuffer[1024]; bool isInt(const char* str) { - int len = dStrlen(str); - if(len <= 0) - return 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; - } + // 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; + 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; + 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; - } + // 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; + 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; + 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; + 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); + return (port >= 0 && port <=65535); } //============================================================================= @@ -380,29 +380,29 @@ DefineConsoleFunction( strlenskip, S32, ( const char* str, const char* first, co "@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; + 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; - } - } + //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); + return S32(size); } //----------------------------------------------------------------------------- @@ -831,9 +831,9 @@ DefineConsoleFunction( getFirstNumber, String, ( const char* str ),, "@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); + U32 start; + U32 end; + return String::GetFirstNumber(str, start, end); } //---------------------------------------------------------------- @@ -1031,17 +1031,17 @@ DefineConsoleFunction( strToggleCaseToWords, const char*, ( const char* str ),, "@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 += " "; + 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]; - } + newStr += str[i]; + } - return Con::getReturnBuffer(newStr); + return Con::getReturnBuffer(newStr); } //---------------------------------------------------------------- @@ -1056,7 +1056,7 @@ DefineConsoleFunction( isInt, bool, ( const char* str),, "@endtsexample\n" "@ingroup Strings" ) { - return isInt(str); + return isInt(str); } //---------------------------------------------------------------- @@ -1071,7 +1071,7 @@ DefineConsoleFunction( isFloat, bool, ( const char* str, bool sciOk), (false), "@endtsexample\n" "@ingroup Strings" ) { - return isFloat(str, sciOk); + return isFloat(str, sciOk); } //---------------------------------------------------------------- @@ -1085,13 +1085,13 @@ DefineConsoleFunction( isValidPort, bool, ( const char* str),, "@endtsexample\n" "@ingroup Strings" ) { - if(isInt(str)) - { - U16 port = dAtous(str); - return isValidPort(port); - } - else - return false; + if(isInt(str)) + { + U16 port = dAtous(str); + return isValidPort(port); + } + else + return false; } //---------------------------------------------------------------- @@ -1105,12 +1105,12 @@ DefineConsoleFunction( isValidIP, bool, ( const char* str),, "@endtsexample\n" "@ingroup Strings" ) { - if(dStrcmp(str, "localhost") == 0) - { - return true; - } - else - return isValidIP(str); + if(dStrcmp(str, "localhost") == 0) + { + return true; + } + else + return isValidIP(str); } //---------------------------------------------------------------- @@ -1244,22 +1244,22 @@ DefineEngineFunction( monthNumToStr, String, ( S32 num, bool abbreviate ), (fals "@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 ""; - } + 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), @@ -1267,17 +1267,17 @@ DefineEngineFunction( weekdayNumToStr, String, ( S32 num, bool abbreviate ), (fa "@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 ""; - } + 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 ""; + } } //----------------------------------------------------------------------------- @@ -3071,5 +3071,5 @@ 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; + return MAX_DYNAMIC_VERTS / 2; } \ No newline at end of file diff --git a/Engine/source/core/util/str.cpp b/Engine/source/core/util/str.cpp index 59fd0ab46..f97aa08fa 100644 --- a/Engine/source/core/util/str.cpp +++ b/Engine/source/core/util/str.cpp @@ -1627,100 +1627,100 @@ String String::GetTrailingNumber(const char* str, S32& number) String String::GetFirstNumber(const char* str, U32& startPos, U32& endPos) { - // Check for trivial strings - if (!str || !str[0]) - return String::EmptyString; + // 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; + // 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; + //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++; - } + //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 ""; + //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; + //update our end position at least to the start of our number + endPos = startPos; - //Backup our ptr - const char* backup = p; + //Backup our ptr + const char* backup = p; - //Check for any negative or decimal values - if(startPos > 0) - { - p--; - startPos--; - if(*p == '.') - { - dec = true; + //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--; - } + //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++; - } - } + //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; + //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; + //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++; - } + p++; + endPos++; + } - U32 len = (!isdigit(*p)) ? endPos - startPos : (endPos + 1) - startPos; - return base.substr(startPos, len); + U32 len = (!isdigit(*p)) ? endPos - startPos : (endPos + 1) - startPos; + return base.substr(startPos, len); } diff --git a/Engine/source/math/mConsoleFunctions.cpp b/Engine/source/math/mConsoleFunctions.cpp index f9b352c28..679dad3e2 100644 --- a/Engine/source/math/mConsoleFunctions.cpp +++ b/Engine/source/math/mConsoleFunctions.cpp @@ -96,16 +96,16 @@ DefineConsoleFunction( mFloor, S32, ( F32 v ),, DefineConsoleFunction( mRound, F32, ( F32 v, S32 n ), (0), - "Round v to the nth decimal place or the nearest whole number by default." - "@param v Value to round\n" - "@param n Number of decimal places to round to, 0 by default\n" - "@return The rounded value as a S32." - "@ingroup Math" ) + "Round v to the nth decimal place or the nearest whole number by default." + "@param v Value to round\n" + "@param n Number of decimal places to round to, 0 by default\n" + "@return The rounded value as a S32." + "@ingroup Math" ) { - if(n <= 0) - return mRound(v); - else - return mRound(v, n); + if(n <= 0) + return mRound(v); + else + return mRound(v, n); } DefineConsoleFunction( mCeil, S32, ( F32 v ),, From 2e7018bf681e8c5733cab28cac11f7e2de16e703 Mon Sep 17 00:00:00 2001 From: Nathan Bowhay Date: Wed, 11 Feb 2015 10:55:30 -0800 Subject: [PATCH 19/33] Added type conversions to fix compile errors Added two type conversions that were missing in order to fix some compile errors. --- Engine/source/core/strings/stringFunctions.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Engine/source/core/strings/stringFunctions.h b/Engine/source/core/strings/stringFunctions.h index 0c11d73ed..89601319a 100644 --- a/Engine/source/core/strings/stringFunctions.h +++ b/Engine/source/core/strings/stringFunctions.h @@ -150,11 +150,20 @@ inline U32 dAtoui(const char *str, U32 base = 10) 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) { return strtof(str, NULL); } +inline F64 dAtod(const char *str) +{ + return strtod(str, NULL); +} inline char dToupper(const char c) { From 0915a642a5f96d6076047aa7e2243ea9a4bccb5f Mon Sep 17 00:00:00 2001 From: Nathan Bowhay Date: Thu, 12 Feb 2015 12:07:55 -0800 Subject: [PATCH 20/33] Optimized file reading to buffer Optimized the code that reads the file to the buffer as suggested by @jamesu --- Engine/source/app/net/tcpObject.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/Engine/source/app/net/tcpObject.cpp b/Engine/source/app/net/tcpObject.cpp index 28e91ba45..ac21cd43b 100644 --- a/Engine/source/app/net/tcpObject.cpp +++ b/Engine/source/app/net/tcpObject.cpp @@ -416,11 +416,7 @@ bool TCPObject::sendFile(const char* fileName) //Read each byte into our buffer Vector buffer(readFile.getStreamSize()); - U8 byte; - while(readFile.read(&byte)) - { - buffer.push_back(byte); - } + readFile.read(buffer.size(), &buffer); //Send the buffer send(buffer.address(), buffer.size()); From 1d20f6d26a1fe7f438e0f3540e35b083b843e25b Mon Sep 17 00:00:00 2001 From: Nathan Bowhay Date: Thu, 12 Feb 2015 12:18:34 -0800 Subject: [PATCH 21/33] Fixed spacing issues Changed spacing from tabs to 3 spaces. --- Engine/source/app/net/tcpObject.cpp | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/Engine/source/app/net/tcpObject.cpp b/Engine/source/app/net/tcpObject.cpp index ac21cd43b..d1f127924 100644 --- a/Engine/source/app/net/tcpObject.cpp +++ b/Engine/source/app/net/tcpObject.cpp @@ -407,21 +407,21 @@ void TCPObject::send(const U8 *buffer, U32 len) bool TCPObject::sendFile(const char* fileName) { - //Open the file for reading - FileStream readFile; - if(!readFile.open(fileName, Torque::FS::File::Read)) - { - return false; - } + //Open the file for reading + FileStream readFile; + if(!readFile.open(fileName, Torque::FS::File::Read)) + { + return false; + } - //Read each byte into our buffer - Vector buffer(readFile.getStreamSize()); - readFile.read(buffer.size(), &buffer); + //Read each byte into our buffer + Vector buffer(readFile.getStreamSize()); + readFile.read(buffer.size(), &buffer); - //Send the buffer - send(buffer.address(), buffer.size()); + //Send the buffer + send(buffer.address(), buffer.size()); - return true; + return true; } DefineEngineMethod(TCPObject, send, void, (const char *data),, @@ -450,13 +450,13 @@ DefineEngineMethod(TCPObject, sendFile, bool, (const char *fileName),, "@param fileName The filename of the file to transfer.\n") { - return object->sendFile(fileName); + return object->sendFile(fileName); } DefineEngineMethod(TCPObject, finishLastLine, void, (),, "@brief Eat the rest of the lines.\n") { - object->finishLastLine(); + object->finishLastLine(); } DefineEngineMethod(TCPObject, listen, void, (U32 port),, From 69b1c0072cb7a492f20123be4139733b6ab4c668 Mon Sep 17 00:00:00 2001 From: Nathan Bowhay Date: Thu, 12 Feb 2015 12:19:56 -0800 Subject: [PATCH 22/33] Allowed for WebSocket reading Allowed for WebSocket reading in script. --- Engine/source/app/net/tcpObject.cpp | 47 ++++++++++++++++++++++++++++- Engine/source/app/net/tcpObject.h | 5 ++- 2 files changed, 50 insertions(+), 2 deletions(-) diff --git a/Engine/source/app/net/tcpObject.cpp b/Engine/source/app/net/tcpObject.cpp index d1f127924..06f320576 100644 --- a/Engine/source/app/net/tcpObject.cpp +++ b/Engine/source/app/net/tcpObject.cpp @@ -139,6 +139,11 @@ IMPLEMENT_CALLBACK(TCPObject, onLine, void, (const char* line), (line), "@param line Data sent from the server.\n" ); +IMPLEMENT_CALLBACK(TCPObject, onPacket, bool, (const char* data), (data), + "@brief Called when we get a packet with no newlines or nulls (probably websocket).\n\n" + "@param data Data sent from the server.\n" + "@return true if script handled the packet.\n" + ); IMPLEMENT_CALLBACK(TCPObject, onEndReceive, void, (), (), "@brief Called when we are done reading all lines.\n\n" ); @@ -360,7 +365,7 @@ void TCPObject::onConnectFailed() onConnectFailed_callback(); } -void TCPObject::finishLastLine() +bool TCPObject::finishLastLine() { if(mBufferSize) { @@ -369,6 +374,25 @@ void TCPObject::finishLastLine() dFree(mBuffer); mBuffer = 0; mBufferSize = 0; + + return true; + } + + return false; +} + +bool TCPObject::isBufferEmpty() +{ + return (mBufferSize <= 0); +} + +void TCPObject::emptyBuffer() +{ + if(mBufferSize) + { + dFree(mBuffer); + mBuffer = 0; + mBufferSize = 0; } } @@ -538,6 +562,27 @@ void processConnectedReceiveEvent(NetSocket sock, RawData incomingData) buffer += ret; } + //If our buffer now has something in it then it's probably a web socket packet and lets handle it + if(!tcpo->isBufferEmpty()) + { + //Copy all the data into a string (may be a quicker way of doing this) + U8 *data = (U8*)incomingData.data; + String temp; + for(S32 i = 0; i < incomingData.size; i++) + { + temp += data[i]; + } + + //Send the packet to script + bool handled = tcpo->onPacket_callback(temp); + + //If the script did something with it, clear the buffer + if(handled) + { + tcpo->emptyBuffer(); + } + } + tcpo->onEndReceive_callback(); } diff --git a/Engine/source/app/net/tcpObject.h b/Engine/source/app/net/tcpObject.h index 39b9464ba..9a8b5e40d 100644 --- a/Engine/source/app/net/tcpObject.h +++ b/Engine/source/app/net/tcpObject.h @@ -36,6 +36,7 @@ public: DECLARE_CALLBACK(void, onConnectionRequest, (const char* address, const char* ID)); DECLARE_CALLBACK(void, onLine, (const char* line)); + DECLARE_CALLBACK(bool, onPacket, (const char* data)); DECLARE_CALLBACK(void, onEndReceive, ()); DECLARE_CALLBACK(void, onDNSResolved,()); DECLARE_CALLBACK(void, onDNSFailed, ()); @@ -61,7 +62,9 @@ public: virtual ~TCPObject(); void parseLine(U8 *buffer, U32 *start, U32 bufferLen); - void finishLastLine(); + bool finishLastLine(); + bool isBufferEmpty(); + void emptyBuffer(); static TCPObject *find(NetSocket tag); From cd686a23b3b39c18552c933f76bc6587fc5ce2f3 Mon Sep 17 00:00:00 2001 From: Miodrag Sejic Date: Sat, 28 Feb 2015 21:28:10 +0100 Subject: [PATCH 23/33] +proper buffer size for udp socket MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SkypeLog: 28.02.2015 [17:18:32] Dušan Jocic: when creating user datagram protocol or UDP, old implementation was limiting lan utalization to 1% of our modern 1000Mbps hardwar [17:19:15] Dušan Jocic: that add proper buffer size for udp socket [17:19:43] Dušan Jocic: and lift off limitation what was present there for 10/100 mbps lan --- Engine/source/platform/platformNet.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Engine/source/platform/platformNet.cpp b/Engine/source/platform/platformNet.cpp index acc4e9905..5f7adb856 100644 --- a/Engine/source/platform/platformNet.cpp +++ b/Engine/source/platform/platformNet.cpp @@ -503,7 +503,7 @@ bool Net::openPort(S32 port, bool doBind) } if(error == NoError) - error = setBufferSize(udpSocket, 32768); + error = setBufferSize(udpSocket, 32768*8); if(error == NoError && !useVDP) error = setBroadcast(udpSocket, true); From 27112c468aaa1b1938facf6da679e097595ebbac Mon Sep 17 00:00:00 2001 From: Azaezel Date: Thu, 17 Sep 2015 16:14:49 -0500 Subject: [PATCH 24/33] reversion for https://github.com/GarageGames/Torque3D/commit/a4c09d168029dccac872b5816b21f8298f73f5e9 To be honest, can't remember how I was intending to fix that, but this one's causing it to fail to profile twice in a row, so kill it with fire. --- Engine/source/platform/profiler.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/Engine/source/platform/profiler.cpp b/Engine/source/platform/profiler.cpp index ca34b4593..fb60453fc 100644 --- a/Engine/source/platform/profiler.cpp +++ b/Engine/source/platform/profiler.cpp @@ -214,12 +214,10 @@ Profiler::~Profiler() void Profiler::reset() { mEnabled = false; // in case we're in a profiler call. - ProfilerData * head = mProfileList; - ProfilerData * curr = NULL; - while ((curr = head) != NULL) + while (mProfileList) { - head = head->mNextProfilerData; - free(curr); + free(mProfileList); + mProfileList = NULL; } for(ProfilerRootData *walk = ProfilerRootData::sRootList; walk; walk = walk->mNextRoot) From 691a08bb33341500f405fb60fa00c03fe11f9897 Mon Sep 17 00:00:00 2001 From: Azaezel Date: Tue, 6 Oct 2015 15:34:26 -0500 Subject: [PATCH 25/33] Backend correction for the rigid vs rigid collision resolver: First line is to ensure similar behavior to current regarding pushback on the object doing the colliding. Second line applies an impulse to the rigid that was collided with. --- Engine/source/T3D/rigid.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Engine/source/T3D/rigid.cpp b/Engine/source/T3D/rigid.cpp index e2441441f..31f4d411a 100644 --- a/Engine/source/T3D/rigid.cpp +++ b/Engine/source/T3D/rigid.cpp @@ -156,7 +156,7 @@ bool Rigid::resolveCollision(const Point3F& p, const Point3F &normal, Rigid* rig return false; // Compute impulse - F32 d, n = -nv * (1.0f + restitution * rigid->restitution); + F32 d, n = -nv * (2.0f + restitution * rigid->restitution); Point3F a1,b1,c1; mCross(r1,normal,&a1); invWorldInertia.mulV(a1,&b1); @@ -173,7 +173,7 @@ bool Rigid::resolveCollision(const Point3F& p, const Point3F &normal, Rigid* rig applyImpulse(r1,impulse); impulse.neg(); - applyImpulse(r2,impulse); + rigid->applyImpulse(r2, impulse); return true; } From 28d303c5eaa0f2fb41bf75770ee4e3a1c4122b12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Du=C5=A1an=20Joci=C4=87?= Date: Sat, 20 Feb 2016 21:28:18 +0100 Subject: [PATCH 26/33] Added immutable vertex and index buffers. --- Engine/source/gfx/D3D9/gfxD3D9Device.cpp | 28 ++++++++++++-- Engine/source/gfx/D3D9/gfxD3D9Device.h | 6 ++- .../gfx/D3D9/pc/gfxD3D9PrimitiveBuffer.pc.cpp | 1 + Engine/source/gfx/Null/gfxNullDevice.cpp | 6 ++- Engine/source/gfx/Null/gfxNullDevice.h | 6 ++- Engine/source/gfx/gfxDevice.h | 6 ++- Engine/source/gfx/gfxEnums.h | 7 ++-- Engine/source/gfx/gfxPrimitiveBuffer.cpp | 13 +++++++ Engine/source/gfx/gfxPrimitiveBuffer.h | 2 + Engine/source/gfx/gl/gfxGLDevice.cpp | 37 +++++++++++++++---- Engine/source/gfx/gl/gfxGLDevice.h | 5 ++- Engine/source/gfx/gl/gfxGLEnumTranslate.cpp | 1 + .../renderInstance/renderParticleMgr.cpp | 12 ++---- 13 files changed, 98 insertions(+), 32 deletions(-) diff --git a/Engine/source/gfx/D3D9/gfxD3D9Device.cpp b/Engine/source/gfx/D3D9/gfxD3D9Device.cpp index 2ad550064..d3eb8ed8a 100644 --- a/Engine/source/gfx/D3D9/gfxD3D9Device.cpp +++ b/Engine/source/gfx/D3D9/gfxD3D9Device.cpp @@ -731,7 +731,8 @@ void GFXD3D9Device::setShader( GFXShader *shader, bool force ) //----------------------------------------------------------------------------- GFXPrimitiveBuffer * GFXD3D9Device::allocPrimitiveBuffer( U32 numIndices, U32 numPrimitives, - GFXBufferType bufferType ) + GFXBufferType bufferType, + void* data ) { // Allocate a buffer to return GFXD3D9PrimitiveBuffer * res = new GFXD3D9PrimitiveBuffer(this, numIndices, numPrimitives, bufferType); @@ -741,12 +742,13 @@ GFXPrimitiveBuffer * GFXD3D9Device::allocPrimitiveBuffer( U32 numIndices, D3DPOOL pool = D3DPOOL_DEFAULT; // Assumptions: - // - static buffers are write once, use many + // - static buffers are write rarely, use many // - dynamic buffers are write many, use many // - volatile buffers are write once, use once // You may never read from a buffer. switch(bufferType) { + case GFXBufferTypeImmutable: case GFXBufferTypeStatic: pool = isD3D9Ex() ? D3DPOOL_DEFAULT : D3DPOOL_MANAGED; break; @@ -781,6 +783,14 @@ GFXPrimitiveBuffer * GFXD3D9Device::allocPrimitiveBuffer( U32 numIndices, D3D9Assert(mD3DDevice->CreateIndexBuffer( sizeof(U16) * numIndices , usage, GFXD3D9IndexFormat[GFXIndexFormat16], pool, &res->ib, 0), "Failed to allocate an index buffer."); } + + if(data) + { + void* dest; + res->lock(0, numIndices, &dest); + dMemcpy(dest, data, sizeof(U16) * numIndices); + res->unlock(); + } return res; } @@ -791,7 +801,8 @@ GFXPrimitiveBuffer * GFXD3D9Device::allocPrimitiveBuffer( U32 numIndices, GFXVertexBuffer * GFXD3D9Device::allocVertexBuffer( U32 numVerts, const GFXVertexFormat *vertexFormat, U32 vertSize, - GFXBufferType bufferType ) + GFXBufferType bufferType, + void* data) { PROFILE_SCOPE( GFXD3D9Device_allocVertexBuffer ); @@ -808,7 +819,7 @@ GFXVertexBuffer * GFXD3D9Device::allocVertexBuffer( U32 numVerts, res->mNumVerts = 0; // Assumptions: - // - static buffers are write once, use many + // - static buffers are write rarely, use many // - dynamic buffers are write many, use many // - volatile buffers are write once, use once // You may never read from a buffer. @@ -850,6 +861,15 @@ GFXVertexBuffer * GFXD3D9Device::allocVertexBuffer( U32 numVerts, } res->mNumVerts = numVerts; + + if(data) + { + void* dest; + res->lock(0, numVerts, &dest); + dMemcpy(dest, data, vertSize * numVerts); + res->unlock(); + } + return res; } diff --git a/Engine/source/gfx/D3D9/gfxD3D9Device.h b/Engine/source/gfx/D3D9/gfxD3D9Device.h index c928b1a0d..ef1c9be5d 100644 --- a/Engine/source/gfx/D3D9/gfxD3D9Device.h +++ b/Engine/source/gfx/D3D9/gfxD3D9Device.h @@ -298,10 +298,12 @@ public: virtual GFXVertexBuffer* allocVertexBuffer( U32 numVerts, const GFXVertexFormat *vertexFormat, U32 vertSize, - GFXBufferType bufferType ); + GFXBufferType bufferType, + void* data = NULL ); virtual GFXPrimitiveBuffer *allocPrimitiveBuffer( U32 numIndices, U32 numPrimitives, - GFXBufferType bufferType ); + GFXBufferType bufferType, + void* data = NULL ); virtual void deallocVertexBuffer( GFXD3D9VertexBuffer *vertBuff ); virtual GFXVertexDecl* allocVertexDecl( const GFXVertexFormat *vertexFormat ); virtual void setVertexDecl( const GFXVertexDecl *decl ); diff --git a/Engine/source/gfx/D3D9/pc/gfxD3D9PrimitiveBuffer.pc.cpp b/Engine/source/gfx/D3D9/pc/gfxD3D9PrimitiveBuffer.pc.cpp index 21bb586bb..32251438d 100644 --- a/Engine/source/gfx/D3D9/pc/gfxD3D9PrimitiveBuffer.pc.cpp +++ b/Engine/source/gfx/D3D9/pc/gfxD3D9PrimitiveBuffer.pc.cpp @@ -31,6 +31,7 @@ void GFXD3D9PrimitiveBuffer::lock(U32 indexStart, U32 indexEnd, void **indexPtr) U32 flags=0; switch(mBufferType) { + case GFXBufferTypeImmutable: case GFXBufferTypeStatic: // flags |= D3DLOCK_DISCARD; break; diff --git a/Engine/source/gfx/Null/gfxNullDevice.cpp b/Engine/source/gfx/Null/gfxNullDevice.cpp index 315336c24..f22e3bc7a 100644 --- a/Engine/source/gfx/Null/gfxNullDevice.cpp +++ b/Engine/source/gfx/Null/gfxNullDevice.cpp @@ -276,14 +276,16 @@ GFXNullDevice::~GFXNullDevice() GFXVertexBuffer *GFXNullDevice::allocVertexBuffer( U32 numVerts, const GFXVertexFormat *vertexFormat, U32 vertSize, - GFXBufferType bufferType ) + GFXBufferType bufferType, + void* data ) { return new GFXNullVertexBuffer(GFX, numVerts, vertexFormat, vertSize, bufferType); } GFXPrimitiveBuffer *GFXNullDevice::allocPrimitiveBuffer( U32 numIndices, U32 numPrimitives, - GFXBufferType bufferType) + GFXBufferType bufferType, + void* data ) { return new GFXNullPrimitiveBuffer(GFX, numIndices, numPrimitives, bufferType); } diff --git a/Engine/source/gfx/Null/gfxNullDevice.h b/Engine/source/gfx/Null/gfxNullDevice.h index 5e137cf01..28d6ad4e9 100644 --- a/Engine/source/gfx/Null/gfxNullDevice.h +++ b/Engine/source/gfx/Null/gfxNullDevice.h @@ -115,10 +115,12 @@ protected: virtual GFXVertexBuffer *allocVertexBuffer( U32 numVerts, const GFXVertexFormat *vertexFormat, U32 vertSize, - GFXBufferType bufferType ); + GFXBufferType bufferType, + void* data = NULL ); virtual GFXPrimitiveBuffer *allocPrimitiveBuffer( U32 numIndices, U32 numPrimitives, - GFXBufferType bufferType ); + GFXBufferType bufferType, + void* data = NULL ); virtual GFXVertexDecl* allocVertexDecl( const GFXVertexFormat *vertexFormat ) { return NULL; } virtual void setVertexDecl( const GFXVertexDecl *decl ) { } diff --git a/Engine/source/gfx/gfxDevice.h b/Engine/source/gfx/gfxDevice.h index b9ff01e8c..e8ca6739b 100644 --- a/Engine/source/gfx/gfxDevice.h +++ b/Engine/source/gfx/gfxDevice.h @@ -637,7 +637,8 @@ protected: virtual GFXVertexBuffer *allocVertexBuffer( U32 numVerts, const GFXVertexFormat *vertexFormat, U32 vertSize, - GFXBufferType bufferType ) = 0; + GFXBufferType bufferType, + void* data = NULL ) = 0; /// Called from GFXVertexFormat to allocate the hardware /// specific vertex declaration for rendering. @@ -674,7 +675,8 @@ protected: /// @note All index buffers use unsigned 16-bit indices. virtual GFXPrimitiveBuffer *allocPrimitiveBuffer( U32 numIndices, U32 numPrimitives, - GFXBufferType bufferType ) = 0; + GFXBufferType bufferType, + void* data = NULL ) = 0; /// @} diff --git a/Engine/source/gfx/gfxEnums.h b/Engine/source/gfx/gfxEnums.h index 9dfba2f73..e0c560ac8 100644 --- a/Engine/source/gfx/gfxEnums.h +++ b/Engine/source/gfx/gfxEnums.h @@ -39,8 +39,8 @@ enum GFXBufferType { - GFXBufferTypeStatic, ///< Static vertex buffers are created and filled one time. - ///< incur a performance penalty. Resizing a static vertex buffer is not + GFXBufferTypeStatic, ///< Static vertex buffers are created and rarely updated. + ///< Updating might incur a performance penalty. Resizing a static vertex buffer is not ///< allowed. GFXBufferTypeDynamic, ///< Dynamic vertex buffers are meant for vertices that can be changed ///< often. Vertices written into dynamic vertex buffers will remain valid @@ -48,7 +48,8 @@ enum GFXBufferType ///< allowed. GFXBufferTypeVolatile, ///< Volatile vertex or index buffers are meant for vertices or indices that are essentially ///< only used once. They can be resized without any performance penalty. - + GFXBufferTypeImmutable, ///< Immutable buffers must specify the data when creating the buffer. Cannot be modified. + GFXBufferType_COUNT ///< Number of buffer types. }; diff --git a/Engine/source/gfx/gfxPrimitiveBuffer.cpp b/Engine/source/gfx/gfxPrimitiveBuffer.cpp index 9a0a09119..2a06f53e2 100644 --- a/Engine/source/gfx/gfxPrimitiveBuffer.cpp +++ b/Engine/source/gfx/gfxPrimitiveBuffer.cpp @@ -80,3 +80,16 @@ void GFXPrimitiveBufferHandle::set(GFXDevice *theDevice, U32 indexCount, U32 pri getPointer()->mDebugCreationPath = desc; #endif } + +//----------------------------------------------------------------------------- +// immutable +//----------------------------------------------------------------------------- +void GFXPrimitiveBufferHandle::immutable(GFXDevice *theDevice, U32 indexCount, U32 primitiveCount, void* data, String desc) +{ + StrongRefPtr::operator=( theDevice->allocPrimitiveBuffer(indexCount, primitiveCount, GFXBufferTypeImmutable, data) ); + +#ifdef TORQUE_DEBUG + if( desc.isNotEmpty() ) + getPointer()->mDebugCreationPath = desc; +#endif +} diff --git a/Engine/source/gfx/gfxPrimitiveBuffer.h b/Engine/source/gfx/gfxPrimitiveBuffer.h index c2955786c..9fa6ed14f 100644 --- a/Engine/source/gfx/gfxPrimitiveBuffer.h +++ b/Engine/source/gfx/gfxPrimitiveBuffer.h @@ -140,6 +140,8 @@ public: } void set(GFXDevice *theDevice, U32 indexCount, U32 primitiveCount, GFXBufferType bufferType, String desc = String::EmptyString ); + + void immutable(GFXDevice *theDevice, U32 indexCount, U32 primitiveCount, void* data, String desc = String::EmptyString ); void lock(U16 **indexBuffer, GFXPrimitive **primitiveBuffer = NULL, U32 indexStart = 0, U32 indexEnd = 0) { diff --git a/Engine/source/gfx/gl/gfxGLDevice.cpp b/Engine/source/gfx/gl/gfxGLDevice.cpp index 9cec609d1..b6227faad 100644 --- a/Engine/source/gfx/gl/gfxGLDevice.cpp +++ b/Engine/source/gfx/gl/gfxGLDevice.cpp @@ -355,23 +355,46 @@ GFXPrimitiveBuffer* GFXGLDevice::findVolatilePBO(U32 numIndices, U32 numPrimitiv GFXVertexBuffer *GFXGLDevice::allocVertexBuffer( U32 numVerts, const GFXVertexFormat *vertexFormat, U32 vertSize, - GFXBufferType bufferType ) + GFXBufferType bufferType, + void* data = NULL ) { if(bufferType == GFXBufferTypeVolatile) return findVolatileVBO(numVerts, vertexFormat, vertSize); GFXGLVertexBuffer* buf = new GFXGLVertexBuffer( GFX, numVerts, vertexFormat, vertSize, bufferType ); - buf->registerResourceWithDevice(this); + buf->registerResourceWithDevice(this); + + if(data) + { + void* dest; + buf->lock(0, numVerts, &dest); + dMemcpy(dest, data, vertSize * numVerts); + buf->unlock(); + } + return buf; } -GFXPrimitiveBuffer *GFXGLDevice::allocPrimitiveBuffer( U32 numIndices, U32 numPrimitives, GFXBufferType bufferType ) +GFXPrimitiveBuffer *GFXGLDevice::allocPrimitiveBuffer( U32 numIndices, U32 numPrimitives, GFXBufferType bufferType, void* data ) { + GFXPrimitiveBuffer* buf if(bufferType == GFXBufferTypeVolatile) - return findVolatilePBO(numIndices, numPrimitives); - - GFXGLPrimitiveBuffer* buf = new GFXGLPrimitiveBuffer(GFX, numIndices, numPrimitives, bufferType); - buf->registerResourceWithDevice(this); + { + buf = findVolatilePBO(numIndices, numPrimitives); + } + else + { + buf = new GFXGLPrimitiveBuffer(GFX, numIndices, numPrimitives, bufferType); + buf->registerResourceWithDevice(this); + } + + if(data) + { + void* dest; + buf->lock(0, numIndices, &dest); + dMemcpy(dest, data, sizeof(U16) * numIndices); + buf->unlock(); + } return buf; } diff --git a/Engine/source/gfx/gl/gfxGLDevice.h b/Engine/source/gfx/gl/gfxGLDevice.h index 72193835d..902bfb3f6 100644 --- a/Engine/source/gfx/gl/gfxGLDevice.h +++ b/Engine/source/gfx/gl/gfxGLDevice.h @@ -173,8 +173,9 @@ protected: virtual GFXVertexBuffer *allocVertexBuffer( U32 numVerts, const GFXVertexFormat *vertexFormat, U32 vertSize, - GFXBufferType bufferType ); - virtual GFXPrimitiveBuffer *allocPrimitiveBuffer( U32 numIndices, U32 numPrimitives, GFXBufferType bufferType ); + GFXBufferType bufferType, + void* data = NULL); + virtual GFXPrimitiveBuffer *allocPrimitiveBuffer( U32 numIndices, U32 numPrimitives, GFXBufferType bufferType, void* data = NULL ); // NOTE: The GL device doesn't need a vertex declaration at // this time, but we need to return something to keep the system diff --git a/Engine/source/gfx/gl/gfxGLEnumTranslate.cpp b/Engine/source/gfx/gl/gfxGLEnumTranslate.cpp index 19f6e1c69..e78d807c1 100644 --- a/Engine/source/gfx/gl/gfxGLEnumTranslate.cpp +++ b/Engine/source/gfx/gl/gfxGLEnumTranslate.cpp @@ -45,6 +45,7 @@ void GFXGLEnumTranslate::init() GFXGLBufferType[GFXBufferTypeStatic] = GL_STATIC_DRAW; GFXGLBufferType[GFXBufferTypeDynamic] = GL_DYNAMIC_DRAW; GFXGLBufferType[GFXBufferTypeVolatile] = GL_STREAM_DRAW; + GFXGLBufferType[GFXBufferTypeImmutable] = GL_STATIC_DRAW; // Primitives GFXGLPrimType[GFXPointList] = GL_POINTS; diff --git a/Engine/source/renderInstance/renderParticleMgr.cpp b/Engine/source/renderInstance/renderParticleMgr.cpp index 2b475ab7f..dcae9756c 100644 --- a/Engine/source/renderInstance/renderParticleMgr.cpp +++ b/Engine/source/renderInstance/renderParticleMgr.cpp @@ -338,14 +338,10 @@ void RenderParticleMgr::render( SceneRenderState *state ) void RenderParticleMgr::_initGFXResources() { // Screen quad - U16 *prims = NULL; - mScreenQuadPrimBuff.set(GFX, 4, 2, GFXBufferTypeStatic); - mScreenQuadPrimBuff.lock(&prims); - (*prims++) = 0; - (*prims++) = 1; - (*prims++) = 2; - (*prims++) = 3; - mScreenQuadPrimBuff.unlock(); + U16 prims [] = { + 0, 1, 2, 3, + }; + mScreenQuadPrimBuff.immutable(GFX, 4, 2, prims); mScreenQuadVertBuff.set(GFX, 4, GFXBufferTypeStatic); CompositeQuadVert *verts = mScreenQuadVertBuff.lock(); From c3b1aaae5a09837871bb7e88e836cc534acd70c6 Mon Sep 17 00:00:00 2001 From: irei1as Date: Tue, 23 Feb 2016 17:17:54 +0100 Subject: [PATCH 27/33] New script function to edit created decals TorqueScript function to edit decals created with decalManagerAddDecal. --- Engine/source/T3D/decal/decalManager.cpp | 41 ++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/Engine/source/T3D/decal/decalManager.cpp b/Engine/source/T3D/decal/decalManager.cpp index 6db06a521..d733a78dd 100644 --- a/Engine/source/T3D/decal/decalManager.cpp +++ b/Engine/source/T3D/decal/decalManager.cpp @@ -1744,3 +1744,44 @@ DefineEngineFunction( decalManagerRemoveDecal, bool, ( S32 decalID ),, gDecalManager->removeDecal(inst); return true; } + +DefineEngineFunction( decalManagerEditDecal, bool, ( S32 decalID, Point3F pos, Point3F normal, F32 rotAroundNormal, F32 decalScale ),, + "Edit specified decal of the decal manager.\n" + "@param decalID ID of the decal to edit.\n" + "@param pos World position for the decal.\n" + "@param normal Decal normal vector (if the decal was a tire lying flat on a " + "surface, this is the vector pointing in the direction of the axle).\n" + "@param rotAroundNormal Angle (in radians) to rotate this decal around its normal vector.\n" + "@param decalScale Scale factor applied to the decal.\n" + "@return Returns true if successful, false if decalID not found.\n" + "" ) +{ + DecalInstance *decalInstance = gDecalManager->getDecal( decalID ); + if( !decalInstance ) + return false; + + //Internally we need Point3F tangent instead of the user friendly F32 rotAroundNormal + MatrixF mat( true ); + MathUtils::getMatrixFromUpVector( normal, &mat ); + + AngAxisF rot( normal, rotAroundNormal ); + MatrixF rotmat; + rot.setMatrix( &rotmat ); + mat.mul( rotmat ); + + Point3F tangent; + mat.getColumn( 1, &tangent ); + + //if everything is unchanged just do nothing and return "everything is ok" + if ( pos.equal(decalInstance->mPosition) && normal.equal(decalInstance->mNormal) && tangent.equal(decalInstance->mTangent) && mFabs( decalInstance->mSize - (decalInstance->mDataBlock->size * decalScale) ) < POINT_EPSILON ) return true; + + decalInstance->mPosition = pos; + decalInstance->mNormal = normal; + decalInstance->mTangent = tangent; + decalInstance->mSize = decalInstance->mDataBlock->size * decalScale; + + gDecalManager->clipDecal( decalInstance, NULL, NULL); + + gDecalManager->notifyDecalModified( decalInstance ); + return true; +} From 988bd47d5279d36b11f30c8bc815d9361b6dcd68 Mon Sep 17 00:00:00 2001 From: irei1as Date: Wed, 24 Feb 2016 09:02:07 +0100 Subject: [PATCH 28/33] Visibility change as sugested by dottools --- Engine/source/T3D/decal/decalManager.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Engine/source/T3D/decal/decalManager.cpp b/Engine/source/T3D/decal/decalManager.cpp index d733a78dd..f992705d1 100644 --- a/Engine/source/T3D/decal/decalManager.cpp +++ b/Engine/source/T3D/decal/decalManager.cpp @@ -1773,7 +1773,11 @@ DefineEngineFunction( decalManagerEditDecal, bool, ( S32 decalID, Point3F pos, P mat.getColumn( 1, &tangent ); //if everything is unchanged just do nothing and return "everything is ok" - if ( pos.equal(decalInstance->mPosition) && normal.equal(decalInstance->mNormal) && tangent.equal(decalInstance->mTangent) && mFabs( decalInstance->mSize - (decalInstance->mDataBlock->size * decalScale) ) < POINT_EPSILON ) return true; + if ( pos.equal(decalInstance->mPosition) && + normal.equal(decalInstance->mNormal) && + tangent.equal(decalInstance->mTangent) && + mFabs( decalInstance->mSize - (decalInstance->mDataBlock->size * decalScale) ) < POINT_EPSILON ) + return true; decalInstance->mPosition = pos; decalInstance->mNormal = normal; From f39f7a80c8e50732d3daac9a718a7b22f842aac0 Mon Sep 17 00:00:00 2001 From: Anis Date: Thu, 25 Feb 2016 15:26:25 +0100 Subject: [PATCH 29/33] Update gfxGLDevice.cpp --- Engine/source/gfx/gl/gfxGLDevice.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Engine/source/gfx/gl/gfxGLDevice.cpp b/Engine/source/gfx/gl/gfxGLDevice.cpp index b6227faad..cb5ead912 100644 --- a/Engine/source/gfx/gl/gfxGLDevice.cpp +++ b/Engine/source/gfx/gl/gfxGLDevice.cpp @@ -356,7 +356,7 @@ GFXVertexBuffer *GFXGLDevice::allocVertexBuffer( U32 numVerts, const GFXVertexFormat *vertexFormat, U32 vertSize, GFXBufferType bufferType, - void* data = NULL ) + void* data ) { if(bufferType == GFXBufferTypeVolatile) return findVolatileVBO(numVerts, vertexFormat, vertSize); From 740c999c19f7353ba1ccf2344ddee5640c02cce9 Mon Sep 17 00:00:00 2001 From: Anis Date: Thu, 25 Feb 2016 15:26:52 +0100 Subject: [PATCH 30/33] compile fix --- Engine/source/gfx/gl/gfxGLDevice.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Engine/source/gfx/gl/gfxGLDevice.cpp b/Engine/source/gfx/gl/gfxGLDevice.cpp index cb5ead912..01bbd02ea 100644 --- a/Engine/source/gfx/gl/gfxGLDevice.cpp +++ b/Engine/source/gfx/gl/gfxGLDevice.cpp @@ -377,7 +377,8 @@ GFXVertexBuffer *GFXGLDevice::allocVertexBuffer( U32 numVerts, GFXPrimitiveBuffer *GFXGLDevice::allocPrimitiveBuffer( U32 numIndices, U32 numPrimitives, GFXBufferType bufferType, void* data ) { - GFXPrimitiveBuffer* buf + GFXPrimitiveBuffer* buf; + if(bufferType == GFXBufferTypeVolatile) { buf = findVolatilePBO(numIndices, numPrimitives); From 7418fbfbbdd2a7bebedd8f80a9a732de6544c036 Mon Sep 17 00:00:00 2001 From: Anis Date: Thu, 25 Feb 2016 18:26:15 +0100 Subject: [PATCH 31/33] fixed memory leak in proper way --- Engine/source/platform/profiler.cpp | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/Engine/source/platform/profiler.cpp b/Engine/source/platform/profiler.cpp index fb60453fc..c978b9ac2 100644 --- a/Engine/source/platform/profiler.cpp +++ b/Engine/source/platform/profiler.cpp @@ -214,12 +214,22 @@ Profiler::~Profiler() void Profiler::reset() { mEnabled = false; // in case we're in a profiler call. - while (mProfileList) + ProfilerData * head = mProfileList; + ProfilerData * curr = head; + + while ( curr ) { - free(mProfileList); - mProfileList = NULL; + head = curr->mNextProfilerData; + free( curr ); + + if ( head ) + curr = head; + else + curr = NULL; } + mProfileList = NULL; + for(ProfilerRootData *walk = ProfilerRootData::sRootList; walk; walk = walk->mNextRoot) { walk->mFirstProfilerData = 0; From f701228a37bdd24fe8ca22f6480498fd69ad37f7 Mon Sep 17 00:00:00 2001 From: "Anis A. Hireche" Date: Fri, 26 Feb 2016 15:53:20 +0100 Subject: [PATCH 32/33] Steve Acaster's Ai Poses --- Engine/source/T3D/aiPlayer.cpp | 40 +++++++++++++++++++++++++++++++++ Engine/source/T3D/aiPlayer.h | 4 +++- Engine/source/T3D/player.cpp | 35 +++++++++++++++++++---------- Engine/source/T3D/shapeBase.cpp | 1 + Engine/source/T3D/shapeBase.h | 1 + 5 files changed, 68 insertions(+), 13 deletions(-) diff --git a/Engine/source/T3D/aiPlayer.cpp b/Engine/source/T3D/aiPlayer.cpp index 8992c2c55..8b35e478e 100644 --- a/Engine/source/T3D/aiPlayer.cpp +++ b/Engine/source/T3D/aiPlayer.cpp @@ -563,6 +563,21 @@ bool AIPlayer::getAIMove(Move *movePtr) } } + Pose desiredPose = mPose; + + if ( mSwimming ) + desiredPose = SwimPose; + else if ( mAiPose == 1 && canCrouch() ) + desiredPose = CrouchPose; + else if ( mAiPose == 2 && canProne() ) + desiredPose = PronePose; + else if ( mAiPose == 3 && canSprint() ) + desiredPose = SprintPose; + else if ( canStand() ) + desiredPose = StandPose; + + setPose( desiredPose ); + // Replicate the trigger state into the move so that // triggers can be controlled from scripts. for( U32 i = 0; i < MaxTriggerKeys; i++ ) @@ -591,6 +606,16 @@ bool AIPlayer::getAIMove(Move *movePtr) return true; } +void AIPlayer::setAiPose( S32 pose ) +{ + mAiPose = pose; +} + +S32 AIPlayer::getAiPose() +{ + return mAiPose; +} + /** * Utility function to throw callbacks. Callbacks always occure * on the datablock class. @@ -1348,3 +1373,18 @@ DefineEngineMethod( AIPlayer, clearMoveTriggers, void, ( ),, { object->clearMoveTriggers(); } + +DefineEngineMethod( AIPlayer, setAiPose, void, ( S32 pose ),, + "@brief Sets the AiPose for an AI object.\n" + "@param pose StandPose=0, CrouchPose=1, PronePose=2, SprintPose=3.\n" + "Uses the new AiPose variable from shapebase (as defined in its PlayerData datablock).\n") +{ + object->setAiPose(pose); +} + +DefineEngineMethod( AIPlayer, getAiPose, S32, (),, + "@brief Get the object's current AiPose.\n" + "@return StandPose=0, CrouchPose=1, PronePose=2, SprintPose=3.\n") +{ + return object->getAiPose(); +} diff --git a/Engine/source/T3D/aiPlayer.h b/Engine/source/T3D/aiPlayer.h index d693314eb..f072d2423 100644 --- a/Engine/source/T3D/aiPlayer.h +++ b/Engine/source/T3D/aiPlayer.h @@ -179,7 +179,9 @@ public: void setMoveDestination( const Point3F &location, bool slowdown ); Point3F getMoveDestination() const { return mMoveDestination; } void stopMove(); - + void setAiPose( S32 pose ); + S32 getAiPose(); + // Trigger sets/gets void setMoveTrigger( U32 slot, const bool isSet = true ); bool getMoveTrigger( U32 slot ) const; diff --git a/Engine/source/T3D/player.cpp b/Engine/source/T3D/player.cpp index 6e33284a6..d05609523 100644 --- a/Engine/source/T3D/player.cpp +++ b/Engine/source/T3D/player.cpp @@ -3173,18 +3173,21 @@ void Player::updateMove(const Move* move) // Update the PlayerPose Pose desiredPose = mPose; - if ( mSwimming ) - desiredPose = SwimPose; - else if ( runSurface && move->trigger[sCrouchTrigger] && canCrouch() ) - desiredPose = CrouchPose; - else if ( runSurface && move->trigger[sProneTrigger] && canProne() ) - desiredPose = PronePose; - else if ( move->trigger[sSprintTrigger] && canSprint() ) - desiredPose = SprintPose; - else if ( canStand() ) - desiredPose = StandPose; + if ( !mIsAiControlled ) + { + if ( mSwimming ) + desiredPose = SwimPose; + else if ( runSurface && move->trigger[sCrouchTrigger] && canCrouch() ) + desiredPose = CrouchPose; + else if ( runSurface && move->trigger[sProneTrigger] && canProne() ) + desiredPose = PronePose; + else if ( move->trigger[sSprintTrigger] && canSprint() ) + desiredPose = SprintPose; + else if ( canStand() ) + desiredPose = StandPose; - setPose( desiredPose ); + setPose( desiredPose ); + } } @@ -6186,6 +6189,10 @@ U32 Player::packUpdate(NetConnection *con, U32 mask, BitStream *stream) { stream->writeFlag(mFalling); + stream->writeFlag(mSwimming); + stream->writeFlag(mJetting); + stream->writeInt(mPose, NumPoseBits); + stream->writeInt(mState,NumStateBits); if (stream->writeFlag(mState == RecoverState)) stream->writeInt(mRecoverTicks,PlayerData::RecoverDelayBits); @@ -6282,7 +6289,11 @@ void Player::unpackUpdate(NetConnection *con, BitStream *stream) if (stream->readFlag()) { mPredictionCount = sMaxPredictionTicks; mFalling = stream->readFlag(); - + + mSwimming = stream->readFlag(); + mJetting = stream->readFlag(); + mPose = (Pose)(stream->readInt(NumPoseBits)); + ActionState actionState = (ActionState)stream->readInt(NumStateBits); if (stream->readFlag()) { mRecoverTicks = stream->readInt(PlayerData::RecoverDelayBits); diff --git a/Engine/source/T3D/shapeBase.cpp b/Engine/source/T3D/shapeBase.cpp index 55b258a72..52ea070e3 100644 --- a/Engine/source/T3D/shapeBase.cpp +++ b/Engine/source/T3D/shapeBase.cpp @@ -879,6 +879,7 @@ IMPLEMENT_CALLBACK( ShapeBase, validateCameraFov, F32, (F32 fov), (fov), ShapeBase::ShapeBase() : mDataBlock( NULL ), mIsAiControlled( false ), + mAiPose( 0 ), mControllingObject( NULL ), mMoveMotion( false ), mShapeBaseMount( NULL ), diff --git a/Engine/source/T3D/shapeBase.h b/Engine/source/T3D/shapeBase.h index fcada642b..5a7ff5eb1 100644 --- a/Engine/source/T3D/shapeBase.h +++ b/Engine/source/T3D/shapeBase.h @@ -874,6 +874,7 @@ protected: /// @name Physical Properties /// @{ + S32 mAiPose; ///< Current pose. F32 mEnergy; ///< Current enery level. F32 mRechargeRate; ///< Energy recharge rate (in units/tick). From 0fb62de4b8faa711d8fe544516fed653cb409701 Mon Sep 17 00:00:00 2001 From: "Anis A. Hireche" Date: Fri, 26 Feb 2016 18:41:29 +0100 Subject: [PATCH 33/33] restored old signature of mRound as it's used from scripts. --- Engine/source/math/mConsoleFunctions.cpp | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/Engine/source/math/mConsoleFunctions.cpp b/Engine/source/math/mConsoleFunctions.cpp index 679dad3e2..1a11fe23e 100644 --- a/Engine/source/math/mConsoleFunctions.cpp +++ b/Engine/source/math/mConsoleFunctions.cpp @@ -94,18 +94,13 @@ DefineConsoleFunction( mFloor, S32, ( F32 v ),, return (S32)mFloor( v ); } - -DefineConsoleFunction( mRound, F32, ( F32 v, S32 n ), (0), +DefineConsoleFunction( mRound, S32, ( F32 v ),, "Round v to the nth decimal place or the nearest whole number by default." - "@param v Value to round\n" - "@param n Number of decimal places to round to, 0 by default\n" - "@return The rounded value as a S32." - "@ingroup Math" ) + "@param v Value to roundn" + "@return The rounded value as a S32." + "@ingroup Math" ) { - if(n <= 0) - return mRound(v); - else - return mRound(v, n); + return mRound(v); } DefineConsoleFunction( mCeil, S32, ( F32 v ),,