Browse Source

Resize Mode Fill and Better Handling for Min Extent in Frame Set

This update adds a new experimental resize mode called "Fill" which attempts to always keep a control at position 0, 0 and make it's extent match the parent's content area. You're results may vary. I'm sure I'll be revisiting this to handle various cases in the future. This code also greatly improves how Min Extent is handled by the Frame Set. Instead of modifying the Min Extent of children, the Frame Set now safely clips the children if they can't fit inside their frame.
Peter Robinson 2 years ago
parent
commit
ff8b246e09

+ 5 - 8
editor/AssetAdmin/AssetAdmin.cs

@@ -88,7 +88,7 @@ function AssetAdmin::buildLibrary(%this)
         VertSizing = "bottom";
         Position = "0 0";
         Extent = "330 380";
-        MinExtent = "100 100";
+        MinExtent = "200 100";
         text = "Asset Library";
         canMove = true;
         canClose = false;
@@ -168,10 +168,9 @@ function AssetAdmin::buildInspector(%this)
     {
         HorizSizing = "right";
         VertSizing = "bottom";
-        Position = "0 0";
-        Extent = "706 380";
-        MinExtent = "100 100";
         text = "Asset Inspector";
+		Extent = "706 380";
+		MinExtent = "500 250";
         canMove = true;
         canClose = false;
         canMinimize = true;
@@ -189,11 +188,9 @@ function AssetAdmin::buildInspector(%this)
 	%this.inspector = new GuiControl()
 	{
 		class = "AssetInspector";
-        HorizSizing = "width";
-        VertSizing = "height";
-		Position="0 0";
 		Extent="700 370";
-		MinExtent="350 222";
+        HorizSizing = "fill";
+        VertSizing = "fill";
 	};
 	ThemeManager.setProfile(%this.inspector, "overlayProfile");
 

+ 1 - 1
editor/AssetAdmin/AssetInspector.cs

@@ -88,7 +88,7 @@ function AssetInspector::onAdd(%this)
 		HorizSizing = width;
 		VertSizing = height;
 		Position = "0 34";
-		Extent = "700 320";
+		Extent = "700 336";
 		TabPosition = top;
 		Visible = false;
 	};

+ 2 - 0
editor/EditorCore/scripts/EditorProjectCard.cs

@@ -52,6 +52,8 @@ function EditorProjectCard::onAdd(%this)
 		Extent="200 120";
 		hScrollBar="alwaysOff";
 		vScrollBar="alwaysOn";
+		HorizSizing = "right";
+		VertSizing = "bottom";
 		constantThumbHeight="0";
 		showArrowButtons="0";
 		scrollBarThickness="6";

+ 2 - 0
engine/source/gui/buttons/guiDropDownCtrl.cc

@@ -94,6 +94,8 @@ GuiDropDownCtrl::GuiDropDownCtrl()
 	mScroll = new GuiScrollCtrl();
 	AssertFatal(mScroll, "GuiDropDownCtrl: Failed to initialize GuiScrollCtrl!");
 	mScroll->setField("profile", "GuiScrollProfile");
+	mScroll->setField("horizSizing","right");
+	mScroll->setField("vertSizing","bottom");
 	mScrollProfile = mScroll->mProfile;
 	mScrollProfile->incRefCount();
 

+ 46 - 4
engine/source/gui/containers/guiFrameSetCtrl.cc

@@ -56,10 +56,6 @@ void GuiFrameSetCtrl::Frame::resize(const Point2I& newPosition, const Point2I& n
 	sizeInsertButtons(newPosition, newExtent);
 	if (control)
 	{
-		if (control->mMinExtent.x > minSize || control->mMinExtent.y > minSize)
-		{
-			control->mMinExtent.set(minSize, minSize);
-		}
 		control->resize(newPosition, newExtent);
 	}
 	if (!child1 && !child2 && owner->isEditMode())
@@ -1133,6 +1129,52 @@ void GuiFrameSetCtrl::undockWindowFromBook(GuiWindowCtrl* window, GuiTabBookCtrl
 	}
 }
 
