Bläddra i källkod

Merge pull request #1033 from marauder2k9-torque/GuiInspectorFields

Add multi dimensional entries to inspector
Areloch 2 år sedan
förälder
incheckning
cb766f2878

+ 759 - 0
Engine/source/gui/editor/guiInspectorTypes.cpp

@@ -1719,3 +1719,762 @@ void GuiInspectorTypeSFXSourceName::consoleInit()
 
    ConsoleBaseType::getType( TypeSFXSourceName )->setInspectorFieldType( "GuiInspectorTypeSFXSourceName" );
 }
+
+//-----------------------------------------------------------------------------
+// Two Dimensional Field base GuiInspectorField Class
+//-----------------------------------------------------------------------------
+
+void GuiInspectorType2DValue::constructEditControlChildren(GuiControl* retCtrl, S32 width)
+{
+   mCtrlX = new GuiTextEditSliderCtrl();
+   _registerEditControl(mCtrlX, "x");
+   mLabelX = new GuiControl();
+   _registerEditControl(mLabelX, "lx");
+
+   mCtrlY = new GuiTextEditSliderCtrl();
+   _registerEditControl(mCtrlY, "y");
+   mLabelY = new GuiControl();
+   _registerEditControl(mLabelY, "ly");
+
+   mScriptValue = new GuiTextEditCtrl();
+
+   mCopyButton = new GuiButtonCtrl();
+   mCopyButton->setExtent(Point2I(45, 15));
+   mCopyButton->registerObject();
+   mCopyButton->setDataField(StringTable->insert("text"), NULL, "Copy");
+   mCopyButton->setDataField(StringTable->insert("Profile"), NULL, "GuiInspectorButtonProfile");
+   mCopyButton->setDataField(StringTable->insert("tooltipprofile"), NULL, "GuiToolTipProfile");
+   mCopyButton->setDataField(StringTable->insert("hovertime"), NULL, "1000");
+   mCopyButton->setDataField(StringTable->insert("tooltip"), NULL, "Copy all values for script.");
+
+   mPasteButton = new GuiButtonCtrl();
+   mPasteButton->setExtent(Point2I(45, 15));
+   mPasteButton->registerObject();
+   mPasteButton->setDataField(StringTable->insert("text"), NULL, "Paste");
+   mPasteButton->setDataField(StringTable->insert("Profile"), NULL, "GuiInspectorButtonProfile");
+   mPasteButton->setDataField(StringTable->insert("tooltipprofile"), NULL, "GuiToolTipProfile");
+   mPasteButton->setDataField(StringTable->insert("hovertime"), NULL, "1000");
+   mPasteButton->setDataField(StringTable->insert("tooltip"), NULL, "Copy all values for script.");
+
+   mCtrlX->setDataField(StringTable->insert("profile"), NULL, "GuiInspectorTextEditProfile");
+   mCtrlX->setDataField(StringTable->insert("tooltipprofile"), NULL, "GuiToolTipProfile");
+   mCtrlX->setDataField(StringTable->insert("format"), NULL, "%.4f");
+   mCtrlX->setDataField(StringTable->insert("range"), NULL, "-1e+03 1e+03");
+   mCtrlX->setDataField(StringTable->insert("increment"), NULL, "0.1");
+
+   mCtrlY->setDataField(StringTable->insert("profile"), NULL, "GuiInspectorTextEditProfile");
+   mCtrlY->setDataField(StringTable->insert("tooltipprofile"), NULL, "GuiToolTipProfile");
+   mCtrlY->setDataField(StringTable->insert("format"), NULL, "%.4f");
+   mCtrlY->setDataField(StringTable->insert("range"), NULL, "-1e+03 1e+03");
+   mCtrlY->setDataField(StringTable->insert("increment"), NULL, "0.1");
+
+   mLabelX->setDataField(StringTable->insert("profile"), NULL, "ToolsGuiXDimensionText");
+   mLabelY->setDataField(StringTable->insert("profile"), NULL, "ToolsGuiYDimensionText");
+
+   mScriptValue->setDataField(StringTable->insert("profile"), NULL, "GuiInspectorTextEditProfile");
+   mScriptValue->setDataField(StringTable->insert("tooltipprofile"), NULL, "GuiToolTipProfile");
+
+   S32 labelWidth = 3;
+   mLabelX->setExtent(Point2I(labelWidth, 18));
+   mLabelY->setExtent(Point2I(labelWidth, 18));
+
+   mCtrlX->setExtent(Point2I(width - labelWidth, 18));
+   mCtrlY->setExtent(Point2I(width - labelWidth, 18));
+   mScriptValue->setExtent(Point2I(width, 18));
+
+   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());
+
+   mCtrlX->setField("AltCommand", szBuffer);
+   mCtrlY->setField("AltCommand", szBuffer);
+
+   mCtrlX->setField("Validate", szBuffer);
+   mCtrlY->setField("Validate", szBuffer);
+
+   mContainerX = new GuiControl();
+   mContainerX->setDataField(StringTable->insert("profile"), NULL, "GuiInspectorTextEditProfile");
+   mContainerX->setExtent(Point2I(width, 18));
+   mContainerX->addObject(mLabelX);
+   mContainerX->addObject(mCtrlX);
+   _registerEditControl(mContainerX, "cx");
+
+   mContainerY = new GuiControl();
+   mContainerY->setDataField(StringTable->insert("profile"), NULL, "GuiInspectorTextEditProfile");
+   mContainerY->setExtent(Point2I(width, 18));
+   mContainerY->addObject(mLabelY);
+   mContainerY->addObject(mCtrlY);
+   _registerEditControl(mContainerY, "cy");
+
+   retCtrl->addObject(mContainerX);
+   retCtrl->addObject(mContainerY);
+   //retCtrl->addObject(mScriptValue);
+}
+
+void GuiInspectorType2DValue::updateValue()
+{
+   if (mField)
+   {
+      Parent::updateValue();
+      const char* data = getData();
+      if (!data)
+         data = "";
+      U32 elementCount = StringUnit::getUnitCount(data, " ");
+
+      if (elementCount > 0)
+      {
+         F32 value = dAtof(StringUnit::getUnit(data, 0, " \t\n"));
+         char szBuffer[64];
+         dSprintf(szBuffer, 64, "%.4f", value);
+         mCtrlX->setText(szBuffer);
+      }
+
+      if (elementCount > 1)
+      {
+         F32 value = dAtof(StringUnit::getUnit(data, 1, " \t\n"));
+         char szBuffer[64];
+         dSprintf(szBuffer, 64, "%.4f", value);
+         mCtrlY->setText(szBuffer);
+      }
+
+      mScriptValue->setText(data);
+
+      mEdit->setDataField(StringTable->insert("tooltip"), NULL, data);
+   }
+}
+
+bool GuiInspectorType2DValue::resize(const Point2I& newPosition, const Point2I& newExtent)
+{
+   if (!Parent::resize(newPosition, newExtent))
+      return false;
+
+   if (mEdit != NULL)
+   {
+      return updateRects();
+   }
+
+   return false;
+}
+
+bool GuiInspectorType2DValue::updateRects()
+{
+   S32 rowSize = 18;
+   S32 dividerPos, dividerMargin;
+   mInspector->getDivider(dividerPos, dividerMargin);
+   Point2I fieldExtent = getExtent();
+   Point2I fieldPos = getPosition();
+
+   mEditCtrlRect.set(fieldExtent.x - dividerPos + dividerMargin, 1, dividerPos - dividerMargin - 29, fieldExtent.y);
+   S32 cellWidth = mCeil((dividerPos - dividerMargin - 29));
+
+   mCtrlX->setExtent(Point2I(cellWidth - 3, 18));
+   mCtrlY->setExtent(Point2I(cellWidth - 3, 18));
+
+   S32 dimX = 10;
+
+   mCaptionLabel->resize(Point2I(mProfile->mTextOffset.x, 0), Point2I(fieldExtent.x, rowSize));
+   mDimensionLabelX->resize(Point2I(fieldExtent.x - dividerPos - dimX, 0), Point2I(dimX, rowSize));
+   mDimensionLabelY->resize(Point2I(fieldExtent.x - dividerPos - dimX, rowSize + 3), Point2I(dimX, rowSize));
+
+   mCopyButton->resize(Point2I(mProfile->mTextOffset.x, rowSize + 3), Point2I(45, 15));
+   mPasteButton->resize(Point2I(mProfile->mTextOffset.x, rowSize + rowSize + 6), Point2I(45, 15));
+
+   mEdit->resize(mEditCtrlRect.point, mEditCtrlRect.extent);
+
+   return true;
+}
+
+//-----------------------------------------------------------------------------
+// Three Dimensional Field base GuiInspectorField Class
+//-----------------------------------------------------------------------------
+
+void GuiInspectorType3DValue::constructEditControlChildren(GuiControl* retCtrl, S32 width)
+{
+   Parent::constructEditControlChildren(retCtrl, width);
+
+   mCtrlZ = new GuiTextEditSliderCtrl();
+   _registerEditControl(mCtrlZ, "z");
+   mLabelZ = new GuiControl();
+   _registerEditControl(mLabelZ, "lz");
+
+   mCtrlZ->setDataField(StringTable->insert("profile"), NULL, "GuiInspectorTextEditProfile");
+   mCtrlZ->setDataField(StringTable->insert("tooltipprofile"), NULL, "GuiToolTipProfile");
+   mCtrlZ->setDataField(StringTable->insert("format"), NULL, "%.4f");
+   mCtrlZ->setDataField(StringTable->insert("range"), NULL, "-1e+03 1e+03");
+   mCtrlZ->setDataField(StringTable->insert("increment"), NULL, "0.1");
+
+   mLabelZ->setDataField(StringTable->insert("profile"), NULL, "ToolsGuiZDimensionText");
+
+   S32 labelWidth = 3;
+   mLabelZ->setExtent(Point2I(labelWidth, 18));
+
+   mCtrlZ->setExtent(Point2I(width - labelWidth, 18));
+
+   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());
+
+   mCtrlX->setField("AltCommand", szBuffer);
+   mCtrlY->setField("AltCommand", szBuffer);
+   mCtrlZ->setField("AltCommand", szBuffer);
+
+   mCtrlX->setField("Validate", szBuffer);
+   mCtrlY->setField("Validate", szBuffer);
+   mCtrlZ->setField("Validate", szBuffer);
+
+   mContainerZ = new GuiControl();
+   mContainerZ->setDataField(StringTable->insert("profile"), NULL, "GuiInspectorTextEditProfile");
+   mContainerZ->setExtent(Point2I(width, 18));
+   mContainerZ->addObject(mLabelZ);
+   mContainerZ->addObject(mCtrlZ);
+   _registerEditControl(mContainerZ, "cz");
+
+   retCtrl->addObject(mContainerZ);
+}
+
+void GuiInspectorType3DValue::updateValue()
+{
+   if (mField)
+   {
+      Parent::updateValue();
+      const char* data = getData();
+      if (!data)
+         data = "";
+
+      U32 elementCount = StringUnit::getUnitCount(data, " ");
+
+      if (elementCount > 2)
+      {
+         F32 value = dAtof(StringUnit::getUnit(data, 2, " \t\n"));
+         char szBuffer[64];
+         dSprintf(szBuffer, 64, "%.4f", value);
+         mCtrlZ->setText(szBuffer);
+      }
+   }
+}
+
+bool GuiInspectorType3DValue::resize(const Point2I& newPosition, const Point2I& newExtent)
+{
+   if (!Parent::resize(newPosition, newExtent))
+      return false;
+
+   if (mEdit != NULL)
+   {
+      return updateRects();
+   }
+
+   return false;
+}
+
+bool GuiInspectorType3DValue::updateRects()
+{
+   if (!Parent::updateRects())
+      return false;
+
+   S32 rowSize = 18;
+   S32 dividerPos, dividerMargin;
+   mInspector->getDivider(dividerPos, dividerMargin);
+   Point2I fieldExtent = getExtent();
+   Point2I fieldPos = getPosition();
+
+   S32 cellWidth = mCeil((dividerPos - dividerMargin - 29));
+
+   mCtrlZ->setExtent(Point2I(cellWidth - 3, 18));
+
+   S32 dimX = 10;
+
+   mDimensionLabelZ->resize(Point2I(fieldExtent.x - dividerPos - dimX, rowSize + rowSize + 6), Point2I(dimX, rowSize));
+
+   return true;
+}
+
+//-----------------------------------------------------------------------------
+// Four Dimensional Field base GuiInspectorField Class
+//-----------------------------------------------------------------------------
+
+void GuiInspectorType4DValue::constructEditControlChildren(GuiControl* retCtrl, S32 width)
+{
+   Parent::constructEditControlChildren(retCtrl, width);
+
+   mCtrlW = new GuiTextEditCtrl();
+   GuiControl* mLabelW = new GuiControl();
+
+   _registerEditControl(mCtrlW);
+
+   mCtrlW->setDataField(StringTable->insert("profile"), NULL, "GuiInspectorTextEditProfile");
+   mCtrlW->setDataField(StringTable->insert("tooltipprofile"), NULL, "GuiToolTipProfile");
+
+   mLabelW->setDataField(StringTable->insert("profile"), NULL, "ToolsGuiZDimensionText");
+
+   S32 labelWidth = 3;
+   mLabelW->setExtent(Point2I(labelWidth, 18));
+
+   mCtrlW->setExtent(Point2I(width - labelWidth, 18));
+
+   mScriptValue->setExtent(Point2I(width, 18));
+
+   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());
+
+   mCtrlX->setField("AltCommand", szBuffer);
+   mCtrlY->setField("AltCommand", szBuffer);
+   mCtrlZ->setField("AltCommand", szBuffer);
+   mCtrlW->setField("AltCommand", szBuffer);
+
+   mCtrlX->setField("Validate", szBuffer);
+   mCtrlY->setField("Validate", szBuffer);
+   mCtrlZ->setField("Validate", szBuffer);
+   mCtrlW->setField("Validate", szBuffer);
+
+   GuiControl* mContainerW = new GuiControl();
+   mContainerW->setDataField(StringTable->insert("profile"), NULL, "GuiInspectorTextEditProfile");
+   mContainerW->setExtent(Point2I(width, 18));
+   mContainerW->addObject(mLabelW);
+   mContainerW->addObject(mCtrlW);
+   _registerEditControl(mContainerW);
+
+   retCtrl->addObject(mContainerW);
+}
+
+void GuiInspectorType4DValue::updateValue()
+{
+   if (mField)
+   {
+      Parent::updateValue();
+      const char* data = getData();
+      if (!data)
+         data = "";
+      U32 elementCount = StringUnit::getUnitCount(data, " ");
+
+      if (elementCount > 3)
+      {
+         mCtrlW->setText(StringUnit::getUnit(data, 3, " \t\n"));
+      }
+   }
+}
+
+bool GuiInspectorType4DValue::resize(const Point2I& newPosition, const Point2I& newExtent)
+{
+   if (!Parent::resize(newPosition, newExtent))
+      return false;
+
+   if (mEdit != NULL)
+   {
+      return updateRects();
+   }
+
+   return false;
+}
+
+bool GuiInspectorType4DValue::updateRects()
+{
+   if (!Parent::updateRects())
+      return false;
+
+   S32 rowSize = 18;
+   S32 dividerPos, dividerMargin;
+   mInspector->getDivider(dividerPos, dividerMargin);
+   Point2I fieldExtent = getExtent();
+   Point2I fieldPos = getPosition();
+
+   S32 cellWidth = mCeil((dividerPos - dividerMargin - 29));
+
+   mCtrlW->setExtent(Point2I(cellWidth - 3, 18));
+
+   S32 dimX = 10;
+
+   mDimensionLabelW->resize(Point2I(fieldExtent.x - dividerPos - dimX, rowSize + rowSize + 6), Point2I(dimX, rowSize));
+
+   return true;
+}
+
+//-----------------------------------------------------------------------------
+// TypePoint2F GuiInspectorField Class
+//-----------------------------------------------------------------------------
+IMPLEMENT_CONOBJECT(GuiInspectorTypePoint2F);
+
+ConsoleDocClass(GuiInspectorTypePoint2F,
+   "@brief Inspector field type for Point2F\n\n"
+   "Editor use only.\n\n"
+   "@internal"
+);
+void GuiInspectorTypePoint2F::consoleInit()
+{
+   Parent::consoleInit();
+
+   ConsoleBaseType::getType(TypePoint2F)->setInspectorFieldType("GuiInspectorTypePoint2F");
+}
+
+GuiControl* GuiInspectorTypePoint2F::constructEditControl()
+{
+   GuiStackControl* retCtrl = new GuiStackControl();
+
+   if (retCtrl == NULL)
+      return retCtrl;
+
+   mCaptionLabel = new GuiTextCtrl();
+   mCaptionLabel->registerObject();
+   mCaptionLabel->setControlProfile(mProfile);
+   mCaptionLabel->setText(mCaption);
+   addObject(mCaptionLabel);
+
+   mDimensionLabelX = new GuiTextCtrl();
+   mDimensionLabelX->registerObject();
+   mDimensionLabelX->setControlProfile(mProfile);
+   mDimensionLabelX->setText("X");
+   addObject(mDimensionLabelX);
+
+   mDimensionLabelY = new GuiTextCtrl();
+   mDimensionLabelY->registerObject();
+   mDimensionLabelY->setControlProfile(mProfile);
+   mDimensionLabelY->setText("Y");
+   addObject(mDimensionLabelY);
+
+   retCtrl->setDataField(StringTable->insert("profile"), NULL, "ToolsGuiDefaultProfile");
+   retCtrl->setDataField(StringTable->insert("tooltipprofile"), NULL, "GuiToolTipProfile");
+   retCtrl->setDataField(StringTable->insert("stackingType"), NULL, "Vertical");
+   retCtrl->setDataField(StringTable->insert("dynamicSize"), NULL, "1");
+   retCtrl->setDataField(StringTable->insert("padding"), NULL, "3");
+
+   _registerEditControl(retCtrl);
+
+   constructEditControlChildren(retCtrl, getWidth());
+
+   char szBuffer[512];
+   dSprintf(szBuffer, 512, "setClipboard(%d.getText() SPC %d.getText());", mCtrlX->getId(), mCtrlY->getId());
+   mCopyButton->setField("Command", szBuffer);
+   addObject(mCopyButton);
+
+   dSprintf(szBuffer, 512, "%d.apply(getWords(getClipboard(), 0, 1));", getId());
+   mPasteButton->setField("Command", szBuffer);
+   addObject(mPasteButton);
+
+   mUseHeightOverride = true;
+   mHeightOverride = retCtrl->getHeight() + 16 + 6;
+
+   return retCtrl;
+}
+
+//-----------------------------------------------------------------------------
+// TypePoint2I GuiInspectorField Class
+//-----------------------------------------------------------------------------
+IMPLEMENT_CONOBJECT(GuiInspectorTypePoint2I);
+
+ConsoleDocClass(GuiInspectorTypePoint2I,
+   "@brief Inspector field type for Point2I\n\n"
+   "Editor use only.\n\n"
+   "@internal"
+);
+void GuiInspectorTypePoint2I::consoleInit()
+{
+   Parent::consoleInit();
+
+   ConsoleBaseType::getType(TypePoint2I)->setInspectorFieldType("GuiInspectorTypePoint2I");
+}
+
+GuiControl* GuiInspectorTypePoint2I::constructEditControl()
+{
+   GuiControl* retCtrl = Parent::constructEditControl();
+
+   mCtrlX->setDataField(StringTable->insert("format"), NULL, "%d");
+   mCtrlY->setDataField(StringTable->insert("format"), NULL, "%d");
+
+   return retCtrl;
+}
+
+//-----------------------------------------------------------------------------
+// TypePoint3F GuiInspectorField Class
+//-----------------------------------------------------------------------------
+IMPLEMENT_CONOBJECT(GuiInspectorTypePoint3F);
+
+ConsoleDocClass(GuiInspectorTypePoint3F,
+   "@brief Inspector field type for Point3F\n\n"
+   "Editor use only.\n\n"
+   "@internal"
+);
+void GuiInspectorTypePoint3F::consoleInit()
+{
+   Parent::consoleInit();
+
+   ConsoleBaseType::getType(TypeMatrixPosition)->setInspectorFieldType("GuiInspectorTypePoint3F");
+   ConsoleBaseType::getType(TypePoint3F)->setInspectorFieldType("GuiInspectorTypePoint3F");
+}
+
+GuiControl* GuiInspectorTypePoint3F::constructEditControl()
+{
+   GuiStackControl* retCtrl = new GuiStackControl();
+
+   if (retCtrl == NULL)
+      return retCtrl;
+
+   mCaptionLabel = new GuiTextCtrl();
+   mCaptionLabel->registerObject();
+   mCaptionLabel->setControlProfile(mProfile);
+   mCaptionLabel->setText(mCaption);
+   addObject(mCaptionLabel);
+
+   mDimensionLabelX = new GuiTextCtrl();
+   mDimensionLabelX->registerObject();
+   mDimensionLabelX->setControlProfile(mProfile);
+   mDimensionLabelX->setText("X");
+   addObject(mDimensionLabelX);
+
+   mDimensionLabelY = new GuiTextCtrl();
+   mDimensionLabelY->registerObject();
+   mDimensionLabelY->setControlProfile(mProfile);
+   mDimensionLabelY->setText("Y");
+   addObject(mDimensionLabelY);
+
+   mDimensionLabelZ = new GuiTextCtrl();
+   mDimensionLabelZ->registerObject();
+   mDimensionLabelZ->setControlProfile(mProfile);
+   mDimensionLabelZ->setText("Z");
+   addObject(mDimensionLabelZ);
+
+   retCtrl->setDataField(StringTable->insert("profile"), NULL, "ToolsGuiDefaultProfile");
+   retCtrl->setDataField(StringTable->insert("tooltipprofile"), NULL, "GuiToolTipProfile");
+   retCtrl->setDataField(StringTable->insert("stackingType"), NULL, "Vertical");
+   retCtrl->setDataField(StringTable->insert("dynamicSize"), NULL, "1");
+   retCtrl->setDataField(StringTable->insert("padding"), NULL, "3");
+
+   _registerEditControl(retCtrl);
+
+   constructEditControlChildren(retCtrl, getWidth());
+
+   char szBuffer[512];
+   dSprintf(szBuffer, 512, "setClipboard(%d.getText() SPC %d.getText() SPC %d.getText());", mCtrlX->getId(), mCtrlY->getId(), mCtrlZ->getId());
+   mCopyButton->setField("Command", szBuffer);
+   addObject(mCopyButton);
+
+   dSprintf(szBuffer, 512, "%d.apply(getWords(getClipboard(), 0, 2));", getId());
+   mPasteButton->setField("Command", szBuffer);
+   addObject(mPasteButton);
+
+   mUseHeightOverride = true;
+   mHeightOverride = retCtrl->getHeight() + 6;
+
+   return retCtrl;
+}
+
+//-----------------------------------------------------------------------------
+// GuiInspectorTypeMatrixRotation GuiInspectorField Class
+//-----------------------------------------------------------------------------
+IMPLEMENT_CONOBJECT(GuiInspectorTypeMatrixRotation);
+
+ConsoleDocClass(GuiInspectorTypeMatrixRotation,
+   "@brief Inspector field type for rotation\n\n"
+   "Editor use only.\n\n"
+   "@internal"
+);
+void GuiInspectorTypeMatrixRotation::consoleInit()
+{
+   Parent::consoleInit();
+
+   ConsoleBaseType::getType(TypeMatrixRotation)->setInspectorFieldType("GuiInspectorTypeMatrixRotation");
+}
+
+GuiControl* GuiInspectorTypeMatrixRotation::constructEditControl()
+{
+   GuiStackControl* retCtrl = new GuiStackControl();
+
+   if (retCtrl == NULL)
+      return retCtrl;
+
+   mCaptionLabel = new GuiTextCtrl();
+   mCaptionLabel->registerObject();
+   mCaptionLabel->setControlProfile(mProfile);
+   mCaptionLabel->setText(mCaption);
+   addObject(mCaptionLabel);
+
+   mDimensionLabelX = new GuiTextCtrl();
+   mDimensionLabelX->registerObject();
+   mDimensionLabelX->setControlProfile(mProfile);
+   mDimensionLabelX->setText("Pitch");
+   addObject(mDimensionLabelX);
+
+   mDimensionLabelY = new GuiTextCtrl();
+   mDimensionLabelY->registerObject();
+   mDimensionLabelY->setControlProfile(mProfile);
+   mDimensionLabelY->setText("Roll");
+   addObject(mDimensionLabelY);
+
+   mDimensionLabelZ = new GuiTextCtrl();
+   mDimensionLabelZ->registerObject();
+   mDimensionLabelZ->setControlProfile(mProfile);
+   mDimensionLabelZ->setText("Yaw");
+   addObject(mDimensionLabelZ);
+
+   retCtrl->setDataField(StringTable->insert("profile"), NULL, "ToolsGuiDefaultProfile");
+   retCtrl->setDataField(StringTable->insert("tooltipprofile"), NULL, "GuiToolTipProfile");
+   retCtrl->setDataField(StringTable->insert("stackingType"), NULL, "Vertical");
+   retCtrl->setDataField(StringTable->insert("dynamicSize"), NULL, "1");
+   retCtrl->setDataField(StringTable->insert("padding"), NULL, "3");
+
+   _registerEditControl(retCtrl);
+
+   constructEditControlChildren(retCtrl, getWidth());
+
+   //retCtrl->addObject(mScriptValue);
+
+   char szBuffer[512];
+   dSprintf(szBuffer, 512, "setClipboard(%d.getText());", mScriptValue->getId());
+   mCopyButton->setField("Command", szBuffer);
+   addObject(mCopyButton);
+
+   dSprintf(szBuffer, 512, "%d.apply(getClipboard());", getId());
+   mPasteButton->setField("Command", szBuffer);
+   addObject(mPasteButton);
+
+   mUseHeightOverride = true;
+   mHeightOverride = retCtrl->getHeight() + 6;
+
+   return retCtrl;
+}
+
+void GuiInspectorTypeMatrixRotation::constructEditControlChildren(GuiControl* retCtrl, S32 width)
+{
+   Parent::constructEditControlChildren(retCtrl, width);
+
+   // Don't forget to register ourselves
+   _registerEditControl(mScriptValue, "value");
+   retCtrl->addObject(mScriptValue);
+
+   // enable script value
+   String angleInput = String::ToString("%d.apply(%d.getText());", getId(), mScriptValue->getId());
+   mScriptValue->setField("AltCommand", angleInput.c_str());
+   mScriptValue->setField("Validate", angleInput.c_str());
+
+   // change command for pitch roll yaw input.
+   angleInput = String::ToString("%d.applyRotation(mEulDegToAng(%d.getText() SPC %d.getText() SPC %d.getText()));", getId(), mCtrlX->getId(), mCtrlY->getId(), mCtrlZ->getId());
+   
+
+   mCtrlX->setField("AltCommand", angleInput.c_str());
+   mCtrlX->setField("Validate", angleInput.c_str());
+   mCtrlX->setDataField(StringTable->insert("format"), NULL, "%.6f");
+
+   mCtrlY->setField("AltCommand", angleInput.c_str());
+   mCtrlY->setField("Validate", angleInput.c_str());
+   mCtrlY->setDataField(StringTable->insert("format"), NULL, "%.6f");
+
+   mCtrlZ->setField("AltCommand", angleInput.c_str());
+   mCtrlZ->setField("Validate", angleInput.c_str());
+   mCtrlZ->setDataField(StringTable->insert("format"), NULL, "%.6f");
+}
+
+void GuiInspectorTypeMatrixRotation::updateValue()
+{
+   if (mField)
+   {
+      Update::updateValue();
+      const char* data = getData();
+
+      angAx.set(Point3F(dAtof(StringUnit::getUnit(data, 0, " \t\n")),
+         dAtof(StringUnit::getUnit(data, 1, " \t\n")),
+         dAtof(StringUnit::getUnit(data, 2, " \t\n"))),
+         mDegToRad(dAtof(StringUnit::getUnit(data, 3, " \t\n"))));
+
+      eulAng = mAngToEul(angAx);
+
+      U32 elementCount = StringUnit::getUnitCount(data, " ");
+
+      if (elementCount > 0)
+      {
+         char szBuffer[64];
+         dSprintf(szBuffer, 64, "%.6f", eulAng.x);
+         mCtrlX->setText(szBuffer);
+      }
+      if (elementCount > 1)
+      {
+         char szBuffer[64];
+         dSprintf(szBuffer, 64, "%.6f", eulAng.y);
+         mCtrlY->setText(szBuffer);
+      }
+      if (elementCount > 2)
+      {
+         char szBuffer[64];
+         dSprintf(szBuffer, 64, "%.6f", eulAng.z);
+         mCtrlZ->setText(szBuffer);
+      }
+
+      mScriptValue->setText(data);
+
+      mEdit->setDataField(StringTable->insert("tooltip"), NULL, data);
+   }
+
+}
+
+bool GuiInspectorTypeMatrixRotation::resize(const Point2I& newPosition, const Point2I& newExtent)
+{
+   if (!Parent::resize(newPosition, newExtent))
+      return false;
+
+   if (mEdit != NULL)
+   {
+      return updateRects();
+   }
+   return false;
+}
+
+bool GuiInspectorTypeMatrixRotation::updateRects()
+{
+   S32 rowSize = 18;
+   S32 dividerPos, dividerMargin;
+   mInspector->getDivider(dividerPos, dividerMargin);
+   Point2I fieldExtent = getExtent();
+   Point2I fieldPos = getPosition();
+
+   mEditCtrlRect.set(fieldExtent.x - dividerPos + dividerMargin, 1, dividerPos - dividerMargin - 29, fieldExtent.y);
+   S32 cellWidth = mCeil((dividerPos - dividerMargin - 29));
+
+   mCtrlX->setExtent(Point2I(cellWidth - 3, 18));
+   mCtrlY->setExtent(Point2I(cellWidth - 3, 18));
+   mCtrlZ->setExtent(Point2I(cellWidth - 3, 18));
+
+   mCaptionLabel->resize(Point2I(mProfile->mTextOffset.x, 0), Point2I(fieldExtent.x, rowSize));
+   mDimensionLabelX->resize(Point2I(fieldExtent.x - dividerPos - 30, 0), Point2I(30, rowSize));
+   mDimensionLabelY->resize(Point2I(fieldExtent.x - dividerPos - 30, rowSize + 3), Point2I(50, rowSize));
+   mDimensionLabelZ->resize(Point2I(fieldExtent.x - dividerPos - 30, rowSize + rowSize + 6), Point2I(40, rowSize));
+
+   mEdit->resize(mEditCtrlRect.point, mEditCtrlRect.extent);
+
+   mCopyButton->resize(Point2I(mProfile->mTextOffset.x, rowSize + 3), Point2I(45, 15));
+   mPasteButton->resize(Point2I(mProfile->mTextOffset.x, rowSize + rowSize + 6), Point2I(45, 15));
+
+   return true;
+}
+
+void GuiInspectorTypeMatrixRotation::updateAng(AngAxisF newAngAx)
+{
+   angAx.axis = newAngAx.axis;
+   angAx.angle = mRadToDeg(newAngAx.angle);
+}
+
+void GuiInspectorTypeMatrixRotation::updateEul(EulerF newEul)
+{
+   eulAng = newEul;
+}
+
+void GuiInspectorTypeMatrixRotation::updateData()
+{
+   StringTableEntry data = getValue();
+   setData(data);
+}
+
+StringTableEntry GuiInspectorTypeMatrixRotation::getValue()
+{
+   String angBuffer = String::ToString("%.6f %.6f %.6f %.6f", angAx.axis.x, angAx.axis.y, angAx.axis.z, angAx.angle);
+   return StringTable->insert(angBuffer.c_str());
+}
+
+DefineEngineMethod(GuiInspectorTypeMatrixRotation, applyRotation, void, (AngAxisF angAx), , "")
+{
+   object->updateAng(angAx);
+   object->updateEul(mAngToEul(angAx));
+   object->updateData();
+}
+

