From fdadfa5eeadfaf3fd48cad639c30fce451ba1cc5 Mon Sep 17 00:00:00 2001 From: Areloch Date: Tue, 30 Apr 2024 18:44:17 -0500 Subject: [PATCH 1/2] Adds handling for complex fields such as Point2, Point3 and Point4's to be able to apply value changes to only one axis across a multi-object set without affecting other axis' --- .../source/gui/editor/guiInspectorTypes.cpp | 72 ++++++---- Engine/source/gui/editor/guiInspectorTypes.h | 6 +- Engine/source/gui/editor/inspector/field.cpp | 129 ++++++++++++++++++ Engine/source/gui/editor/inspector/field.h | 2 + 4 files changed, 179 insertions(+), 30 deletions(-) diff --git a/Engine/source/gui/editor/guiInspectorTypes.cpp b/Engine/source/gui/editor/guiInspectorTypes.cpp index b8fb74148..f18166be1 100644 --- a/Engine/source/gui/editor/guiInspectorTypes.cpp +++ b/Engine/source/gui/editor/guiInspectorTypes.cpp @@ -1765,12 +1765,12 @@ void GuiInspectorTypeSFXSourceName::consoleInit() void GuiInspectorType2DValue::constructEditControlChildren(GuiControl* retCtrl, S32 width) { - mCtrlX = new GuiTextEditSliderCtrl(); + mCtrlX = new GuiTextEditCtrl(); _registerEditControl(mCtrlX, "x"); mLabelX = new GuiControl(); _registerEditControl(mLabelX, "lx"); - mCtrlY = new GuiTextEditSliderCtrl(); + mCtrlY = new GuiTextEditCtrl(); _registerEditControl(mCtrlY, "y"); mLabelY = new GuiControl(); _registerEditControl(mLabelY, "ly"); @@ -1824,14 +1824,17 @@ void GuiInspectorType2DValue::constructEditControlChildren(GuiControl* retCtrl, mCtrlX->setPosition(Point2I(labelWidth, 0)); mCtrlY->setPosition(Point2I(labelWidth, 0)); - char szBuffer[512]; - dSprintf(szBuffer, 512, "%d.apply(%d.getText() SPC %d.getText());", getId(), mCtrlX->getId(), mCtrlY->getId()); + char szXCBuffer[512]; + dSprintf(szXCBuffer, 512, "%d.applyWord(0, %d.getText());", getId(), mCtrlX->getId()); - mCtrlX->setField("AltCommand", szBuffer); - mCtrlY->setField("AltCommand", szBuffer); + char szYCBuffer[512]; + dSprintf(szYCBuffer, 512, "%d.applyWord(1, %d.getText());", getId(), mCtrlY->getId()); - mCtrlX->setField("Validate", szBuffer); - mCtrlY->setField("Validate", szBuffer); + mCtrlX->setField("AltCommand", szXCBuffer); + mCtrlY->setField("AltCommand", szYCBuffer); + + mCtrlX->setField("Validate", szXCBuffer); + mCtrlY->setField("Validate", szYCBuffer); mContainerX = new GuiControl(); mContainerX->setDataField(StringTable->insert("profile"), NULL, "GuiInspectorTextEditProfile"); @@ -1933,7 +1936,7 @@ void GuiInspectorType3DValue::constructEditControlChildren(GuiControl* retCtrl, { Parent::constructEditControlChildren(retCtrl, width); - mCtrlZ = new GuiTextEditSliderCtrl(); + mCtrlZ = new GuiTextEditCtrl(); _registerEditControl(mCtrlZ, "z"); mLabelZ = new GuiControl(); _registerEditControl(mLabelZ, "lz"); @@ -1953,16 +1956,22 @@ void GuiInspectorType3DValue::constructEditControlChildren(GuiControl* retCtrl, mCtrlZ->setPosition(Point2I(labelWidth, 0)); - char szBuffer[512]; - dSprintf(szBuffer, 512, "%d.apply(%d.getText() SPC %d.getText() SPC %d.getText());", getId(), mCtrlX->getId(), mCtrlY->getId(), mCtrlZ->getId()); + char szXCBuffer[512]; + dSprintf(szXCBuffer, 512, "%d.applyWord(0, %d.getText());", getId(), mCtrlX->getId()); - mCtrlX->setField("AltCommand", szBuffer); - mCtrlY->setField("AltCommand", szBuffer); - mCtrlZ->setField("AltCommand", szBuffer); + char szYCBuffer[512]; + dSprintf(szYCBuffer, 512, "%d.applyWord(1, %d.getText());", getId(), mCtrlY->getId()); - mCtrlX->setField("Validate", szBuffer); - mCtrlY->setField("Validate", szBuffer); - mCtrlZ->setField("Validate", szBuffer); + char szZCBuffer[512]; + dSprintf(szZCBuffer, 512, "%d.applyWord(2, %d.getText());", getId(), mCtrlZ->getId()); + + mCtrlX->setField("AltCommand", szXCBuffer); + mCtrlY->setField("AltCommand", szYCBuffer); + mCtrlZ->setField("AltCommand", szZCBuffer); + + mCtrlX->setField("Validate", szXCBuffer); + mCtrlY->setField("Validate", szYCBuffer); + mCtrlZ->setField("Validate", szZCBuffer); mContainerZ = new GuiControl(); mContainerZ->setDataField(StringTable->insert("profile"), NULL, "GuiInspectorTextEditProfile"); @@ -2057,18 +2066,27 @@ void GuiInspectorType4DValue::constructEditControlChildren(GuiControl* retCtrl, mCtrlW->setPosition(Point2I(labelWidth, 0)); - char szBuffer[512]; - dSprintf(szBuffer, 512, "%d.apply(%d.getText() SPC %d.getText() SPC %d.getText() SPC %d.getText());", getId(), mCtrlX->getId(), mCtrlY->getId(), mCtrlZ->getId(), mCtrlW->getId()); + char szXCBuffer[512]; + dSprintf(szXCBuffer, 512, "%d.applyWord(0, %d.getText());", getId(), mCtrlX->getId()); - mCtrlX->setField("AltCommand", szBuffer); - mCtrlY->setField("AltCommand", szBuffer); - mCtrlZ->setField("AltCommand", szBuffer); - mCtrlW->setField("AltCommand", szBuffer); + char szYCBuffer[512]; + dSprintf(szYCBuffer, 512, "%d.applyWord(1, %d.getText());", getId(), mCtrlY->getId()); - mCtrlX->setField("Validate", szBuffer); - mCtrlY->setField("Validate", szBuffer); - mCtrlZ->setField("Validate", szBuffer); - mCtrlW->setField("Validate", szBuffer); + char szZCBuffer[512]; + dSprintf(szZCBuffer, 512, "%d.applyWord(2, %d.getText());", getId(), mCtrlZ->getId()); + + char szWCBuffer[512]; + dSprintf(szZCBuffer, 512, "%d.applyWord(3, %d.getText());", getId(), mCtrlW->getId()); + + mCtrlX->setField("AltCommand", szXCBuffer); + mCtrlY->setField("AltCommand", szYCBuffer); + mCtrlZ->setField("AltCommand", szZCBuffer); + mCtrlW->setField("AltCommand", szWCBuffer); + + mCtrlX->setField("Validate", szXCBuffer); + mCtrlY->setField("Validate", szYCBuffer); + mCtrlZ->setField("Validate", szZCBuffer); + mCtrlW->setField("Validate", szWCBuffer); GuiControl* mContainerW = new GuiControl(); mContainerW->setDataField(StringTable->insert("profile"), NULL, "GuiInspectorTextEditProfile"); diff --git a/Engine/source/gui/editor/guiInspectorTypes.h b/Engine/source/gui/editor/guiInspectorTypes.h index 12ce20c68..a123936e9 100644 --- a/Engine/source/gui/editor/guiInspectorTypes.h +++ b/Engine/source/gui/editor/guiInspectorTypes.h @@ -604,10 +604,10 @@ class GuiInspectorType2DValue : public GuiInspectorField private: typedef GuiInspectorField Parent; protected: - GuiTextEditSliderCtrl* mCtrlX; + GuiTextEditCtrl* mCtrlX; GuiControl* mLabelX; GuiControl* mContainerX; - GuiTextEditSliderCtrl* mCtrlY; + GuiTextEditCtrl* mCtrlY; GuiControl* mLabelY; GuiControl* mContainerY; GuiTextCtrl* mScriptValue; @@ -634,7 +634,7 @@ class GuiInspectorType3DValue : public GuiInspectorType2DValue private: typedef GuiInspectorType2DValue Parent; protected: - GuiTextEditSliderCtrl* mCtrlZ; + GuiTextEditCtrl* mCtrlZ; GuiControl* mLabelZ; GuiControl* mContainerZ; diff --git a/Engine/source/gui/editor/inspector/field.cpp b/Engine/source/gui/editor/inspector/field.cpp index 35f85f405..17350f325 100644 --- a/Engine/source/gui/editor/inspector/field.cpp +++ b/Engine/source/gui/editor/inspector/field.cpp @@ -264,6 +264,129 @@ void GuiInspectorField::onRightMouseUp( const GuiEvent &event ) } //----------------------------------------------------------------------------- +void GuiInspectorField::setWordData(const S32& wordIndex, const char* data, bool callbacks) +{ + if (mSpecialEditField) + { + if (mTargetObject != nullptr && mVariableName != StringTable->EmptyString()) + { + const char* fieldData = mTargetObject->getDataField(mVariableName, NULL); + + StringBuilder newFieldData; + const U32 wordCount = StringUnit::getUnitCount(fieldData, " \t\n"); + for (U32 i = 0; i < wordCount; i++) + { + if (i != 0) + newFieldData.append(" "); + + if (i == wordIndex) + newFieldData.append(data); + else + { + newFieldData.append(StringUnit::getUnit(fieldData, i, " \t\n")); + } + } + + mTargetObject->setDataField(mVariableName, NULL, newFieldData.end()); + + if (mCallbackName != StringTable->EmptyString()) + Con::executef(mInspector, mCallbackName, mVariableName, newFieldData.end(), mTargetObject); + } + else if (mVariableName != StringTable->EmptyString()) + { + const char* fieldData = Con::getVariable(mVariableName, ""); + + StringBuilder newFieldData; + const U32 wordCount = StringUnit::getUnitCount(fieldData, " \t\n"); + for (U32 i = 0; i < wordCount; i++) + { + if (i != 0) + newFieldData.append(" "); + + if (i == wordIndex) + newFieldData.append(data); + else + { + newFieldData.append(StringUnit::getUnit(fieldData, i, " \t\n")); + } + } + + Con::setVariable(mVariableName, newFieldData.end()); + + if (mCallbackName != StringTable->EmptyString()) + Con::executef(mInspector, mCallbackName, mVariableName, newFieldData.end()); + } + } + + if (mField == NULL) + return; + + if (verifyData(data)) + { + String strData = data; + const U32 numTargets = mInspector->getNumInspectObjects(); + + if (callbacks && numTargets > 1) + Con::executef(mInspector, "onBeginCompoundEdit"); + + for (U32 i = 0; i < numTargets; ++i) + { + //For now, for simplicity's sake, you can only edit the components in a simple edit + SimObject* target = NULL; + if (numTargets == 1) + { + target = mTargetObject; + + if (!target) + target = mInspector->getInspectObject(i); + } + else + { + target = mInspector->getInspectObject(i); + } + + const char* fieldData = target->getDataField(mField->pFieldname, mFieldArrayIndex); + + StringBuilder newFieldData; + const U32 wordCount = StringUnit::getUnitCount(fieldData, " \t\n"); + for (U32 i = 0; i < wordCount; i++) + { + if (i != 0) + newFieldData.append(" "); + + if (i == wordIndex) + newFieldData.append(data); + else + { + newFieldData.append(StringUnit::getUnit(fieldData, i, " \t\n")); + } + } + + target->inspectPreApply(); + + // Fire callback single-object undo. + + if (callbacks && !mField->flag.test(AbstractClassRep::FieldFlags::FIELD_ComponentInspectors)) + Con::executef(mInspector, "onInspectorFieldModified", + target->getIdString(), + mField->pFieldname, + mFieldArrayIndex ? mFieldArrayIndex : "(null)", + fieldData, + newFieldData.end()); + + target->setDataField(mField->pFieldname, mFieldArrayIndex, newFieldData.end()); + + // Give the target a chance to validate. + target->inspectPostApply(); + } + + if (callbacks && numTargets > 1) + Con::executef(mInspector, "onEndCompoundEdit"); + } + + // Force our edit to update + updateValue(); +} void GuiInspectorField::setData( const char* data, bool callbacks ) { @@ -762,6 +885,12 @@ DefineEngineMethod( GuiInspectorField, apply, void, ( const char * newValue, boo object->setData( newValue, callbacks ); } +//----------------------------------------------------------------------------- +DefineEngineMethod(GuiInspectorField, applyWord, void, (S32 wordIndex, const char* newValue, bool callbacks), (true), "( string newValue, bool callbacks=true ) - Set the field's value. Suppress callbacks for undo if callbacks=false.") +{ + object->setWordData(wordIndex, newValue, callbacks); +} + //----------------------------------------------------------------------------- DefineEngineMethod( GuiInspectorField, applyWithoutUndo, void, (const char * data), , "() - Set field value without recording undo (same as 'apply( value, false )')." ) diff --git a/Engine/source/gui/editor/inspector/field.h b/Engine/source/gui/editor/inspector/field.h index e04e9231b..a5057254d 100644 --- a/Engine/source/gui/editor/inspector/field.h +++ b/Engine/source/gui/editor/inspector/field.h @@ -167,6 +167,8 @@ class GuiInspectorField : public GuiControl /// to perform their own verification. virtual bool verifyData( StringTableEntry data ) { return true; } + void setWordData(const S32& wordIndex, const char* data, bool callbacks); + /// Set value of the field we are inspecting virtual void setData( const char* data, bool callbacks = true ); From 0d2aeac3030f5328208147a4fc273db7a23953a7 Mon Sep 17 00:00:00 2001 From: Areloch Date: Wed, 1 May 2024 21:58:18 -0500 Subject: [PATCH 2/2] Cleaned up unneeded formatting values on the TypePointX field elements Adds logic checks so we don't multi-apply edits from applyWord fields, causing redundant extra undo's --- .../source/gui/editor/guiInspectorTypes.cpp | 9 -- Engine/source/gui/editor/inspector/field.cpp | 102 ++++++++++++++++++ 2 files changed, 102 insertions(+), 9 deletions(-) diff --git a/Engine/source/gui/editor/guiInspectorTypes.cpp b/Engine/source/gui/editor/guiInspectorTypes.cpp index f18166be1..39b59d1ea 100644 --- a/Engine/source/gui/editor/guiInspectorTypes.cpp +++ b/Engine/source/gui/editor/guiInspectorTypes.cpp @@ -1797,15 +1797,9 @@ void GuiInspectorType2DValue::constructEditControlChildren(GuiControl* retCtrl, mCtrlX->setDataField(StringTable->insert("profile"), NULL, "GuiInspectorTextEditProfile"); mCtrlX->setDataField(StringTable->insert("tooltipprofile"), NULL, "GuiToolTipProfile"); - mCtrlX->setDataField(StringTable->insert("format"), NULL, "%g"); - mCtrlX->setDataField(StringTable->insert("range"), NULL, "-1e+32 1e+32"); - mCtrlX->setDataField(StringTable->insert("increment"), NULL, "0.0001"); mCtrlY->setDataField(StringTable->insert("profile"), NULL, "GuiInspectorTextEditProfile"); mCtrlY->setDataField(StringTable->insert("tooltipprofile"), NULL, "GuiToolTipProfile"); - mCtrlY->setDataField(StringTable->insert("format"), NULL, "%g"); - mCtrlY->setDataField(StringTable->insert("range"), NULL, "-1e+32 1e+32"); - mCtrlY->setDataField(StringTable->insert("increment"), NULL, "0.0001"); mLabelX->setDataField(StringTable->insert("profile"), NULL, "ToolsGuiXDimensionText"); mLabelY->setDataField(StringTable->insert("profile"), NULL, "ToolsGuiYDimensionText"); @@ -1943,9 +1937,6 @@ void GuiInspectorType3DValue::constructEditControlChildren(GuiControl* retCtrl, mCtrlZ->setDataField(StringTable->insert("profile"), NULL, "GuiInspectorTextEditProfile"); mCtrlZ->setDataField(StringTable->insert("tooltipprofile"), NULL, "GuiToolTipProfile"); - mCtrlZ->setDataField(StringTable->insert("format"), NULL, "%g"); - mCtrlZ->setDataField(StringTable->insert("range"), NULL, "-1e+32 1e+32"); - mCtrlZ->setDataField(StringTable->insert("increment"), NULL, "0.0001"); mLabelZ->setDataField(StringTable->insert("profile"), NULL, "ToolsGuiZDimensionText"); diff --git a/Engine/source/gui/editor/inspector/field.cpp b/Engine/source/gui/editor/inspector/field.cpp index 17350f325..75c7cd923 100644 --- a/Engine/source/gui/editor/inspector/field.cpp +++ b/Engine/source/gui/editor/inspector/field.cpp @@ -266,11 +266,36 @@ void GuiInspectorField::onRightMouseUp( const GuiEvent &event ) //----------------------------------------------------------------------------- void GuiInspectorField::setWordData(const S32& wordIndex, const char* data, bool callbacks) { + if (mSpecialEditField) { if (mTargetObject != nullptr && mVariableName != StringTable->EmptyString()) { const char* fieldData = mTargetObject->getDataField(mVariableName, NULL); + const char* wordData = StringUnit::getUnit(fieldData, wordIndex, " \t\n"); + + S32 type = mField->type; + if (type == TypeS8 || type == TypeS32 || type == TypeF32 || type == TypeS32Vector + || type == TypeF32Vector + || type == TypeColorI + || type == TypeColorF + || type == TypePoint2I + || type == TypePoint2F + || type == TypePoint3F + || type == TypePoint4F + || type == TypeRectI + || type == TypeRectF + || type == TypeMatrixPosition + || type == TypeMatrixRotation + || type == TypeBox3F + || type == TypeRectUV + || type == TypeRotationF) + { + if (dAtof(wordData) != dAtof(data)) + return; + } + else if(dStrEqual(wordData, data)) + return; StringBuilder newFieldData; const U32 wordCount = StringUnit::getUnitCount(fieldData, " \t\n"); @@ -295,6 +320,30 @@ void GuiInspectorField::setWordData(const S32& wordIndex, const char* data, bool else if (mVariableName != StringTable->EmptyString()) { const char* fieldData = Con::getVariable(mVariableName, ""); + const char* wordData = StringUnit::getUnit(fieldData, wordIndex, " \t\n"); + + S32 type = mField->type; + if (type == TypeS8 || type == TypeS32 || type == TypeF32 || type == TypeS32Vector + || type == TypeF32Vector + || type == TypeColorI + || type == TypeColorF + || type == TypePoint2I + || type == TypePoint2F + || type == TypePoint3F + || type == TypePoint4F + || type == TypeRectI + || type == TypeRectF + || type == TypeMatrixPosition + || type == TypeMatrixRotation + || type == TypeBox3F + || type == TypeRectUV + || type == TypeRotationF) + { + if (dAtof(wordData) != dAtof(data)) + return; + } + else if (dStrEqual(wordData, data)) + return; StringBuilder newFieldData; const U32 wordCount = StringUnit::getUnitCount(fieldData, " \t\n"); @@ -326,6 +375,59 @@ void GuiInspectorField::setWordData(const S32& wordIndex, const char* data, bool String strData = data; const U32 numTargets = mInspector->getNumInspectObjects(); + bool changed = false; + for (U32 i = 0; i < numTargets; ++i) + { + //For now, for simplicity's sake, you can only edit the components in a simple edit + SimObject* target = NULL; + if (numTargets == 1) + { + target = mTargetObject; + + if (!target) + target = mInspector->getInspectObject(i); + } + else + { + target = mInspector->getInspectObject(i); + } + + const char* fieldData = target->getDataField(mField->pFieldname, mFieldArrayIndex); + const char* wordData = StringUnit::getUnit(fieldData, wordIndex, " \t\n"); + + S32 type = mField->type; + if (type == TypeS8 || type == TypeS32 || type == TypeF32 || type == TypeS32Vector + || type == TypeF32Vector + || type == TypeColorI + || type == TypeColorF + || type == TypePoint2I + || type == TypePoint2F + || type == TypePoint3F + || type == TypePoint4F + || type == TypeRectI + || type == TypeRectF + || type == TypeMatrixPosition + || type == TypeMatrixRotation + || type == TypeBox3F + || type == TypeRectUV + || type == TypeRotationF) + { + if (dAtof(wordData) != dAtof(data)) + { + changed = true; + break; + } + } + else if (!dStrEqual(wordData, data)) + { + changed = true; + break; + } + } + + if(!changed) + return; + if (callbacks && numTargets > 1) Con::executef(mInspector, "onBeginCompoundEdit");