+void GuiFrameSetCtrl::renderChild(GuiControl* ctrl, const Point2I& offset, const RectI& content, const RectI& clipRect)
+{
+	RectI clip = RectI(clipRect);
+	Frame* frame = mRootFrame.findFrameWithCtrl(ctrl);
+	if (frame)
+	{
+		Point2I framePos = localToGlobalCoord(frame->localPosition);
+		RectI area(framePos, frame->extent);
+		clip.intersect(area);
+	}
+
+	Parent::renderChild(ctrl, offset, content, clip);
+}
+
+GuiControl* GuiFrameSetCtrl::findHitControl(const Point2I& pt, S32 initialLayer)
+{
+	iterator i = end(); // find in z order (last to first)
+	while (i != begin())
+	{
+		i--;
+		GuiControl* ctrl = static_cast<GuiControl*>(*i);
+		RectI ctrlRect = RectI(localToGlobalCoord(ctrl->getPosition()), ctrl->getExtent());
+		Frame* frame = mRootFrame.findFrameWithCtrl(ctrl);
+		if (frame)
+		{
+			Point2I framePos = localToGlobalCoord(frame->localPosition);
+			RectI area(framePos, frame->extent);
+			ctrlRect.intersect(area);
+		}
+		Point2I globalPoint = localToGlobalCoord(pt);
+		if (initialLayer >= 0 && ctrl->mLayer > initialLayer)
+		{
+			continue;
+		}
+		else if (ctrl->mVisible && ctrl->pointInControl(pt - ctrl->mRenderInsetLT) && ctrl->mUseInput && ctrlRect.pointInRect(globalPoint))
+		{
+			Point2I ptemp = pt - (ctrl->mBounds.point + ctrl->mRenderInsetLT);
+			GuiControl* hitCtrl = ctrl->findHitControl(ptemp);
+
+			if (hitCtrl->mUseInput)
+				return hitCtrl;
+		}
+	}
+	return this;
+}
+
 void GuiFrameSetCtrl::setDropButtonProfile(GuiControlProfile* prof)
 {
 	AssertFatal(prof, "GuiFrameSetCtrl::setDropButtonProfile: invalid content profile");

+ 2 - 0
engine/source/gui/containers/guiFrameSetCtrl.h

@@ -120,6 +120,8 @@ public:
 	void renderDropButton(const GuiFrameSetCtrl::Frame* frame, const RectI& buttonRect, const Point2I& cursorPt, const Point2I& fillPos, const Point2I& fillExt, GuiDirection direction);
 	void handleDropButtons(GuiWindowCtrl* window);
 	void undockWindowFromBook(GuiWindowCtrl* window, GuiTabBookCtrl* book, GuiTabPageCtrl* page);
+	void renderChild(GuiControl* ctrl, const Point2I& offset, const RectI& content, const RectI& clipRect);
+	GuiControl* findHitControl(const Point2I& pt, S32 initialLayer = -1);
 
 	Point2I splitFrame(S32 frameID, bool isVertical);
 	void splitFrame(GuiFrameSetCtrl::Frame* frame, GuiDirection direction);

+ 2 - 8
engine/source/gui/containers/guiGridCtrl.cc

@@ -333,14 +333,8 @@ Point2F GuiGridCtrl::GetGridItemHeight(const S32 totalArea, const S32 maxChainLe
 void GuiGridCtrl::onChildAdded(GuiControl* child)
 {
 	//Ensure the child isn't positioned to the center
-	if (child->getHorizSizing() == horizResizeCenter)
-	{
-		child->setHorizSizing(horizResizeLeft);
-	}
-	if (child->getVertSizing() == vertResizeCenter)
-	{
-		child->setVertSizing(vertResizeTop);
-	}
+	child->preventResizeModeCenter();
+	child->preventResizeModeFill();
 	resize(getPosition(), getExtent());
 
 	Parent::onChildAdded(child);

+ 16 - 2
engine/source/gui/containers/guiScrollCtrl.cc

@@ -49,7 +49,7 @@ IMPLEMENT_CONOBJECT(GuiScrollCtrl);
 GuiScrollCtrl::GuiScrollCtrl()
 {
    mBounds.extent.set(200,200);
-   mScrollBarThickness = 16;
+   mScrollBarThickness = 14;
    mScrollBarDragTolerance = 130;
    mDepressed = false;
    curHitRegion = Content;
@@ -70,6 +70,9 @@ GuiScrollCtrl::GuiScrollCtrl()
    mScrollOffset.set(0, 0);
    mContentExt.set(200,200);
 
+   mHorizSizing = horizResizeFill;
+   mVertSizing = vertResizeFill;
+
    setField("thumbProfile", "GuiScrollThumbProfile");
    setField("arrowProfile", "GuiScrollArrowProfile");
    setField("trackProfile", "GuiScrollTrackProfile");
@@ -117,10 +120,14 @@ void GuiScrollCtrl::resize(const Point2I &newPos, const Point2I &newExt)
 			{
 				GuiControl* ctrl = static_cast<GuiControl*>(*i);
 				ctrl->mRenderInsetRB = Point2I(ctrl->mRenderInsetRB.x + deltaX, ctrl->mRenderInsetRB.y + deltaY);
+				ctrl->preventResizeModeFill();
+				ctrl->preventResizeModeCenter();
 				ctrl->parentResized(mBounds.extent - (ctrl->mRenderInsetLT + ctrl->mRenderInsetRB), mBounds.extent - (ctrl->mRenderInsetLT + ctrl->mRenderInsetRB));
 			}
 
+			mCalcGuard = true;
 			Parent::resize(newPos, newExt);
+			mCalcGuard = false;
 			computeSizes();
 		}
 		mResizeGuard = false;
@@ -135,6 +142,13 @@ void GuiScrollCtrl::childResized(GuiControl *child)
 
 void GuiScrollCtrl::addObject(SimObject* object)
 {
+	//Fill is not supported inside a scroll control
+	GuiControl* child = dynamic_cast<GuiControl*>(object);
+	if (child)
+	{
+		child->preventResizeModeFill();
+		child->preventResizeModeCenter();
+	}
 	Parent::addObject(object);
 	computeSizes();
 }
@@ -1088,7 +1102,7 @@ void GuiScrollCtrl::renderHScrollBar(const Point2I& offset)
 	}
 }
 
-void GuiScrollCtrl::renderChildControls(Point2I offset, RectI content, const RectI& updateRect)
+void GuiScrollCtrl::renderChildControls(const Point2I& offset, const RectI& content, const RectI& updateRect)
 {
 	// offset is the upper-left corner of this control in screen coordinates. It should almost always be the same offset passed into the onRender method.
 	// updateRect is the area that this control was allowed to draw in. It should almost always be the same as the value in onRender.

+ 1 - 1
engine/source/gui/containers/guiScrollCtrl.h

@@ -178,7 +178,7 @@ public:
    virtual void renderVScrollBar(const Point2I& offset);
    virtual void renderHScrollBar(const Point2I& offset);
    virtual GuiControl* findHitControl(const Point2I &pt, S32 initialLayer = -1);
-   virtual void renderChildControls(Point2I offset, RectI content, const RectI& updateRect);
+   virtual void renderChildControls(const Point2I& offset, const RectI& content, const RectI& updateRect);
 };
 
 #endif //_GUI_SCROLL_CTRL_H

+ 2 - 0
engine/source/gui/editor/guiMenuBarCtrl.cc

@@ -718,6 +718,8 @@ void GuiMenuItemCtrl::onChildAdded(GuiControl *child)
 		if(mScroll == NULL)
 		{
 			mScroll = new GuiScrollCtrl();
+			mScroll->setField("horizSizing","right");
+			mScroll->setField("vertSizing","bottom");
 			AssertFatal(mScroll, "GuiMenuItemCtrl::onChildAdded Failed to initialize GuiScrollCtrl!");
 		}
 

+ 73 - 21
engine/source/gui/guiControl.cc

@@ -185,20 +185,22 @@ static EnumTable::Enums horzEnums[] =
     { GuiControl::horizResizeRight,      "right"     },
     { GuiControl::horizResizeWidth,      "width"     },
     { GuiControl::horizResizeLeft,       "left"      },
-   { GuiControl::horizResizeCenter,     "center"    },
-   { GuiControl::horizResizeRelative,   "relative"  }
+    { GuiControl::horizResizeCenter,      "center"   },
+    { GuiControl::horizResizeRelative,    "relative" },
+    { GuiControl::horizResizeFill,        "fill"     }
 };