+ 142 - 1
Engine/source/gui/editor/guiInspectorTypes.h

@@ -42,6 +42,10 @@
 #include "gui/buttons/guiBitmapButtonCtrl.h"
 #endif
 
+#ifndef _GUITEXTEDITSLIDERCTRL_H_
+#include "gui/controls/guiTextEditSliderCtrl.h"
+#endif
+
 class GuiPopUpMenuCtrl;
 
 /// A base class for other inspector field types which
@@ -576,5 +580,142 @@ public:
    virtual void _populateMenu( GuiPopUpMenuCtrl *menu );
 };
 
+//-----------------------------------------------------------------------------
+// Two Dimensional Field base GuiInspectorField Class
+//-----------------------------------------------------------------------------
+
+class GuiInspectorType2DValue : public GuiInspectorField
+{
+private:
+   typedef GuiInspectorField Parent;
+protected:
+   GuiTextEditSliderCtrl* mCtrlX;
+   GuiControl* mLabelX;
+   GuiControl* mContainerX;
+   GuiTextEditSliderCtrl* mCtrlY;
+   GuiControl* mLabelY;
+   GuiControl* mContainerY;
+   GuiTextCtrl* mScriptValue;
+
+public:
+   GuiTextCtrl* mCaptionLabel;
+   GuiTextCtrl* mDimensionLabelX;
+   GuiTextCtrl* mDimensionLabelY;
+   GuiButtonCtrl* mCopyButton;
+   GuiButtonCtrl* mPasteButton;
+
+   virtual void constructEditControlChildren(GuiControl* retCtrl, S32 width);
+   virtual void updateValue();
+   virtual bool resize(const Point2I& newPosition, const Point2I& newExtent);
+   virtual bool updateRects();
+};
+
+//-----------------------------------------------------------------------------
+// Three Dimensional Field base GuiInspectorField Class
+//-----------------------------------------------------------------------------
+
+class GuiInspectorType3DValue : public GuiInspectorType2DValue
+{
+private:
+   typedef GuiInspectorType2DValue Parent;
+protected:
+   GuiTextEditSliderCtrl* mCtrlZ;
+   GuiControl* mLabelZ;
+   GuiControl* mContainerZ;
+
+public:
+   GuiTextCtrl* mDimensionLabelZ;
+
+   virtual void constructEditControlChildren(GuiControl* retCtrl, S32 width);
+   virtual void updateValue();
+   virtual bool resize(const Point2I& newPosition, const Point2I& newExtent);
+   virtual bool updateRects();
+};
+
+//-----------------------------------------------------------------------------
+// Four Dimensional Field base GuiInspectorField Class
+//-----------------------------------------------------------------------------
+
+class GuiInspectorType4DValue : public GuiInspectorType3DValue
+{
+private:
+   typedef GuiInspectorType3DValue Parent;
+protected:
+   GuiTextEditCtrl* mCtrlW;
+
+public:
+   GuiTextCtrl* mDimensionLabelW;
+
+   virtual void constructEditControlChildren(GuiControl* retCtrl, S32 width);
+   virtual void updateValue();
+   virtual bool resize(const Point2I& newPosition, const Point2I& newExtent);
+   virtual bool updateRects();
+};
+
+//-----------------------------------------------------------------------------
+// TypePoint2F GuiInspectorField Class
+//-----------------------------------------------------------------------------
+
+class GuiInspectorTypePoint2F : public GuiInspectorType2DValue
+{
+private:
+   typedef GuiInspectorType2DValue Parent;
+public:
+   DECLARE_CONOBJECT(GuiInspectorTypePoint2F);
+   static void consoleInit();
+   virtual GuiControl* constructEditControl();
+};
+
+class GuiInspectorTypePoint2I : public GuiInspectorTypePoint2F
+{
+private:
+   typedef GuiInspectorTypePoint2F Parent;
+public:
+   DECLARE_CONOBJECT(GuiInspectorTypePoint2I);
+   static void consoleInit();
+   virtual GuiControl* constructEditControl();
+};
+
+
+
+//-----------------------------------------------------------------------------
+// TypePoint3F GuiInspectorField Class
+//-----------------------------------------------------------------------------
+
+class GuiInspectorTypePoint3F : public GuiInspectorType3DValue
+{
+private:
+   typedef GuiInspectorType3DValue Parent;
+public:
+   DECLARE_CONOBJECT(GuiInspectorTypePoint3F);
+   static void consoleInit();
+   virtual GuiControl* constructEditControl();
+};
+
+//-----------------------------------------------------------------------------
+// TypeMatrixRotation GuiInspectorField Class
+//-----------------------------------------------------------------------------
+
+class GuiInspectorTypeMatrixRotation : public GuiInspectorType3DValue
+{
+private:
+   typedef GuiInspectorType3DValue Parent;
+   typedef GuiInspectorField Update;
+public:
+   AngAxisF angAx;
+   EulerF eulAng;
+   DECLARE_CONOBJECT(GuiInspectorTypeMatrixRotation);
+   static void consoleInit();
+   virtual GuiControl* constructEditControl();
+   virtual void constructEditControlChildren(GuiControl* retCtrl, S32 width);
+   virtual void updateValue();
+   virtual bool resize(const Point2I& newPosition, const Point2I& newExtent);
+   virtual bool updateRects();
+
+   void updateAng(AngAxisF newAngAx);
+   void updateEul(EulerF newEul);
 
-#endif // _GUI_INSPECTOR_TYPES_H_
+   virtual void updateData();
+   virtual StringTableEntry getValue();
+};
+#endif // _GUI_INSPECTOR_TYPES_H_

