Browse Source

Extent Change and MinExtent Error

This fixes an error when the sizing mode of width, height, or relative cause the extent to shrink  below the minExtent. When sizing up again the extent will now be correctly restored.
Peter Robinson 4 years ago
parent
commit
f61e389111

+ 52 - 6
engine/source/gui/guiControl.cc

@@ -58,9 +58,10 @@ GuiControl::GuiControl()
 {
    mLayer = 0;
    mBounds.set(0, 0, 64, 64);
+   mStoredExtent.set(0, 0);
    mRenderInsetLT.set(0, 0);
    mRenderInsetRB.set(0, 0);
-   mMinExtent.set(8, 2);			// Set to 8x2 so GuiControl can be used as a separator.
+   mMinExtent.set(0, 0);
 
    mProfile = NULL;
 
@@ -164,8 +165,8 @@ void GuiControl::initPersistFields()
    addField("VertSizing",        TypeEnum,			Offset(mVertSizing, GuiControl), 1, &gVertSizingTable);
 
    addField("Position",          TypePoint2I,		Offset(mBounds.point, GuiControl));
-   addField("Extent",            TypePoint2I,		Offset(mBounds.extent, GuiControl));
-   addField("MinExtent",         TypePoint2I,		Offset(mMinExtent, GuiControl));
+   addProtectedField("Extent",            TypePoint2I,		Offset(mBounds.extent, GuiControl), &setExtentFn, &defaultProtectedGetFn, "The size of the control writen as width and height.");
+   addProtectedField("MinExtent",         TypePoint2I,		Offset(mMinExtent, GuiControl), &setMinExtentFn, &defaultProtectedGetFn, &writeMinExtentFn, "The extent will not shrink below this size.");
    addField("canSave",           TypeBool,			Offset(mCanSave, GuiControl));
    addField("Visible",           TypeBool,			Offset(mVisible, GuiControl));
    addDepricatedField("Modal");
@@ -353,13 +354,13 @@ void GuiControl::resize(const Point2I &newPosition, const Point2I &newExtent)
    if (extentChanged) {
       //call set update both before and after
       setUpdate();
+      mBounds.set(newPosition, actualNewExtent);
       iterator i;
       for(i = begin(); i != end(); i++)
       {
          GuiControl *ctrl = static_cast<GuiControl *>(*i);
          ctrl->parentResized(oldExtent - (ctrl->mRenderInsetLT + ctrl->mRenderInsetRB), actualNewExtent - (ctrl->mRenderInsetLT + ctrl->mRenderInsetRB));
       }
-      mBounds.set(newPosition, actualNewExtent);
 
       GuiControl *parent = getParent();
       if (parent)
@@ -418,8 +419,17 @@ void GuiControl::parentResized(const Point2I &oldParentExtent, const Point2I &ne
     S32 deltaX = newParentExtent.x - oldParentExtent.x;
     S32 deltaY = newParentExtent.y - oldParentExtent.y;
 
+	//In the case of centering, we want to make doubly sure we are using the inner rect.
+	GuiControl* parent = getParent();
+	Point2I parentInnerExt = Point2I(newParentExtent);
+	if(mHorizSizing == horizResizeCenter || mVertSizing == vertResizeCenter)
+	{
+		//This is based on the "new" outer extent of the parent.
+		parentInnerExt = getInnerRect(Point2I(0, 0), parent->mBounds.extent, NormalState, parent->mProfile).extent;
+	}
+
     if (mHorizSizing == horizResizeCenter)
-       newPosition.x = (newParentExtent.x - mBounds.extent.x) >> 1;
+       newPosition.x = (parentInnerExt.x - mBounds.extent.x) >> 1;
     else if (mHorizSizing == horizResizeWidth)
         newExtent.x += deltaX;
     else if (mHorizSizing == horizResizeLeft)
@@ -434,7 +444,7 @@ void GuiControl::parentResized(const Point2I &oldParentExtent, const Point2I &ne
    }
 
     if (mVertSizing == vertResizeCenter)
-       newPosition.y = (newParentExtent.y - mBounds.extent.y) >> 1;
+       newPosition.y = (parentInnerExt.y - mBounds.extent.y) >> 1;
     else if (mVertSizing == vertResizeHeight)
         newExtent.y += deltaY;
     else if (mVertSizing == vertResizeTop)
@@ -448,9 +458,45 @@ void GuiControl::parentResized(const Point2I &oldParentExtent, const Point2I &ne
       newExtent.y = newBottom - newTop;
    }
 
+   newExtent = extentBattery(newExtent);
+
    resize(newPosition, newExtent);
 }
 
+Point2I GuiControl::extentBattery(Point2I &newExtent)
+{
+	if (mMinExtent.x == 0 && mMinExtent.y == 0)
+	{
+		return newExtent;
+	}
+
+	Point2I result = Point2I(newExtent);
+	if (newExtent.x < mBounds.extent.x && newExtent.x < mMinExtent.x)
+	{
+		mStoredExtent.x += mBounds.extent.x > mMinExtent.x ? (mMinExtent.x - newExtent.x) : (mBounds.extent.x - newExtent.x);
+		result.x = mMinExtent.x;
+	}
+	else if (newExtent.x > mBounds.extent.x && mStoredExtent.x > 0)
+	{
+		S32 charge = getMin(newExtent.x - mBounds.extent.x, mStoredExtent.x);
+		mStoredExtent.x -= charge;
+		result.x = newExtent.x - charge;
+	}
+
+	if (newExtent.y < mBounds.extent.y && newExtent.y < mMinExtent.y)
+	{
+		mStoredExtent.y += mBounds.extent.y > mMinExtent.y ? (mMinExtent.y - newExtent.y) : (mBounds.extent.y - newExtent.y);
+		result.y = mMinExtent.y;
+	}
+	else if (newExtent.y > mBounds.extent.y && mStoredExtent.y > 0)
+	{
+		S32 charge = getMin(newExtent.y - mBounds.extent.y, mStoredExtent.y);
+		mStoredExtent.y -= charge;
+		result.y = newExtent.y - charge;
+	}
+	return result;
+}
+
 //----------------------------------------------------------------
 
 void GuiControl::onRender(Point2I offset, const RectI &updateRect)

+ 13 - 1
engine/source/gui/guiControl.h

@@ -195,6 +195,8 @@ protected:
     S32 mHorizSizing;      ///< Set from horizSizingOptions.
     S32 mVertSizing;       ///< Set from vertSizingOptions.
 
+	Point2I mStoredExtent; //Used in conjunction with the min extent.
+
     StringTableEntry	mConsoleVariable;
     StringTableEntry	mConsoleCommand;
     StringTableEntry	mAltConsoleCommand;
@@ -309,9 +311,13 @@ public:
 	virtual const char*      getText();
 
 	// Text Property Accessors
-	static bool setTextProperty(void* obj, const char* data) { static_cast<GuiControl*>(obj)->setText(data); return true; }
+	static bool setTextProperty(void* obj, const char* data) { static_cast<GuiControl*>(obj)->setText(data); return false; }
 	static const char* getTextProperty(void* obj, const char* data) { return static_cast<GuiControl*>(obj)->getText(); }
 
+	static bool setExtentFn(void* obj, const char* data) { GuiControl* ctrl = static_cast<GuiControl*>(obj); Vector2 v = Vector2(data); ctrl->setExtent(Point2I(v.x, v.y)); ctrl->resetStoredExtent(); return false; }
+	static bool setMinExtentFn(void* obj, const char* data) { GuiControl* ctrl = static_cast<GuiControl*>(obj); Vector2 v = Vector2(data); ctrl->mMinExtent.set(v.x, v.y); ctrl->resetStoredExtent(); return false; }
+	static bool writeMinExtentFn(void* obj,  const char* data) { GuiControl* ctrl = static_cast<GuiControl*>(obj); return ctrl->mMinExtent.x != 0 || ctrl->mMinExtent.y != 0; }
+
     /// @}
 
     /// @name Flags
@@ -732,6 +738,12 @@ public:
     virtual void inspectPostApply();
     virtual void inspectPreApply();
 
+	//Stores or spends stored extent
+	Point2I extentBattery(Point2I &newExtent);
+
+	//Expells all stored extent
+	inline void resetStoredExtent() { mStoredExtent.set(0,0); }
+
 protected:
 	virtual void interpolateTick(F32 delta) {};
 	virtual void processTick() {};

+ 1 - 0
engine/source/gui/guiControl_ScriptBinding.h

@@ -278,6 +278,7 @@ ConsoleMethodWithDocs( GuiControl, setExtent, ConsoleVoid, 4, 4, (int width, int
 {
    Point2I kExt(dAtoi(argv[2]), dAtoi(argv[3]));
    object->setExtent(kExt);
+   object->resetStoredExtent();
 }
 
 /*! Get the minimum allowed size of the control.