فهرست منبع

Merge pull request #1269 from Areloch/MultiObjectEditMadness

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'
Brian Roberts 1 سال پیش
والد
کامیت
67b052a192

+ 45 - 36
Engine/source/gui/editor/guiInspectorTypes.cpp

@@ -1765,12 +1765,12 @@ void GuiInspectorTypeSFXSourceName::consoleInit()
 
 
 void GuiInspectorType2DValue::constructEditControlChildren(GuiControl* retCtrl, S32 width)
 void GuiInspectorType2DValue::constructEditControlChildren(GuiControl* retCtrl, S32 width)
 {
 {
-   mCtrlX = new GuiTextEditSliderCtrl();
+   mCtrlX = new GuiTextEditCtrl();
    _registerEditControl(mCtrlX, "x");
    _registerEditControl(mCtrlX, "x");
    mLabelX = new GuiControl();
    mLabelX = new GuiControl();
    _registerEditControl(mLabelX, "lx");
    _registerEditControl(mLabelX, "lx");
 
 
-   mCtrlY = new GuiTextEditSliderCtrl();
+   mCtrlY = new GuiTextEditCtrl();
    _registerEditControl(mCtrlY, "y");
    _registerEditControl(mCtrlY, "y");
    mLabelY = new GuiControl();
    mLabelY = new GuiControl();
    _registerEditControl(mLabelY, "ly");
    _registerEditControl(mLabelY, "ly");
@@ -1797,15 +1797,9 @@ void GuiInspectorType2DValue::constructEditControlChildren(GuiControl* retCtrl,
 
 
    mCtrlX->setDataField(StringTable->insert("profile"), NULL, "GuiInspectorTextEditProfile");
    mCtrlX->setDataField(StringTable->insert("profile"), NULL, "GuiInspectorTextEditProfile");
    mCtrlX->setDataField(StringTable->insert("tooltipprofile"), NULL, "GuiToolTipProfile");
    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("profile"), NULL, "GuiInspectorTextEditProfile");
    mCtrlY->setDataField(StringTable->insert("tooltipprofile"), NULL, "GuiToolTipProfile");
    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");
    mLabelX->setDataField(StringTable->insert("profile"), NULL, "ToolsGuiXDimensionText");
    mLabelY->setDataField(StringTable->insert("profile"), NULL, "ToolsGuiYDimensionText");
    mLabelY->setDataField(StringTable->insert("profile"), NULL, "ToolsGuiYDimensionText");
@@ -1824,14 +1818,17 @@ void GuiInspectorType2DValue::constructEditControlChildren(GuiControl* retCtrl,
    mCtrlX->setPosition(Point2I(labelWidth, 0));
    mCtrlX->setPosition(Point2I(labelWidth, 0));
    mCtrlY->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 = new GuiControl();
    mContainerX->setDataField(StringTable->insert("profile"), NULL, "GuiInspectorTextEditProfile");
    mContainerX->setDataField(StringTable->insert("profile"), NULL, "GuiInspectorTextEditProfile");
@@ -1933,16 +1930,13 @@ void GuiInspectorType3DValue::constructEditControlChildren(GuiControl* retCtrl,
 {
 {
    Parent::constructEditControlChildren(retCtrl, width);
    Parent::constructEditControlChildren(retCtrl, width);
 
 
-   mCtrlZ = new GuiTextEditSliderCtrl();
+   mCtrlZ = new GuiTextEditCtrl();
    _registerEditControl(mCtrlZ, "z");
    _registerEditControl(mCtrlZ, "z");
    mLabelZ = new GuiControl();
    mLabelZ = new GuiControl();
    _registerEditControl(mLabelZ, "lz");
    _registerEditControl(mLabelZ, "lz");
 
 
    mCtrlZ->setDataField(StringTable->insert("profile"), NULL, "GuiInspectorTextEditProfile");
    mCtrlZ->setDataField(StringTable->insert("profile"), NULL, "GuiInspectorTextEditProfile");
    mCtrlZ->setDataField(StringTable->insert("tooltipprofile"), NULL, "GuiToolTipProfile");
    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");
    mLabelZ->setDataField(StringTable->insert("profile"), NULL, "ToolsGuiZDimensionText");
 
 
@@ -1953,16 +1947,22 @@ void GuiInspectorType3DValue::constructEditControlChildren(GuiControl* retCtrl,
 
 
    mCtrlZ->setPosition(Point2I(labelWidth, 0));
    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 = new GuiControl();
    mContainerZ->setDataField(StringTable->insert("profile"), NULL, "GuiInspectorTextEditProfile");
    mContainerZ->setDataField(StringTable->insert("profile"), NULL, "GuiInspectorTextEditProfile");
@@ -2057,18 +2057,27 @@ void GuiInspectorType4DValue::constructEditControlChildren(GuiControl* retCtrl,
 
 
    mCtrlW->setPosition(Point2I(labelWidth, 0));
    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());
+
+   char szYCBuffer[512];
+   dSprintf(szYCBuffer, 512, "%d.applyWord(1, %d.getText());", getId(), mCtrlY->getId());
+
+   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", szBuffer);
-   mCtrlY->setField("AltCommand", szBuffer);
-   mCtrlZ->setField("AltCommand", szBuffer);
-   mCtrlW->setField("AltCommand", szBuffer);
+   mCtrlX->setField("AltCommand", szXCBuffer);
+   mCtrlY->setField("AltCommand", szYCBuffer);
+   mCtrlZ->setField("AltCommand", szZCBuffer);
+   mCtrlW->setField("AltCommand", szWCBuffer);
 
 
-   mCtrlX->setField("Validate", szBuffer);
-   mCtrlY->setField("Validate", szBuffer);
-   mCtrlZ->setField("Validate", szBuffer);
-   mCtrlW->setField("Validate", szBuffer);
+   mCtrlX->setField("Validate", szXCBuffer);
+   mCtrlY->setField("Validate", szYCBuffer);
+   mCtrlZ->setField("Validate", szZCBuffer);
+   mCtrlW->setField("Validate", szWCBuffer);
 
 
    GuiControl* mContainerW = new GuiControl();
    GuiControl* mContainerW = new GuiControl();
    mContainerW->setDataField(StringTable->insert("profile"), NULL, "GuiInspectorTextEditProfile");
    mContainerW->setDataField(StringTable->insert("profile"), NULL, "GuiInspectorTextEditProfile");

+ 3 - 3
Engine/source/gui/editor/guiInspectorTypes.h

@@ -604,10 +604,10 @@ class GuiInspectorType2DValue : public GuiInspectorField
 private:
 private:
    typedef GuiInspectorField Parent;
    typedef GuiInspectorField Parent;
 protected:
 protected:
-   GuiTextEditSliderCtrl* mCtrlX;
+   GuiTextEditCtrl* mCtrlX;
    GuiControl* mLabelX;
    GuiControl* mLabelX;
    GuiControl* mContainerX;
    GuiControl* mContainerX;
-   GuiTextEditSliderCtrl* mCtrlY;
+   GuiTextEditCtrl* mCtrlY;
    GuiControl* mLabelY;
    GuiControl* mLabelY;
    GuiControl* mContainerY;
    GuiControl* mContainerY;
    GuiTextCtrl* mScriptValue;
    GuiTextCtrl* mScriptValue;
@@ -634,7 +634,7 @@ class GuiInspectorType3DValue : public GuiInspectorType2DValue
 private:
 private:
    typedef GuiInspectorType2DValue Parent;
    typedef GuiInspectorType2DValue Parent;
 protected:
 protected:
-   GuiTextEditSliderCtrl* mCtrlZ;
+   GuiTextEditCtrl* mCtrlZ;
    GuiControl* mLabelZ;
    GuiControl* mLabelZ;
    GuiControl* mContainerZ;
    GuiControl* mContainerZ;
 
 

+ 231 - 0
Engine/source/gui/editor/inspector/field.cpp

@@ -264,6 +264,231 @@ 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");
+         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, "");
+         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");
+         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();
+
+      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");
+
+      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 )
 void GuiInspectorField::setData( const char* data, bool callbacks )
 {
 {
@@ -762,6 +987,12 @@ DefineEngineMethod( GuiInspectorField, apply, void, ( const char * newValue, boo
    object->setData( newValue, callbacks );
    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 )')." )
 DefineEngineMethod( GuiInspectorField, applyWithoutUndo, void, (const char * data), , "() - Set field value without recording undo (same as 'apply( value, false )')." )

+ 2 - 0
Engine/source/gui/editor/inspector/field.h

@@ -167,6 +167,8 @@ class GuiInspectorField : public GuiControl
       /// to perform their own verification.
       /// to perform their own verification.
       virtual bool verifyData( StringTableEntry data ) { return true; }
       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
       /// Set value of the field we are inspecting
       virtual void setData( const char* data, bool callbacks = true );
       virtual void setData( const char* data, bool callbacks = true );