* BugFix: Correct a crash in the variable inspector caused by keeping pointers into tVector managed memory.

This commit is contained in:
Robert MacGregor 2021-11-02 10:18:57 -04:00
parent a0e0e1f220
commit b33e1b400b
3 changed files with 45 additions and 39 deletions

View file

@ -32,6 +32,7 @@ GuiVariableInspector::GuiVariableInspector() : mAutoUpdate(true)
GuiVariableInspector::~GuiVariableInspector() GuiVariableInspector::~GuiVariableInspector()
{ {
} }
IMPLEMENT_CONOBJECT(GuiVariableInspector); IMPLEMENT_CONOBJECT(GuiVariableInspector);
@ -75,7 +76,7 @@ void GuiVariableInspector::update()
for (U32 g = 0; g < mGroups.size(); g++) for (U32 g = 0; g < mGroups.size(); g++)
{ {
if (mGroups[g]->getCaption().equal(mFields[i].mGroup)) if (mGroups[g]->getCaption().equal(mFields[i]->mGroup))
{ {
group = static_cast<GuiInspectorVariableGroup*>(mGroups[g]); group = static_cast<GuiInspectorVariableGroup*>(mGroups[g]);
break; break;
@ -89,14 +90,14 @@ void GuiVariableInspector::update()
group->setHeaderHidden(false); group->setHeaderHidden(false);
group->setCanCollapse(true); group->setCanCollapse(true);
group->mParent = this; group->mParent = this;
group->setCaption(mFields[i].mGroup); group->setCaption(mFields[i]->mGroup);
group->registerObject(); group->registerObject();
mGroups.push_back(group); mGroups.push_back(group);
addObject(group); addObject(group);
} }
group->addField(&mFields[i]); group->addField(mFields[i]);
} }
//And now, cue our update for the groups themselves //And now, cue our update for the groups themselves
@ -148,26 +149,26 @@ void GuiVariableInspector::setGroupsExpanded(bool isExpanded)
void GuiVariableInspector::addField(const char* name, const char* label, const char* typeName, const char* description, void GuiVariableInspector::addField(const char* name, const char* label, const char* typeName, const char* description,
const char* defaultValue, const char* dataValues, const char* callbackName, SimObject* ownerObj) const char* defaultValue, const char* dataValues, const char* callbackName, SimObject* ownerObj)
{ {
VariableField newField; VariableField* newField = new VariableField;
newField.mFieldName = StringTable->insert(name); newField->mFieldName = StringTable->insert(name);
newField.mFieldLabel = StringTable->insert(label, true); newField->mFieldLabel = StringTable->insert(label, true);
newField.mFieldTypeName = StringTable->insert(typeName); newField->mFieldTypeName = StringTable->insert(typeName);
newField.mFieldDescription = StringTable->insert(description); newField->mFieldDescription = StringTable->insert(description);
newField.mDefaultValue = StringTable->insert(defaultValue); newField->mDefaultValue = StringTable->insert(defaultValue);
newField.mDataValues = String(dataValues); newField->mDataValues = String(dataValues);
newField.mGroup = mCurrentGroup; newField->mGroup = mCurrentGroup;
newField.mSetCallbackName = StringTable->insert(callbackName); newField->mSetCallbackName = StringTable->insert(callbackName);
newField.mEnabled = true; newField->mEnabled = true;
newField.mOwnerObject = ownerObj; newField->mOwnerObject = ownerObj;
//establish the field on the ownerObject(if we have one) //establish the field on the ownerObject(if we have one)
//This way, we can let the field hook into the object's field and modify it when changed //This way, we can let the field hook into the object's field and modify it when changed
if (newField.mOwnerObject != nullptr) if (newField->mOwnerObject != nullptr)
{ {
if (!newField.mOwnerObject->isField(newField.mFieldName)) if (!newField->mOwnerObject->isField(newField->mFieldName))
{ {
newField.mOwnerObject->setDataField(newField.mFieldName, NULL, newField.mDefaultValue); newField->mOwnerObject->setDataField(newField->mFieldName, NULL, newField->mDefaultValue);
} }
} }
@ -175,40 +176,40 @@ void GuiVariableInspector::addField(const char* name, const char* label, const c
//find the field type //find the field type
S32 fieldTypeMask = -1; S32 fieldTypeMask = -1;
if (newField.mFieldTypeName == StringTable->insert("int")) if (newField->mFieldTypeName == StringTable->insert("int"))
fieldTypeMask = TypeS32; fieldTypeMask = TypeS32;
else if (newField.mFieldTypeName == StringTable->insert("float")) else if (newField->mFieldTypeName == StringTable->insert("float"))
fieldTypeMask = TypeF32; fieldTypeMask = TypeF32;
else if (newField.mFieldTypeName == StringTable->insert("vector")) else if (newField->mFieldTypeName == StringTable->insert("vector"))
fieldTypeMask = TypePoint3F; fieldTypeMask = TypePoint3F;
else if (newField.mFieldTypeName == StringTable->insert("vector2")) else if (newField->mFieldTypeName == StringTable->insert("vector2"))
fieldTypeMask = TypePoint2F; fieldTypeMask = TypePoint2F;
else if (newField.mFieldTypeName == StringTable->insert("material")) else if (newField->mFieldTypeName == StringTable->insert("material"))
fieldTypeMask = TypeMaterialAssetId; fieldTypeMask = TypeMaterialAssetId;
else if (newField.mFieldTypeName == StringTable->insert("image")) else if (newField->mFieldTypeName == StringTable->insert("image"))
fieldTypeMask = TypeImageAssetId; fieldTypeMask = TypeImageAssetId;
else if (newField.mFieldTypeName == StringTable->insert("shape")) else if (newField->mFieldTypeName == StringTable->insert("shape"))
fieldTypeMask = TypeShapeAssetId; fieldTypeMask = TypeShapeAssetId;
else if (newField.mFieldTypeName == StringTable->insert("bool")) else if (newField->mFieldTypeName == StringTable->insert("bool"))
fieldTypeMask = TypeBool; fieldTypeMask = TypeBool;
else if (newField.mFieldTypeName == StringTable->insert("object")) else if (newField->mFieldTypeName == StringTable->insert("object"))
fieldTypeMask = TypeSimObjectPtr; fieldTypeMask = TypeSimObjectPtr;
else if (newField.mFieldTypeName == StringTable->insert("string")) else if (newField->mFieldTypeName == StringTable->insert("string"))
fieldTypeMask = TypeString; fieldTypeMask = TypeString;
else if (newField.mFieldTypeName == StringTable->insert("colorI")) else if (newField->mFieldTypeName == StringTable->insert("colorI"))
fieldTypeMask = TypeColorI; fieldTypeMask = TypeColorI;
else if (newField.mFieldTypeName == StringTable->insert("colorF")) else if (newField->mFieldTypeName == StringTable->insert("colorF"))
fieldTypeMask = TypeColorF; fieldTypeMask = TypeColorF;
else if (newField.mFieldTypeName == StringTable->insert("ease")) else if (newField->mFieldTypeName == StringTable->insert("ease"))
fieldTypeMask = TypeEaseF; fieldTypeMask = TypeEaseF;
else if (newField.mFieldTypeName == StringTable->insert("command")) else if (newField->mFieldTypeName == StringTable->insert("command"))
fieldTypeMask = TypeCommand; fieldTypeMask = TypeCommand;
else if (newField.mFieldTypeName == StringTable->insert("filename")) else if (newField->mFieldTypeName == StringTable->insert("filename"))
fieldTypeMask = TypeStringFilename; fieldTypeMask = TypeStringFilename;
else else
fieldTypeMask = -1; fieldTypeMask = -1;
newField.mFieldType = fieldTypeMask; newField->mFieldType = fieldTypeMask;
// //
mFields.push_back(newField); mFields.push_back(newField);
@ -226,6 +227,13 @@ void GuiVariableInspector::addCallbackField(const char* name, const char* label,
void GuiVariableInspector::clearFields() void GuiVariableInspector::clearFields()
{ {
mGroups.clear(); mGroups.clear();
// Before clearing the fields, dealloc the memory first
for (U32 iteration = 0; iteration < mFields.size(); ++iteration)
{
delete mFields[iteration];
}
mFields.clear(); mFields.clear();
clear(); clear();
@ -237,9 +245,9 @@ void GuiVariableInspector::setFieldEnabled(const char* name, bool enabled)
String fieldName = name; String fieldName = name;
for (U32 i = 0; i < mFields.size(); i++) for (U32 i = 0; i < mFields.size(); i++)
{ {
if (fieldName.equal(mFields[i].mFieldName, String::NoCase)) if (fieldName.equal(mFields[i]->mFieldName, String::NoCase))
{ {
mFields[i].mEnabled = enabled; mFields[i]->mEnabled = enabled;
update(); update();
return; return;
} }

View file

@ -65,7 +65,7 @@ public:
protected: protected:
Vector<VariableField> mFields; Vector<VariableField*> mFields;
String mCurrentGroup; String mCurrentGroup;

View file

@ -1583,7 +1583,6 @@ bool TSShape::addSequence(const Torque::Path& path, const String& fromSeq,
Con::errorf("%s groundTranslations out of bounds! [%i/%i] ", path.getFullPath().c_str(), groundBase + i, srcShape->groundTranslations.size()); Con::errorf("%s groundTranslations out of bounds! [%i/%i] ", path.getFullPath().c_str(), groundBase + i, srcShape->groundTranslations.size());
offset = srcShape->groundTranslations.size() - 1; offset = srcShape->groundTranslations.size() - 1;
} }
groundTranslations.push_back(srcShape->groundTranslations[offset]); groundTranslations.push_back(srcShape->groundTranslations[offset]);
S32 offset2 = groundBase + i; S32 offset2 = groundBase + i;
@ -1592,7 +1591,6 @@ bool TSShape::addSequence(const Torque::Path& path, const String& fromSeq,
Con::errorf("%s groundRotations out of bounds! [%i/%i] ", path.getFullPath().c_str(), groundBase + i, srcShape->groundRotations.size()); Con::errorf("%s groundRotations out of bounds! [%i/%i] ", path.getFullPath().c_str(), groundBase + i, srcShape->groundRotations.size());
offset2 = srcShape->groundRotations.size() - 1; offset2 = srcShape->groundRotations.size() - 1;
} }
groundRotations.push_back(srcShape->groundRotations[offset2]); groundRotations.push_back(srcShape->groundRotations[offset2]);
} }