-static EnumTable gHorizSizingTable(5, &horzEnums[0]);
+static EnumTable gHorizSizingTable(6, &horzEnums[0]);
 
 static EnumTable::Enums vertEnums[] =
 {
     { GuiControl::vertResizeBottom,      "bottom"     },
     { GuiControl::vertResizeHeight,      "height"     },
     { GuiControl::vertResizeTop,         "top"        },
-   { GuiControl::vertResizeCenter,      "center"     },
-   { GuiControl::vertResizeRelative,    "relative"   }
+    { GuiControl::vertResizeCenter,       "center"    },
+    { GuiControl::vertResizeRelative,     "relative"  },
+    { GuiControl::vertResizeFill,         "fill"      }
 };
-static EnumTable gVertSizingTable(5, &vertEnums[0]);
+static EnumTable gVertSizingTable(6, &vertEnums[0]);
 
 void GuiControl::initPersistFields()
 {
@@ -423,10 +425,20 @@ void GuiControl::resize(const Point2I &newPosition, const Point2I &newExtent)
         {
             actualNewPosition.x = (parentInnerExtent.x - actualNewExtent.x) / 2;
         }
+		else if (mHorizSizing == horizResizeFill)
+		{
+			actualNewPosition.x = 0;
+			actualNewExtent.x = parentInnerExtent.x;
+		}
         if (mVertSizing == vertResizeCenter)
         {
             actualNewPosition.y = (parentInnerExtent.y - actualNewExtent.y) / 2;
         }
+		else if (mVertSizing == vertResizeFill)
+		{
+			actualNewPosition.y = 0;
+			actualNewExtent.y = parentInnerExtent.y;
+		}
     }
 
    // only do the child control resizing stuff if you really need to.
@@ -541,7 +553,8 @@ void GuiControl::parentResized(const Point2I &oldParentExtent, const Point2I &ne
 	//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)
+	if(mHorizSizing == horizResizeCenter || mVertSizing == vertResizeCenter ||
+		mHorizSizing == horizResizeFill || mVertSizing == vertResizeFill)
 	{
 		//This is based on the "new" outer extent of the parent.
 		parentInnerExt = parent->getInnerRect().extent;
@@ -553,6 +566,11 @@ void GuiControl::parentResized(const Point2I &oldParentExtent, const Point2I &ne
         newExtent.x += deltaX;
     else if (mHorizSizing == horizResizeLeft)
       newPosition.x += deltaX;
+	else if (mHorizSizing == horizResizeFill)
+	{
+		newPosition.x = 0;
+		newExtent.x = parentInnerExt.x;
+	}
     else if (mHorizSizing == horizResizeRelative && oldParentExtent.x != 0)
     {
         Point2F percent = relPosBatteryH(newPosition.x, newExtent.x, oldParentExtent.x);
@@ -569,6 +587,11 @@ void GuiControl::parentResized(const Point2I &oldParentExtent, const Point2I &ne
         newExtent.y += deltaY;
     else if (mVertSizing == vertResizeTop)
       newPosition.y += deltaY;
+	else if (mVertSizing == vertResizeFill)
+	{
+		newPosition.y = 0;
+		newExtent.y = parentInnerExt.y;
+	}
     else if(mVertSizing == vertResizeRelative && oldParentExtent.y != 0)
     {
         Point2F percent = relPosBatteryV(newPosition.y, newExtent.y, oldParentExtent.y);
@@ -584,6 +607,30 @@ void GuiControl::parentResized(const Point2I &oldParentExtent, const Point2I &ne
    resize(newPosition, newExtent);
 }
 
+void GuiControl::preventResizeModeFill()
+{
+	if (getHorizSizing() == horizResizeFill)
+	{
+		setHorizSizing(horizResizeRight);
+	}
+	if (getVertSizing() == vertResizeFill)
+	{
+		setVertSizing(vertResizeBottom);
+	}
+}
+
+void GuiControl::preventResizeModeCenter()
+{
+	if (getHorizSizing() == horizResizeCenter)
+	{
+		setHorizSizing(horizResizeRight);
+	}
+	if (getVertSizing() == vertResizeCenter)
+	{
+		setVertSizing(vertResizeBottom);
+	}
+}
+
 Point2I GuiControl::extentBattery(Point2I &newExtent)
 {
 	if (mMinExtent.x == 0 && mMinExtent.y == 0)
@@ -936,7 +983,7 @@ bool GuiControl::renderTooltip(Point2I &cursorPos, const char* tipText )
     return true;
 }
 
-void GuiControl::renderChildControls(Point2I offset, RectI content, const RectI &updateRect)
+void GuiControl::renderChildControls(const Point2I& offset, const RectI& content, const RectI& updateRect)
 {
    // offset is the upper-left corner of this control in screen coordinates. It should almost always be the same offset passed into the onRender method.
    // updateRect is the area that this control was allowed to draw in. It should almost always be the same as the value in onRender.
@@ -957,19 +1004,7 @@ void GuiControl::renderChildControls(Point2I offset, RectI content, const RectI
 		  }
 		  if (ctrl->mVisible)
 		  {
-			 ctrl->mRenderInsetLT = content.point - offset;
-			 ctrl->mRenderInsetRB = mBounds.extent - (ctrl->mRenderInsetLT + content.extent);
-			 Point2I childPosition = content.point + ctrl->getPosition();
-			 RectI childClip(childPosition, ctrl->getExtent());
-
-			 if (childClip.intersect(clipRect))
-			 {
-				RectI old = dglGetClipRect();
-				dglSetClipRect(clipRect);
-				glDisable(GL_CULL_FACE);
-				ctrl->onRender(childPosition, RectI(childPosition, ctrl->getExtent()));
-				dglSetClipRect(old);
-			 }
+			 renderChild(ctrl, offset, content, clipRect);
 		  }
 		  size_cpy = objectList.size(); //	CHRIS: i know its wierd but the size of the list changes sometimes during execution of this loop
 		  if(size != size_cpy)
@@ -981,6 +1016,23 @@ void GuiControl::renderChildControls(Point2I offset, RectI content, const RectI
    }
 }
 
+void GuiControl::renderChild(GuiControl* ctrl, const Point2I& offset, const RectI& content, const RectI& clipRect)
+{
+	ctrl->mRenderInsetLT = content.point - offset;
+	ctrl->mRenderInsetRB = mBounds.extent - (ctrl->mRenderInsetLT + content.extent);
+	Point2I childPosition = content.point + ctrl->getPosition();
+	RectI childClip(childPosition, ctrl->getExtent());
+
+	if (childClip.intersect(clipRect))
+	{
+		RectI old = dglGetClipRect();
+		dglSetClipRect(clipRect);
+		glDisable(GL_CULL_FACE);
+		ctrl->onRender(childPosition, RectI(childPosition, ctrl->getExtent()));
+		dglSetClipRect(old);
+	}
+}
+
 void GuiControl::setUpdateRegion(Point2I pos, Point2I ext)
 {
    Point2I upos = localToGlobalCoord(pos);

+ 15 - 4
engine/source/gui/guiControl.h

@@ -175,7 +175,8 @@ public:
         horizResizeWidth,       ///< fixed on the left and right
         horizResizeLeft,        ///< fixed on the right and width
         horizResizeCenter,
-        horizResizeRelative     ///< resize relative
+        horizResizeRelative,    ///< resize relative
+		horizResizeFill         ///< fill the entire content area of the parent
     };
     enum vertSizingOptions
     {
@@ -183,7 +184,8 @@ public:
         vertResizeHeight,       ///< fixed on the top and bottom
         vertResizeTop,          ///< fixed in height and on the bottom
         vertResizeCenter,
-        vertResizeRelative      ///< resize relative
+        vertResizeRelative,     ///< resize relative
+		vertResizeFill          ///< fill the entire content area of the parent
     };
 	enum TextRotationOptions
 	{
@@ -459,7 +461,13 @@ public:
     /// @param   oldParentExtent   The old size of the parent object
     /// @param   newParentExtent   The new size of the parent object
     virtual void parentResized(const Point2I &oldParentExtent, const Point2I &newParentExtent);
-    /// @}
+    
+	/// Removes the resize mode of fill and changes it to right or bottom
+	void preventResizeModeFill();
+
+	/// Removes the resize mode of center and changes it to right or bottom
+	void preventResizeModeCenter();
+	/// @}
 
     /// @name Rendering
     /// @{
@@ -478,7 +486,10 @@ public:
     /// @param   offset   The top left of the parent control
     /// @param   contentOffset   The top left of the parent's content
     /// @param   updateRect   The screen area this control has drawing access to
-    virtual void renderChildControls(Point2I offset, RectI content, const RectI &updateRect);
+    virtual void renderChildControls(const Point2I& offset, const RectI& content, const RectI& updateRect);
+
+	/// Renders a single child control
+	virtual void renderChild(GuiControl* ctrl, const Point2I& offset, const RectI& content, const RectI& clipRect);
 
     /// Sets the area (local coordinates) this control wants refreshed each frame
     /// @param   pos   UpperLeft point on rectangle of refresh area