+ 7 - 4
Engine/source/gui/editor/inspector/field.cpp

@@ -673,13 +673,16 @@ void GuiInspectorField::_executeSelectedCallback()
 
 //-----------------------------------------------------------------------------
 
-void GuiInspectorField::_registerEditControl( GuiControl *ctrl )
+void GuiInspectorField::_registerEditControl(GuiControl* ctrl, StringTableEntry suffix)
 {
+   if (ctrl->isProperlyAdded()) return;
+   ctrl->setInternalName(suffix);
+
    char szName[512];
-   if(mInspector->getInspectObject() != nullptr)
-      dSprintf( szName, 512, "IE_%s_%d_%s_Field", ctrl->getClassName(), mInspector->getInspectObject()->getId(), mCaption);
+   if (mInspector->getInspectObject() != nullptr)
+      dSprintf(szName, 512, "IE_%s_%d_%s_%s_Field", ctrl->getClassName(), mInspector->getInspectObject()->getId(), suffix, mCaption);
    else
-      dSprintf(szName, 512, "IE_%s_%s_Field", ctrl->getClassName(), mCaption);
+      dSprintf(szName, 512, "IE_%s_%s_%s_Field", ctrl->getClassName(), suffix, mCaption);
 
    // Register the object
    ctrl->registerObject( szName );

+ 1 - 1
Engine/source/gui/editor/inspector/field.h

@@ -100,7 +100,7 @@ class GuiInspectorField : public GuiControl
       //Special edit field, variable type
       StringTableEntry mVariableType;
 
-      virtual void _registerEditControl( GuiControl *ctrl );
+      virtual void _registerEditControl(GuiControl* ctrl, StringTableEntry suffix = "");
       virtual void _executeSelectedCallback();
       
       void _setFieldDocs( StringTableEntry docs );

+ 2 - 2
Engine/source/gui/worldEditor/editor.cpp

@@ -110,7 +110,7 @@ void EditManager::editorDisabled()
    for(SimGroupIterator itr(Sim::getRootGroup());  *itr; ++itr)
    {
       SimObject *so = *itr;
-      AssertFatal(so->isProperlyAdded() && !so->isRemoved(), "bad");
+      AssertFatal(so->isProperlyAdded() && !so->isRemoved(), avar("%s added but not removed!", so->getName()));
       so->onEditorDisable();
    }
 
@@ -161,4 +161,4 @@ DefineEngineMethod( EditManager, editorDisabled, void, (), , "Perform the onEdit
 DefineEngineMethod( EditManager, isEditorEnabled, bool, (), , "Return the value of gEditingMission." )
 {
    return gEditingMission;
-}
+}

+ 67 - 0
Engine/source/math/mAngAxis.cpp

@@ -34,6 +34,42 @@ AngAxisF & AngAxisF::set( const QuatF & q )
       axis.set(1.0f,0.0f,0.0f);
    return *this;
 }
+AngAxisF& AngAxisF::set(const EulerF& eul)
+{
+   F32 c1 = mCos(eul.y / 2);
+   F32 s1 = mSin(eul.y / 2);
+   F32 c2 = mCos(eul.z / 2);
+   F32 s2 = mSin(eul.z / 2);
+   F32 c3 = mCos(eul.x / 2);
+   F32 s3 = mSin(eul.x / 2);
+
+   F32 c1c2 = c1 * c2;
+   F32 s1s2 = s1 * s2;
+
+   F32 w = c1c2 * c3 - s1s2 * s3;
+   F32 x = c1c2 * s3 + s1s2 * c3;
+   F32 y = s1 * c2 * c3 + c1 * s2 * s3;
+   F32 z = c1 * s2 * c3 - s1 * c2 * s3;
+
+   angle = 2.0f * mAcos(w);
+
+   F32 norm = x * x + y * y + z * z;
+   if (norm < POINT_EPSILON)
+   {
+      axis.set(1.0f, 0.0f, 0.0f);
+   }
+   else
+   {
+      norm = mSqrt(norm);
+      x /= norm;
+      y /= norm;
+      z /= norm;
+   }
+
+   axis.set(x, y, z);
+
+   return *this;
+}
 
 AngAxisF & AngAxisF::set( const MatrixF & mat )
 {
@@ -93,3 +129,34 @@ void AngAxisF::RotateZ(F32 angle, const Point3F & from, Point3F * to)
    mat.mulV(from,to);
 }
 
+EulerF AngAxisF::toEuler() const
+{
+   EulerF r;
+
+   F32 s = mSin(angle);
+   F32 c = mCos(angle);
+   F32 invc = 1 - c;
+
+   if ((axis.x * axis.y * invc + axis.z * s) > (1 - POINT_EPSILON))
+   {
+      r.y = 2.0f * mAtan2(axis.x * mSin(angle / 2), mCos(angle / 2));
+      r.z = -M_HALFPI_F;
+      r.x = 0.f;
+      return r;
+   }
+
+   if ((axis.x * axis.y * invc + axis.z * s) < -(1 - POINT_EPSILON))
+   {
+      r.y = -2.0f * mAtan2(axis.x * mSin(angle / 2), mCos(angle / 2));
+      r.z = -M_HALFPI_F;
+      r.x = 0.f;
+      return r;
+   }
+
+   r.x = mAtan2(axis.x * s - axis.y * axis.z * invc, 1.0f - (axis.x * axis.x + axis.z * axis.z) * invc);
+   r.y = mAtan2(axis.y * s - axis.x * axis.z * invc, 1.0f - (axis.y * axis.y + axis.z * axis.z) * invc);
+   r.z = mAsin(axis.x * axis.y * invc + axis.z * s);
+
+   return r;
+
+}

+ 2 - 0
Engine/source/math/mAngAxis.h

@@ -45,6 +45,7 @@ class AngAxisF
    explicit AngAxisF( const QuatF &q );
 
    AngAxisF& set( const Point3F & _axis, F32 _angle );
+   AngAxisF& set( const EulerF & _axis);
    AngAxisF& set( const MatrixF & m );
    AngAxisF& set( const QuatF & q );
 
@@ -60,6 +61,7 @@ class AngAxisF
    static void RotateX(F32 angle, const Point3F & from, Point3F * to);
    static void RotateY(F32 angle, const Point3F & from, Point3F * to);
    static void RotateZ(F32 angle, const Point3F & from, Point3F * to);
+   EulerF toEuler() const;
 };
 
 //----------------------------------------------------------------------------

+ 10 - 0
Engine/source/math/mConsoleFunctions.cpp

@@ -464,3 +464,13 @@ DefineEngineFunction(mDecToBin, const char*, (S32 n), , "convert decimal to a bi
    }
    return ret.c_str();
 }
+
+DefineEngineFunction(mEulDegToAng, AngAxisF, (EulerF euler), , "convert euler to degrees")
+{
+   return mEulDegToAng(euler);
+}
+
+DefineEngineFunction(mAngToEul, EulerF, (AngAxisF angAx), , "convert degrees to euler")
+{
+   return mAngToEul(angAx);
+}

+ 14 - 0
Engine/source/math/mMath.h

@@ -52,4 +52,18 @@
 #include "math/mRotation.h"
 #endif
 
+inline AngAxisF mEulDegToAng(EulerF euler)
+{
+   AngAxisF angAx;
+   angAx.set(euler * M_PI_F / 180.0f);
+   return angAx;
+}
+
+inline EulerF mAngToEul(AngAxisF angAx)
+{
+   EulerF euler = angAx.toEuler();
+   euler *= 180.0f / M_PI_F;
+   return euler;
+}
+
 #endif //_MMATH_H_

+ 20 - 0
Templates/BaseGame/game/tools/gui/profiles.ed.tscript

@@ -207,6 +207,26 @@ new GuiControlProfile (ToolsGuiTextBoldProfile : ToolsGuiTextProfile)
    fontType = "Arial Bold";
 };
 
+if( !isObject( ToolsGuiXDimensionText ) )
+new GuiControlProfile (ToolsGuiXDimensionText : ToolsGuiTextBoldProfile)
+{
+   fillColor = "255 129 123 120";
+};
+
+if( !isObject( ToolsGuiYDimensionText ) )
+new GuiControlProfile (ToolsGuiYDimensionText : ToolsGuiTextBoldProfile)
+{
+   fillColor = "129 255 123 120";
+};
+
+
+if( !isObject( ToolsGuiZDimensionText ) )
+new GuiControlProfile (ToolsGuiZDimensionText : ToolsGuiTextBoldProfile)
+{
+   fillColor = "123 129 255 120";
+};
+
+
 if( !isObject( ToolsGuiTextBoldCenterProfile ) )
 new GuiControlProfile (ToolsGuiTextBoldCenterProfile : ToolsGuiTextProfile)
 {