mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-02-13 19:53:48 +00:00
Merge branch 'Preview4_0' into feature-vfs-security
This commit is contained in:
commit
161ffc62fe
3013 changed files with 348715 additions and 182470 deletions
|
|
@ -399,7 +399,12 @@ U32 ConditionalExprNode::compile(CodeStream& codeStream, U32 ip, TypeReq type)
|
|||
|
||||
TypeReq ConditionalExprNode::getPreferredType()
|
||||
{
|
||||
return trueExpr->getPreferredType();
|
||||
// We can't make it calculate a type based on subsequent expressions as the expression
|
||||
// could be a string, or just numbers. To play it safe, stringify anything that deals with
|
||||
// a conditional, and let the interpreter cast as needed to other types safely.
|
||||
//
|
||||
// See: Regression Test 7 in ScriptTest. It has a string result in the else portion of the ?: ternary.
|
||||
return TypeReqString;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -1620,17 +1620,17 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa
|
|||
++ip; // To skip the recurse flag if the object wasnt found
|
||||
if (curObject)
|
||||
{
|
||||
SimGroup* group = dynamic_cast<SimGroup*>(curObject);
|
||||
if (group)
|
||||
SimSet* set = dynamic_cast<SimSet*>(curObject);
|
||||
if (set)
|
||||
{
|
||||
StringTableEntry intName = StringTable->insert(stack[_STK].getString());
|
||||
bool recurse = code[ip - 1];
|
||||
SimObject* obj = group->findObjectByInternalName(intName, recurse);
|
||||
SimObject* obj = set->findObjectByInternalName(intName, recurse);
|
||||
stack[_STK].setInt(obj ? obj->getId() : 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
Con::errorf(ConsoleLogEntry::Script, "%s: Attempt to use -> on non-group %s of class %s.", getFileLine(ip - 2), curObject->getName(), curObject->getClassName());
|
||||
Con::errorf(ConsoleLogEntry::Script, "%s: Attempt to use -> on non-set %s of class %s.", getFileLine(ip - 2), curObject->getName(), curObject->getClassName());
|
||||
stack[_STK].setInt(0);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,29 +46,28 @@
|
|||
extern StringStack STR;
|
||||
extern ConsoleValueStack<4096> gCallStack;
|
||||
|
||||
Vector<ConsoleValue::ConversionBuffer> ConsoleValue::sConversionBuffer;
|
||||
DataChunker ConsoleValue::sConversionAllocator;
|
||||
|
||||
void ConsoleValue::init()
|
||||
{
|
||||
sConversionBuffer.reserve(8192);
|
||||
sConversionAllocator.setChunkSize(8092);
|
||||
}
|
||||
|
||||
void ConsoleValue::resetConversionBuffer()
|
||||
{
|
||||
sConversionBuffer.resetAndTreatAsScratchBuffer();
|
||||
sConversionAllocator.freeBlocks();
|
||||
}
|
||||
|
||||
char* ConsoleValue::convertToBuffer() const
|
||||
{
|
||||
ConversionBuffer conversion;
|
||||
char* buffer = static_cast<char*>(sConversionAllocator.alloc(32));
|
||||
|
||||
if (type == ConsoleValueType::cvFloat)
|
||||
dSprintf(conversion.buffer, ConversionBufferStride, "%.9g", f);
|
||||
dSprintf(buffer, 32, "%.9g", f);
|
||||
else
|
||||
dSprintf(conversion.buffer, ConversionBufferStride, "%lld", i);
|
||||
dSprintf(buffer, 32, "%lld", i);
|
||||
|
||||
sConversionBuffer.push_back(std::move(conversion));
|
||||
return sConversionBuffer.last().buffer;
|
||||
return buffer;
|
||||
}
|
||||
|
||||
const char* ConsoleValue::getConsoleData() const
|
||||
|
|
|
|||
|
|
@ -146,17 +146,7 @@ class ConsoleValue
|
|||
|
||||
S32 type;
|
||||
|
||||
enum Constants
|
||||
{
|
||||
ConversionBufferStride = 32
|
||||
};
|
||||
|
||||
struct ConversionBuffer
|
||||
{
|
||||
char buffer[ConversionBufferStride];
|
||||
};
|
||||
|
||||
static Vector<ConversionBuffer> sConversionBuffer;
|
||||
static DataChunker sConversionAllocator;
|
||||
|
||||
char* convertToBuffer() const;
|
||||
|
||||
|
|
@ -239,8 +229,10 @@ public:
|
|||
return f;
|
||||
if (type == ConsoleValueType::cvInteger)
|
||||
return i;
|
||||
if (isStringType())
|
||||
return dAtof(s);
|
||||
if (type == ConsoleValueType::cvSTEntry)
|
||||
return s == StringTable->EmptyString() ? 0.0f : dAtof(s);
|
||||
if (type == ConsoleValueType::cvString)
|
||||
return dStrcmp(s, "") == 0 ? 0.0f : dAtof(s);
|
||||
return dAtof(getConsoleData());
|
||||
}
|
||||
|
||||
|
|
@ -250,8 +242,10 @@ public:
|
|||
return i;
|
||||
if (type == ConsoleValueType::cvFloat)
|
||||
return f;
|
||||
if (isStringType())
|
||||
return dAtoi(s);
|
||||
if (type == ConsoleValueType::cvSTEntry)
|
||||
return s == StringTable->EmptyString() ? 0 : dAtoi(s);
|
||||
if (type == ConsoleValueType::cvString)
|
||||
return dStrcmp(s, "") == 0 ? 0 : dAtoi(s);
|
||||
return dAtoi(getConsoleData());
|
||||
}
|
||||
|
||||
|
|
@ -275,8 +269,10 @@ public:
|
|||
return (bool)i;
|
||||
if (type == ConsoleValueType::cvFloat)
|
||||
return (bool)f;
|
||||
if (isStringType())
|
||||
return dAtob(s);
|
||||
if (type == ConsoleValueType::cvSTEntry)
|
||||
return s == StringTable->EmptyString() ? false : dAtob(s);
|
||||
if (type == ConsoleValueType::cvString)
|
||||
return dStrcmp(s, "") == 0 ? false : dAtob(s);
|
||||
return dAtob(getConsoleData());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2859,3 +2859,21 @@ DefineEngineFunction(getTimestamp, const char*, (), ,
|
|||
|
||||
return returnBuffer;
|
||||
}
|
||||
|
||||
#ifdef TORQUE_TOOLS
|
||||
DefineEngineFunction(systemCommand, S32, (const char* commandLineAction, const char* callBackFunction), (""), "")
|
||||
{
|
||||
if (commandLineAction != "")
|
||||
{
|
||||
S32 result = system(commandLineAction);
|
||||
|
||||
if (callBackFunction != "" && callBackFunction[0])
|
||||
{
|
||||
if (Con::isFunction(callBackFunction))
|
||||
Con::executef(callBackFunction, result);
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -387,7 +387,17 @@ DefineEngineFunction(isFile, bool, ( const char* fileName ),,
|
|||
|
||||
"@ingroup FileSystem")
|
||||
{
|
||||
return Torque::FS::IsFile(fileName);
|
||||
Torque::Path givenPath(fileName);
|
||||
|
||||
if (givenPath.getFileName().isEmpty() && givenPath.getExtension().isNotEmpty())
|
||||
{
|
||||
//specially named or hidden files, like .gitignore parse incorrectly due to having
|
||||
//"no" filename, so we adjust that
|
||||
givenPath.setFileName(String(".") + givenPath.getExtension());
|
||||
givenPath.setExtension("");
|
||||
}
|
||||
|
||||
return Torque::FS::IsFile(givenPath);
|
||||
}
|
||||
|
||||
DefineEngineFunction(isScriptFile, bool, (const char* fileName), ,
|
||||
|
|
@ -860,4 +870,20 @@ DefineEngineFunction( createPath, bool, ( const char* path ),,
|
|||
return Torque::FS::CreatePath(path);
|
||||
}
|
||||
|
||||
DefineEngineFunction(deleteDirectory, bool, (const char* path), ,
|
||||
"@brief Delete a directory from the hard drive\n\n"
|
||||
|
||||
"@param path Name and path of the folder to delete\n"
|
||||
"@note THERE IS NO RECOVERY FROM THIS. Deleted files are gone for good.\n"
|
||||
"@return True if file was successfully deleted\n"
|
||||
"@ingroup FileSystem")
|
||||
{
|
||||
static char fileName[1024];
|
||||
static char sandboxFileName[1024];
|
||||
|
||||
Con::expandScriptFilename(fileName, sizeof(fileName), path);
|
||||
Platform::makeFullPathName(fileName, sandboxFileName, sizeof(sandboxFileName));
|
||||
|
||||
return Platform::deleteDirectory(sandboxFileName);
|
||||
}
|
||||
#endif // TORQUE_TOOLS
|
||||
|
|
|
|||
|
|
@ -68,6 +68,8 @@ namespace Sim
|
|||
ImplementNamedSet(SFXAmbienceSet)
|
||||
ImplementNamedSet(TerrainMaterialSet)
|
||||
ImplementNamedSet(DataBlockSet);
|
||||
ImplementNamedSet(ForestBrushSet);
|
||||
ImplementNamedSet(ForestItemDataSet);
|
||||
ImplementNamedGroup(ActionMapGroup)
|
||||
ImplementNamedGroup(ClientGroup)
|
||||
ImplementNamedGroup(GuiGroup)
|
||||
|
|
|
|||
|
|
@ -107,6 +107,8 @@ namespace Sim
|
|||
DeclareNamedSet(SFXAmbienceSet);
|
||||
DeclareNamedSet(TerrainMaterialSet);
|
||||
DeclareNamedSet(DataBlockSet);
|
||||
DeclareNamedSet(ForestBrushSet);
|
||||
DeclareNamedSet(ForestItemDataSet);
|
||||
DeclareNamedGroup(ActionMapGroup)
|
||||
DeclareNamedGroup(ClientGroup)
|
||||
DeclareNamedGroup(GuiGroup)
|
||||
|
|
|
|||
|
|
@ -565,6 +565,8 @@ void init()
|
|||
InstantiateNamedSet(SFXAmbienceSet);
|
||||
InstantiateNamedSet(TerrainMaterialSet);
|
||||
InstantiateNamedSet(DataBlockSet);
|
||||
InstantiateNamedSet(ForestBrushSet);
|
||||
InstantiateNamedSet(ForestItemDataSet);
|
||||
InstantiateNamedGroup(ActionMapGroup);
|
||||
InstantiateNamedGroup(ClientGroup);
|
||||
InstantiateNamedGroup(GuiGroup);
|
||||
|
|
|
|||
|
|
@ -77,6 +77,7 @@ SimObject::SimObject()
|
|||
mObjectName = NULL;
|
||||
mOriginalName = NULL;
|
||||
mInternalName = NULL;
|
||||
mInheritFrom = NULL;
|
||||
nextNameObject = nullptr;
|
||||
nextManagerNameObject = nullptr;
|
||||
nextIdObject = NULL;
|
||||
|
|
@ -154,6 +155,9 @@ void SimObject::initPersistFields()
|
|||
|
||||
addProtectedField( "name", TypeName, Offset(mObjectName, SimObject), &setProtectedName, &defaultProtectedGetFn,
|
||||
"Optional global name of this object." );
|
||||
|
||||
addProtectedField("inheritFrom", TypeString, Offset(mInheritFrom, SimObject), &setInheritFrom, &defaultProtectedGetFn,
|
||||
"Optional Name of object to inherit from as a parent.");
|
||||
|
||||
endGroup( "Ungrouped" );
|
||||
|
||||
|
|
@ -300,6 +304,10 @@ bool SimObject::writeField(StringTableEntry fieldname, const char* value)
|
|||
void SimObject::writeFields(Stream &stream, U32 tabStop)
|
||||
{
|
||||
// Write static fields.
|
||||
|
||||
// Create a default object of the same type
|
||||
ConsoleObject* defaultConObject = ConsoleObject::create(getClassName());
|
||||
SimObject* defaultObject = dynamic_cast<SimObject*>(defaultConObject);
|
||||
|
||||
const AbstractClassRep::FieldList &list = getFieldList();
|
||||
|
||||
|
|
@ -328,6 +336,11 @@ void SimObject::writeFields(Stream &stream, U32 tabStop)
|
|||
if (!writeField(f->pFieldname, valCopy))
|
||||
continue;
|
||||
|
||||
//If the field hasn't been changed from the default value, then don't bother writing it out
|
||||
const char* defaultValueCheck = defaultObject->getDataField(f->pFieldname, array);
|
||||
if (defaultValueCheck && defaultValueCheck[0] != '\0' && dStricmp(defaultValueCheck, valCopy) == 0)
|
||||
continue;
|
||||
|
||||
val = valCopy;
|
||||
|
||||
U32 expandedBufferSize = ( nBufferSize * 2 ) + dStrlen(f->pFieldname) + 32;
|
||||
|
|
@ -362,6 +375,9 @@ void SimObject::writeFields(Stream &stream, U32 tabStop)
|
|||
|
||||
if(mFieldDictionary && mCanSaveFieldDictionary)
|
||||
mFieldDictionary->writeFields(this, stream, tabStop);
|
||||
|
||||
// Cleanup our created default object
|
||||
delete defaultConObject;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
@ -1133,7 +1149,7 @@ const char *SimObject::getPrefixedDataField(StringTableEntry fieldName, const ch
|
|||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void SimObject::setPrefixedDataField(StringTableEntry fieldName, const char *array, const char *value)
|
||||
void SimObject::setPrefixedDataField(StringTableEntry fieldName, const char *_array, const char *value)
|
||||
{
|
||||
// Sanity!
|
||||
AssertFatal(fieldName != NULL, "Cannot set object field value with NULL field name.");
|
||||
|
|
@ -1142,7 +1158,7 @@ void SimObject::setPrefixedDataField(StringTableEntry fieldName, const char *arr
|
|||
// Set value without prefix if there's no value.
|
||||
if (*value == 0)
|
||||
{
|
||||
setDataField(fieldName, NULL, value);
|
||||
setDataField(fieldName, _array, value);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1156,7 +1172,7 @@ void SimObject::setPrefixedDataField(StringTableEntry fieldName, const char *arr
|
|||
if (fieldPrefix == StringTable->EmptyString())
|
||||
{
|
||||
// No, so set the data field in the usual way.
|
||||
setDataField(fieldName, NULL, value);
|
||||
setDataField(fieldName, _array, value);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1167,23 +1183,23 @@ void SimObject::setPrefixedDataField(StringTableEntry fieldName, const char *arr
|
|||
if (dStrnicmp(value, fieldPrefix, fieldPrefixLength) != 0)
|
||||
{
|
||||
// No, so set the data field in the usual way.
|
||||
setDataField(fieldName, NULL, value);
|
||||
setDataField(fieldName, _array, value);
|
||||
return;
|
||||
}
|
||||
|
||||
// Yes, so set the data excluding the prefix.
|
||||
setDataField(fieldName, NULL, value + fieldPrefixLength);
|
||||
setDataField(fieldName, _array, value + fieldPrefixLength);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
const char *SimObject::getPrefixedDynamicDataField(StringTableEntry fieldName, const char *array, const S32 fieldType)
|
||||
const char *SimObject::getPrefixedDynamicDataField(StringTableEntry fieldName, const char *_array, const S32 fieldType)
|
||||
{
|
||||
// Sanity!
|
||||
AssertFatal(fieldName != NULL, "Cannot get field value with NULL field name.");
|
||||
|
||||
// Fetch field value.
|
||||
const char* pFieldValue = getDataField(fieldName, array);
|
||||
const char* pFieldValue = getDataField(fieldName, _array);
|
||||
|
||||
// Sanity.
|
||||
AssertFatal(pFieldValue != NULL, "Field value cannot be NULL.");
|
||||
|
|
@ -2235,10 +2251,10 @@ bool SimObject::setProtectedName(void *obj, const char *index, const char *data)
|
|||
{
|
||||
if (preventNameChanging)
|
||||
return false;
|
||||
SimObject *object = static_cast<SimObject*>(obj);
|
||||
|
||||
if ( object->isProperlyAdded() )
|
||||
object->assignName( data );
|
||||
SimObject* object = static_cast<SimObject*>(obj);
|
||||
|
||||
if (object->isProperlyAdded())
|
||||
object->assignName(data);
|
||||
|
||||
// always return false because we assign the name here
|
||||
return false;
|
||||
|
|
@ -2246,6 +2262,31 @@ bool SimObject::setProtectedName(void *obj, const char *index, const char *data)
|
|||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool SimObject::setInheritFrom(void* obj, const char* index, const char* data)
|
||||
{
|
||||
SimObject* object = static_cast<SimObject*>(obj);
|
||||
|
||||
SimObject* parent;
|
||||
if (Sim::findObject(data, parent))
|
||||
{
|
||||
object->setCopySource(parent);
|
||||
object->assignFieldsFrom(parent);
|
||||
|
||||
// copy any substitution statements
|
||||
SimDataBlock* parent_db = dynamic_cast<SimDataBlock*>(parent);
|
||||
if (parent_db)
|
||||
{
|
||||
SimDataBlock* currentNewObject_db = dynamic_cast<SimDataBlock*>(object);
|
||||
if (currentNewObject_db)
|
||||
currentNewObject_db->copySubstitutionsFrom(parent_db);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void SimObject::inspectPreApply()
|
||||
{
|
||||
}
|
||||
|
|
|
|||
|
|
@ -299,6 +299,8 @@ class SimObject: public ConsoleObject, public TamlCallbacks
|
|||
SimObject* nextManagerNameObject;
|
||||
SimObject* nextIdObject;
|
||||
|
||||
StringTableEntry mInheritFrom;
|
||||
|
||||
/// SimGroup we're contained in, if any.
|
||||
SimGroup* mGroup;
|
||||
|
||||
|
|
@ -380,6 +382,9 @@ class SimObject: public ConsoleObject, public TamlCallbacks
|
|||
// Object name protected set method
|
||||
static bool setProtectedName(void *object, const char *index, const char *data);
|
||||
|
||||
// Sets object to inherit default values from
|
||||
static bool setInheritFrom(void* object, const char* index, const char* data);
|
||||
|
||||
public:
|
||||
inline void setProgenitorFile(const char* pFile) { mProgenitorFile = StringTable->insert(pFile); }
|
||||
inline StringTableEntry getProgenitorFile(void) const { return mProgenitorFile; }
|
||||
|
|
|
|||
|
|
@ -1079,6 +1079,22 @@ TEST(Script, MiscRegressions)
|
|||
)");
|
||||
|
||||
ASSERT_EQ(regression6.getBool(), true);
|
||||
|
||||
ConsoleValue regression7 = RunScript(R"(
|
||||
function Tween::vectorAdd(%v1, %v2)
|
||||
{
|
||||
%temp = "";
|
||||
for (%i = 0; %i < getWordCount(%v1); %i++) {
|
||||
%e = getWord(%v1, %i) + getWord(%v2, %i);
|
||||
%temp = %i == 0 ? %e : %temp SPC %e;
|
||||
}
|
||||
|
||||
return %temp;
|
||||
}
|
||||
return Tween::vectorAdd("1 2 3", "4 5 6");
|
||||
)");
|
||||
|
||||
ASSERT_STREQ(regression7.getString(), "5 7 9");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue