Przeglądaj źródła

GuiGridCtrl

This consolidates our grid positioning controls into a single control. GuiArrayCtrl is no longer a con object and is purely used for shared functionality between a few children. GuiControlArrayControl and GuiDynamicCtrlArrayControl have been removed. GuiGridControl has been renamed GuiGridCtrl and has been rewritten from scratch to have a range of flexible display options. GuiDynamicCtrlArrayControls have been replaced in the toolbox.
Peter Robinson 5 lat temu
rodzic
commit
aaa4ccaf1e

BIN
engine/compilers/VisualStudio 2017/.vs/Torque 2D/v15/Browse.VC.db


BIN
engine/compilers/VisualStudio 2017/.vs/Torque 2D/v15/Solution.VC.db


+ 2 - 4
engine/compilers/VisualStudio 2017/Torque 2D.vcxproj

@@ -622,9 +622,7 @@
     <ClCompile Include="..\..\source\gui\buttons\guiCheckBoxCtrl.cc" />
     <ClCompile Include="..\..\source\gui\buttons\guiCheckBoxCtrl.cc" />
     <ClCompile Include="..\..\source\gui\buttons\guiRadioCtrl.cc" />
     <ClCompile Include="..\..\source\gui\buttons\guiRadioCtrl.cc" />
     <ClCompile Include="..\..\source\gui\containers\guiAutoScrollCtrl.cc" />
     <ClCompile Include="..\..\source\gui\containers\guiAutoScrollCtrl.cc" />
-    <ClCompile Include="..\..\source\gui\containers\guiCtrlArrayCtrl.cc" />
     <ClCompile Include="..\..\source\gui\containers\guiDragAndDropCtrl.cc" />
     <ClCompile Include="..\..\source\gui\containers\guiDragAndDropCtrl.cc" />
-    <ClCompile Include="..\..\source\gui\containers\guiDynamicCtrlArrayCtrl.cc" />
     <ClCompile Include="..\..\source\gui\containers\guiFormCtrl.cc" />
     <ClCompile Include="..\..\source\gui\containers\guiFormCtrl.cc" />
     <ClCompile Include="..\..\source\gui\containers\guiFrameCtrl.cc" />
     <ClCompile Include="..\..\source\gui\containers\guiFrameCtrl.cc" />
     <ClCompile Include="..\..\source\gui\containers\guiPaneCtrl.cc" />
     <ClCompile Include="..\..\source\gui\containers\guiPaneCtrl.cc" />
@@ -889,6 +887,8 @@
     <ClInclude Include="..\..\source\graphics\TextureObject.h" />
     <ClInclude Include="..\..\source\graphics\TextureObject.h" />
     <ClInclude Include="..\..\source\gui\buttons\guiCheckBoxCtrl_ScriptBinding.h" />
     <ClInclude Include="..\..\source\gui\buttons\guiCheckBoxCtrl_ScriptBinding.h" />
     <ClInclude Include="..\..\source\gui\containers\guiGridCtrl.h" />
     <ClInclude Include="..\..\source\gui\containers\guiGridCtrl.h" />
+    <ClInclude Include="..\..\source\gui\containers\guiGridCtrl_ScriptBinding.h" />
+    <ClInclude Include="..\..\source\gui\containers\guiScrollCtrl_ScriptBinding.h" />
     <ClInclude Include="..\..\source\gui\containers\guiTabBookCtrl_ScriptBinding.h" />
     <ClInclude Include="..\..\source\gui\containers\guiTabBookCtrl_ScriptBinding.h" />
     <ClInclude Include="..\..\source\gui\guiArrayCtrl.h" />
     <ClInclude Include="..\..\source\gui\guiArrayCtrl.h" />
     <ClInclude Include="..\..\source\gui\guiBackgroundCtrl.h" />
     <ClInclude Include="..\..\source\gui\guiBackgroundCtrl.h" />
@@ -1211,9 +1211,7 @@
     <ClInclude Include="..\..\source\gui\buttons\guiCheckBoxCtrl.h" />
     <ClInclude Include="..\..\source\gui\buttons\guiCheckBoxCtrl.h" />
     <ClInclude Include="..\..\source\gui\buttons\guiRadioCtrl.h" />
     <ClInclude Include="..\..\source\gui\buttons\guiRadioCtrl.h" />
     <ClInclude Include="..\..\source\gui\containers\guiAutoScrollCtrl.h" />
     <ClInclude Include="..\..\source\gui\containers\guiAutoScrollCtrl.h" />
-    <ClInclude Include="..\..\source\gui\containers\guiCtrlArrayCtrl.h" />
     <ClInclude Include="..\..\source\gui\containers\guiDragAndDropCtrl.h" />
     <ClInclude Include="..\..\source\gui\containers\guiDragAndDropCtrl.h" />
-    <ClInclude Include="..\..\source\gui\containers\guiDynamicCtrlArrayCtrl.h" />
     <ClInclude Include="..\..\source\gui\containers\guiFormCtrl.h" />
     <ClInclude Include="..\..\source\gui\containers\guiFormCtrl.h" />
     <ClInclude Include="..\..\source\gui\containers\guiFrameCtrl.h" />
     <ClInclude Include="..\..\source\gui\containers\guiFrameCtrl.h" />
     <ClInclude Include="..\..\source\gui\containers\guiPaneCtrl.h" />
     <ClInclude Include="..\..\source\gui\containers\guiPaneCtrl.h" />

+ 6 - 12
engine/compilers/VisualStudio 2017/Torque 2D.vcxproj.filters

@@ -462,15 +462,9 @@
     <ClCompile Include="..\..\source\gui\containers\guiAutoScrollCtrl.cc">
     <ClCompile Include="..\..\source\gui\containers\guiAutoScrollCtrl.cc">
       <Filter>gui\containers</Filter>
       <Filter>gui\containers</Filter>
     </ClCompile>
     </ClCompile>
-    <ClCompile Include="..\..\source\gui\containers\guiCtrlArrayCtrl.cc">
-      <Filter>gui\containers</Filter>
-    </ClCompile>
     <ClCompile Include="..\..\source\gui\containers\guiDragAndDropCtrl.cc">
     <ClCompile Include="..\..\source\gui\containers\guiDragAndDropCtrl.cc">
       <Filter>gui\containers</Filter>
       <Filter>gui\containers</Filter>
     </ClCompile>
     </ClCompile>
-    <ClCompile Include="..\..\source\gui\containers\guiDynamicCtrlArrayCtrl.cc">
-      <Filter>gui\containers</Filter>
-    </ClCompile>
     <ClCompile Include="..\..\source\gui\containers\guiFormCtrl.cc">
     <ClCompile Include="..\..\source\gui\containers\guiFormCtrl.cc">
       <Filter>gui\containers</Filter>
       <Filter>gui\containers</Filter>
     </ClCompile>
     </ClCompile>
@@ -1698,15 +1692,9 @@
     <ClInclude Include="..\..\source\gui\containers\guiAutoScrollCtrl.h">
     <ClInclude Include="..\..\source\gui\containers\guiAutoScrollCtrl.h">
       <Filter>gui\containers</Filter>
       <Filter>gui\containers</Filter>
     </ClInclude>
     </ClInclude>
-    <ClInclude Include="..\..\source\gui\containers\guiCtrlArrayCtrl.h">
-      <Filter>gui\containers</Filter>
-    </ClInclude>
     <ClInclude Include="..\..\source\gui\containers\guiDragAndDropCtrl.h">
     <ClInclude Include="..\..\source\gui\containers\guiDragAndDropCtrl.h">
       <Filter>gui\containers</Filter>
       <Filter>gui\containers</Filter>
     </ClInclude>
     </ClInclude>
-    <ClInclude Include="..\..\source\gui\containers\guiDynamicCtrlArrayCtrl.h">
-      <Filter>gui\containers</Filter>
-    </ClInclude>
     <ClInclude Include="..\..\source\gui\containers\guiFormCtrl.h">
     <ClInclude Include="..\..\source\gui\containers\guiFormCtrl.h">
       <Filter>gui\containers</Filter>
       <Filter>gui\containers</Filter>
     </ClInclude>
     </ClInclude>
@@ -3154,6 +3142,12 @@
       <Filter>gui\containers</Filter>
       <Filter>gui\containers</Filter>
     </ClInclude>
     </ClInclude>
     <ClInclude Include="resource.h" />
     <ClInclude Include="resource.h" />
+    <ClInclude Include="..\..\source\gui\containers\guiGridCtrl_ScriptBinding.h">
+      <Filter>gui\containers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\source\gui\containers\guiScrollCtrl_ScriptBinding.h">
+      <Filter>gui\containers</Filter>
+    </ClInclude>
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
     <CustomBuild Include="..\..\source\math\mMath_ASM.asm">
     <CustomBuild Include="..\..\source\math\mMath_ASM.asm">

+ 0 - 109
engine/source/gui/containers/guiCtrlArrayCtrl.cc

@@ -1,109 +0,0 @@
-//-----------------------------------------------------------------------------
-// Copyright (c) 2013 GarageGames, LLC
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to
-// deal in the Software without restriction, including without limitation the
-// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
-// sell copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-// IN THE SOFTWARE.
-//-----------------------------------------------------------------------------
-
-#include "gui/containers/guiCtrlArrayCtrl.h"
-
-IMPLEMENT_CONOBJECT(GuiControlArrayControl);
-
-GuiControlArrayControl::GuiControlArrayControl()
-{
-   mCols = 0;
-   mRowSize = 30;
-   mRowSpacing = 2;
-   mColSpacing = 0;
-   mIsContainer = true;
-}
-
-void GuiControlArrayControl::initPersistFields()
-{
-  Parent::initPersistFields();
-
-  addField("colCount",     TypeS32,       Offset(mCols,        GuiControlArrayControl));
-  addField("colSizes",     TypeS32Vector, Offset(mColumnSizes, GuiControlArrayControl));
-  addField("rowSize",      TypeS32,       Offset(mRowSize,     GuiControlArrayControl));
-  addField("rowSpacing",   TypeS32,       Offset(mRowSpacing,  GuiControlArrayControl));
-  addField("colSpacing",   TypeS32,       Offset(mColSpacing,  GuiControlArrayControl));
-}
-
-bool GuiControlArrayControl::onWake()
-{
-   if ( !Parent::onWake() )
-      return false;
-
-   return true;
-}
-
-void GuiControlArrayControl::onSleep()
-{
-   Parent::onSleep();
-}
-
-void GuiControlArrayControl::inspectPostApply()
-{
-   resize(getPosition(), getExtent());
-}
-
-void GuiControlArrayControl::resize(const Point2I &newPosition, const Point2I &newExtent)
-{
-   Parent::resize(newPosition, newExtent);
-
-   if(mCols < 1 || size() < 1)
-      return;
-
-   S32 *sizes = new S32[mCols];
-   S32 *offsets = new S32[mCols];
-   S32 totalSize = 0;
-
-   // Calculate the column sizes
-   for(S32 i=0; i<mCols; i++)
-   {
-      sizes[i] = mColumnSizes[i];
-      offsets[i] = totalSize;
-
-      // If it's an auto-size one, then... auto-size...
-      if(sizes[i] == -1)
-      {
-         sizes[i] = newExtent.x - totalSize;
-         break;
-      }
-
-      totalSize += sizes[i] + mColSpacing;
-   }
-
-   // Now iterate through the children and resize them to fit the grid...
-   for(S32 i=0; i<size(); i++)
-   {
-      GuiControl *gc = dynamic_cast<GuiControl*>(operator[](i));
-
-      // Get the current column and row...
-      S32 curCol = i % mCols;
-      S32 curRow = i / mCols;
-
-      if(gc)
-      {
-         Point2I newPos(offsets[curCol], curRow * (mRowSize + mRowSpacing));
-         Point2I newExtents(sizes[curCol], mRowSize);
-
-         gc->resize(newPos, newExtents);
-      }
-   }
-}

+ 0 - 58
engine/source/gui/containers/guiCtrlArrayCtrl.h

@@ -1,58 +0,0 @@
-//-----------------------------------------------------------------------------
-// Copyright (c) 2013 GarageGames, LLC
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to
-// deal in the Software without restriction, including without limitation the
-// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
-// sell copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-// IN THE SOFTWARE.
-//-----------------------------------------------------------------------------
-
-#ifndef _GUICTRLARRAYCTRL_H_
-#define _GUICTRLARRAYCTRL_H_
-
-#ifndef _GUICONTROL_H_
-#include "gui/guiControl.h"
-#endif
-
-#include "graphics/dgl.h"
-#include "console/console.h"
-#include "console/consoleTypes.h"
-
-class GuiControlArrayControl : public GuiControl
-{
-private:
-   typedef GuiControl Parent;
-
-   S32 mCols;
-   Vector<S32> mColumnSizes;
-   S32 mRowSize;
-   S32 mRowSpacing;
-   S32 mColSpacing;
-
-public:
-   GuiControlArrayControl();
-
-   void resize(const Point2I &newPosition, const Point2I &newExtent);
-
-   bool onWake();
-   void onSleep();
-   void inspectPostApply();
-
-   static void initPersistFields();
-   DECLARE_CONOBJECT(GuiControlArrayControl);
-};
-
-#endif

+ 0 - 157
engine/source/gui/containers/guiDynamicCtrlArrayCtrl.cc

@@ -1,157 +0,0 @@
-//-----------------------------------------------------------------------------
-// Copyright (c) 2013 GarageGames, LLC
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to
-// deal in the Software without restriction, including without limitation the
-// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
-// sell copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-// IN THE SOFTWARE.
-//-----------------------------------------------------------------------------
-
-#include "gui/containers/guiDynamicCtrlArrayCtrl.h"
-
-ConsoleMethod(GuiDynamicCtrlArrayControl, refresh, void, 2, 2, "() Forces the child controls to recalculate")
-{
-   object->updateChildControls();
-}
-
-IMPLEMENT_CONOBJECT(GuiDynamicCtrlArrayControl);
-
-GuiDynamicCtrlArrayControl::GuiDynamicCtrlArrayControl()
-{
-   mCols = 0;
-   mColSize = 64;
-   mRowSize = 64;
-   mRowSpacing = 0;
-   mColSpacing = 0;
-   mIsContainer = true;
-
-   mResizing = false;
-}
-
-GuiDynamicCtrlArrayControl::~GuiDynamicCtrlArrayControl()
-{
-}
-
-void GuiDynamicCtrlArrayControl::initPersistFields()
-{
-  Parent::initPersistFields();
-
-  addField("colCount",     TypeS32,       Offset(mCols,        GuiDynamicCtrlArrayControl));
-  addField("colSize",      TypeS32,       Offset(mColSize,     GuiDynamicCtrlArrayControl));
-  addField("rowSize",      TypeS32,       Offset(mRowSize,     GuiDynamicCtrlArrayControl));
-  addField("rowSpacing",   TypeS32,       Offset(mRowSpacing,  GuiDynamicCtrlArrayControl));
-  addField("colSpacing",   TypeS32,       Offset(mColSpacing,  GuiDynamicCtrlArrayControl));
-}
-
-void GuiDynamicCtrlArrayControl::inspectPostApply()
-{
-   resize(getPosition(), getExtent());
-   Parent::inspectPostApply();
-}
-
-void GuiDynamicCtrlArrayControl::updateChildControls()
-{
-   // Prevent recursion
-   if(mResizing) return;
-
-   mResizing = true;
-
-   // Store the sum of the heights of our controls.
-
-   Point2I curPos = getPosition();
-
-   // Calculate the number of columns
-   mCols = ( getExtent().x / (mColSize));// + mColSpacing) ) - mColSpacing;
-   if(mCols < 1)
-      mCols = 1;
-
-   // Place each child...
-   S32 childcount = 0;
-   S32 rows = 0;
-   for(S32 i=0; i<size(); i++)
-   {
-      // Place control
-      GuiControl * gc = dynamic_cast<GuiControl*>(operator [](i));
-
-      if(gc && gc->isVisible()) // DAW: Added check if child is visible.  Invisible children don't take part
-      {
-         // Get the current column and row...
-         S32 curCol = childcount % mCols;
-         S32 curRow = childcount / mCols;
-
-         rows = getMax( rows, curRow );
-
-         // Reposition and resize
-         Point2I newPos(mColSpacing + (curCol * (mColSize + mColSpacing)), mRowSpacing + (curRow * (mRowSize + mRowSpacing)));
-         gc->resize(newPos, Point2I(mColSize, mRowSize));
-
-         childcount++;
-      }
-   }
-
-   rows++;
-
-   // Conform our size to the sum of the child sizes.
-   curPos.x = getExtent().x;
-   curPos.y = mRowSpacing + (rows * (mRowSize + mRowSpacing));
-   mBounds.extent.y = curPos.y;
-
-   mResizing = false;
-}
-
-void GuiDynamicCtrlArrayControl::resize(const Point2I &newPosition, const Point2I &newExtent)
-{
-
-   // If we don't have any children, return.
-   if(size() < 1)
-   {
-      Parent::resize(newPosition, newExtent);
-      return;
-   }
-
-   // What we need to do is figure out how many children will fit on a row
-   // given this control's new extent.  This gives us the number of columns.
-   // Then the number of rows will expand or contract, essentially changing
-   // the 'y' extent of this control.
-
-   //call set update both before and after
-   setUpdate();
-   Point2I actualNewExtent = Point2I(getMax(mMinExtent.x, newExtent.x),
-                                     getMax(mMinExtent.y, newExtent.y));
-
-   mBounds.set(newPosition, actualNewExtent);
-
-   GuiControl *parent = getParent();
-   if (parent)
-      parent->childResized(this);
-   setUpdate();
-
-   updateChildControls();
-}
-
-void GuiDynamicCtrlArrayControl::addObject(SimObject *obj)
-{
-   Parent::addObject(obj);
-
-   updateChildControls();
-}
-
-void GuiDynamicCtrlArrayControl::childResized(GuiControl *child)
-{
-   Parent::childResized(child);
-
-   updateChildControls();
-}

+ 0 - 63
engine/source/gui/containers/guiDynamicCtrlArrayCtrl.h

@@ -1,63 +0,0 @@
-//-----------------------------------------------------------------------------
-// Copyright (c) 2013 GarageGames, LLC
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to
-// deal in the Software without restriction, including without limitation the
-// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
-// sell copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-// IN THE SOFTWARE.
-//-----------------------------------------------------------------------------
-
-#ifndef _GUIDYNAMICCTRLARRAYCTRL_H_
-#define _GUIDYNAMICCTRLARRAYCTRL_H_
-
-#ifndef _GUICONTROL_H_
-#include "gui/guiControl.h"
-#endif
-
-#include "graphics/dgl.h"
-#include "console/console.h"
-#include "console/consoleTypes.h"
-
-class GuiDynamicCtrlArrayControl : public GuiControl
-{
-private:
-   typedef GuiControl Parent;
-
-   S32 mCols;
-   S32 mRowSize;
-   S32 mColSize;
-   S32 mRowSpacing;
-   S32 mColSpacing;
-   bool mResizing;
-
-public:
-   GuiDynamicCtrlArrayControl();
-   virtual ~GuiDynamicCtrlArrayControl();
-
-   void updateChildControls();
-   void resize(const Point2I &newPosition, const Point2I &newExtent);
-
-   void addObject(SimObject *obj);
-
-   void childResized(GuiControl *child);
-
-   void inspectPostApply();
-
-   static void initPersistFields();
-   DECLARE_CONOBJECT(GuiDynamicCtrlArrayControl);
-};
-
-#endif // _GUIDYNAMICCTRLARRAYCTRL_H_

+ 267 - 225
engine/source/gui/containers/guiGridCtrl.cc

@@ -20,32 +20,76 @@
 // IN THE SOFTWARE.
 // IN THE SOFTWARE.
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
+#include "console/consoleTypes.h"
+#include "console/console.h"
 #include "gui/containers/guiGridCtrl.h"
 #include "gui/containers/guiGridCtrl.h"
 
 
+#include "guiGridCtrl_ScriptBinding.h"
+
+static EnumTable::Enums cellModeEnums[] = 
+{
+	{ GuiGridCtrl::Absolute, "absolute" },
+	{ GuiGridCtrl::Variable, "variable" },
+	{ GuiGridCtrl::Percent, "percent" }
+};
+static EnumTable gCellModeTable(3, &cellModeEnums[0]);
+
+
+static EnumTable::Enums orderModeEnums[] =
+{
+	{ GuiGridCtrl::LRTB, "lrtb" },
+	{ GuiGridCtrl::RLTB, "rltb" },
+	{ GuiGridCtrl::TBLR, "tblr" },
+	{ GuiGridCtrl::TBRL, "tbrl" },
+	{ GuiGridCtrl::LRBT, "lrbt" },
+	{ GuiGridCtrl::RLBT, "rlbt" },
+	{ GuiGridCtrl::BTLR, "btlr" },
+	{ GuiGridCtrl::BTRL, "btrl" }
+};
+static EnumTable gOrderModeTable(8, &orderModeEnums[0]);
+
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 
 
-IMPLEMENT_CONOBJECT(GuiGridControl);
+IMPLEMENT_CONOBJECT(GuiGridCtrl);
 
 
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 
 
-GuiGridControl::GuiGridControl()
+GuiGridCtrl::GuiGridCtrl()
 {
 {
 	mIsContainer = true;
 	mIsContainer = true;
+	mCellModeX = CellMode::Absolute;
+	mCellModeY = CellMode::Absolute;
+	mCellSizeX = 20;
+	mCellSizeY = 20;
+	mCellSpacingX = 0;
+	mCellSpacingY = 0;
+	mMaxColCount = 0;
+	mMaxRowCount = 0;
+	mOrderMode = OrderMode::LRTB;
+	mIsExtentDynamic = true;
 }
 }
 
 
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 
 
-void GuiGridControl::initPersistFields()
+void GuiGridCtrl::initPersistFields()
 {
 {
 	Parent::initPersistFields();
 	Parent::initPersistFields();
 
 
-	addField("Rows",		TypeStringTableEntryVector, Offset(mGridRows, GuiGridControl), "Number of rows in the grid");
-	addField("Columns",     TypeStringTableEntryVector, Offset(mGridCols, GuiGridControl), "Number of columns in the grid");
+	addField("CellModeX", TypeEnum, Offset(mCellModeX, GuiGridCtrl), 1, &gCellModeTable);
+	addField("CellModeY", TypeEnum, Offset(mCellModeY, GuiGridCtrl), 1, &gCellModeTable);
+	addField("CellSizeX", TypeF32, Offset(mCellSizeX, GuiGridCtrl));
+	addField("CellSizeY", TypeF32, Offset(mCellSizeY, GuiGridCtrl));
+	addField("CellSpacingX", TypeF32, Offset(mCellSpacingX, GuiGridCtrl));
+	addField("CellSpacingY", TypeF32, Offset(mCellSpacingY, GuiGridCtrl));
+	addField("MaxColCount", TypeS32, Offset(mMaxColCount, GuiGridCtrl));
+	addField("MaxRowCount", TypeS32, Offset(mMaxRowCount, GuiGridCtrl));
+	addField("OrderMode", TypeEnum, Offset(mOrderMode, GuiGridCtrl), 1, &gOrderModeTable);
+	addField("IsExtentDynamic", TypeBool, Offset(mIsExtentDynamic, GuiGridCtrl));
 }
 }
 
 
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 
 
-bool GuiGridControl::onWake()
+bool GuiGridCtrl::onWake()
 {
 {
 	if (!Parent::onWake())
 	if (!Parent::onWake())
         return false;
         return false;
@@ -55,299 +99,297 @@ bool GuiGridControl::onWake()
 
 
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 
 
-void GuiGridControl::onSleep()
+void GuiGridCtrl::onSleep()
 {
 {
 	Parent::onSleep();
 	Parent::onSleep();
 }
 }
 
 
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 
 
-void GuiGridControl::inspectPostApply()
+void GuiGridCtrl::inspectPostApply()
 {
 {
     resize(getPosition(), getExtent());
     resize(getPosition(), getExtent());
+	Parent::inspectPostApply();
 }
 }
 
 
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 
 
-bool GuiGridControl::IsPointInGridControl(GuiControl* ctrl, const Point2I& pt)
+void GuiGridCtrl::resize(const Point2I &newPosition, const Point2I &newExtent)
 {
 {
-	if (mRowSizes.size() > 0 && mColSizes.size() > 0)
-	{
-		RectI gridRect = GetGridRect(ctrl);
-		RectI ctrlRect = ctrl->getBounds();
+	Point2I actualNewExtent = Point2I(getMax(mMinExtent.x, newExtent.x),
+		getMax(mMinExtent.y, newExtent.y));
 
 
-		Point2I chkPt = gridRect.point + ctrlRect.point;
-		Point2I chkBound = chkPt + ctrlRect.extent;
+	//call set update both before and after
+	setUpdate();
 
 
-		if (pt.x >= chkPt.x && pt.x <= chkBound.x && pt.y >= chkPt.y && pt.y <= chkBound.y)
-			return true;
-		else
-			return false;
+	RectI innerRect = getInnerRect(mBounds.point.Zero, actualNewExtent, NormalState, mProfile);
+	if (!innerRect.isValidRect() && !mIsExtentDynamic)
+	{
+		return;
 	}
 	}
-	else
-    {
-		return false;
-    }
-
-}
-
-//------------------------------------------------------------------------------
+		
+	AdjustGrid(innerRect.extent);
 
 
-void GuiGridControl::addObject(SimObject *obj)
-{
-	if (mRowSizes.size() <= 0 && mRowSizes.size() <= 0)
-		AdjustGrid(mBounds.extent);
+	iterator i;
+	U16 num = 0;
+	for (i = begin(); i != end(); i++, num++)
+	{
+		GuiControl *ctrl = static_cast<GuiControl *>(*i);
+		ctrl->resize(getCellPosition(num, innerRect.extent), mCalcCellExt);
+	}
 
 
-	GuiControl *ctrl = static_cast<GuiControl *>(obj);
-	
-    if (ctrl)
+	Point2I actualNewPosition = Point2I(newPosition);
+	if(mIsExtentDynamic)
 	{
 	{
-		RectI ctrlRect = GetGridRect(ctrl);
-		if (ctrl->getExtent().isZero())
+		F32 h = mCeil((F32)size() / (F32)mCalcChainLength);
+		if (mOrderMode == LRTB || mOrderMode == RLTB)
 		{
 		{
-			ctrl->setExtent(ctrlRect.extent);
+			h = (h * mCalcCellExt.y) + ((h-1) * mCalcCellSpace.y);
+			innerRect.extent.y = h;
 		}
 		}
-		else
+		else if (mOrderMode == TBLR || mOrderMode == BTLR)
 		{
 		{
-			if (ctrl->mBounds.extent.x > ctrlRect.extent.x)
-				ctrl->mBounds.extent.x = ctrlRect.extent.x;
-			if (ctrl->mBounds.extent.y > ctrlRect.extent.y)
-				ctrl->mBounds.extent.y = ctrlRect.extent.y;
+			h = (h * mCalcCellExt.x) + ((h - 1) * mCalcCellSpace.x);
+			innerRect.extent.x = h;
 		}
 		}
-
-		Point2I pt = ctrl->getPosition();
-		mOrginalControlPos.push_back(pt);
-		pt += ctrlRect.point;
-		ctrl->setPosition(pt);
-	}
-
-	Parent::addObject(obj);
-}
-
-//------------------------------------------------------------------------------
-
-void GuiGridControl::removeObject(SimObject *obj)
-{
-	for(int idx =0; idx < objectList.size();idx++)
-	{
-		if ( objectList[idx] == obj )
+		else if (mOrderMode == LRBT || mOrderMode == RLBT)
+		{
+			h = (h * mCalcCellExt.y) + ((h - 1) * mCalcCellSpace.y);
+			actualNewPosition.y += innerRect.extent.y - h;
+			innerRect.extent.y = h;
+		}
+		else if (mOrderMode == TBRL || mOrderMode == BTRL)
 		{
 		{
-			mOrginalControlPos.erase(idx);
-			break;
+			h = (h * mCalcCellExt.x) + ((h - 1) * mCalcCellSpace.x);
+			actualNewPosition.x += innerRect.extent.x - h;
+			innerRect.extent.x = h;
 		}
 		}
+		actualNewExtent = getOuterExtent(innerRect.extent, NormalState, mProfile);
 	}
 	}
 
 
-	Parent::removeObject(obj);
+	mBounds.set(actualNewPosition, actualNewExtent);
+
+	GuiControl *parent = getParent();
+	if (parent)
+		parent->childResized(this);
+	setUpdate();
 }
 }
 
 
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 
 
-void GuiGridControl::resize(const Point2I &newPosition, const Point2I &newExtent)
+Point2I GuiGridCtrl::getCellPosition(const U16 num, const Point2I &innerExtent)
 {
 {
-	setUpdate();
-
-	Point2I actualNewExtent = Point2I(  getMax(mMinExtent.x, newExtent.x), getMax(mMinExtent.y, newExtent.y));
-	mBounds.set(newPosition, actualNewExtent);
+	Point2I result(0,0);
+	U16 y = (U16)mFloor(num / mCalcChainLength);
+	U16 x = (U16)(num % mCalcChainLength);
+	F32 ChainCount = mCeil((F32)size() / (F32)mCalcChainLength);
 
 
-	bool bFirstResize = false;
-	iterator i;
-	Vector<Point2I> oldCtrlExtent;
-	
-	if (mRowSizes.size() == 0 && mColSizes.size() == 0)
+	if (mOrderMode == LRTB)
 	{
 	{
-		bFirstResize = true;
+		result.set(x * (mCalcCellExt.x + mCalcCellSpace.x), y * (mCalcCellExt.y + mCalcCellSpace.y));
 	}
 	}
-	else
+	else if (mOrderMode == RLTB)
 	{
 	{
-		for(i = begin(); i != end(); i++)
-		{
-			GuiControl *ctrl = static_cast<GuiControl *>(*i);
-			if (ctrl)
-			{
-				RectI newRect = GetGridRect(ctrl);		
-				oldCtrlExtent.push_back(newRect.extent);
-			}
-		}
-
+		x = (mCalcChainLength - 1) - x;
+		S32 delta = innerExtent.x - ((mCalcChainLength * mCalcCellExt.x) + ((mCalcChainLength - 1) * mCalcCellSpace.x));
+		result.set((x * (mCalcCellExt.x + mCalcCellSpace.x)) + delta, y * (mCalcCellExt.y + mCalcCellSpace.y));
 	}
 	}
-
-	AdjustGrid(mBounds.extent);
-
-	//resize and position all child controls.
-	int idx = 0;
-	for(i = begin(); i != end(); i++)
+	else if (mOrderMode == TBLR)
 	{
 	{
-		GuiControl *ctrl = static_cast<GuiControl *>(*i);
-		if (ctrl)
-		{
-			RectI newRect = GetGridRect(ctrl);		
-			
-			if (ctrl->getExtent().x == 0 && ctrl->getExtent().y == 0)
-				ctrl->setExtent(newRect.extent);
-
-			ctrl->setPosition(mOrginalControlPos[idx] + newRect.point);
-
-			if (bFirstResize)
-			{
-				ctrl->parentResized(newRect.extent, newRect.extent);
-			}
-			else
-			{
-				ctrl->parentResized(oldCtrlExtent[idx++], newRect.extent);
-			}
-		}
+		result.set(y * (mCalcCellExt.x + mCalcCellSpace.x), x * (mCalcCellExt.y + mCalcCellSpace.y));
+	}
+	else if (mOrderMode == BTLR)
+	{
+		x = (mCalcChainLength - 1) - x;
+		S32 delta = innerExtent.y - ((mCalcChainLength * mCalcCellExt.y) + ((mCalcChainLength - 1) * mCalcCellSpace.y));
+		result.set(y * (mCalcCellExt.x + mCalcCellSpace.x), (x * (mCalcCellExt.y + mCalcCellSpace.y)) + delta);
+	}
+	else if (mOrderMode == LRBT)
+	{
+		y = (ChainCount - 1) - y;
+		result.set(x * (mCalcCellExt.x + mCalcCellSpace.x), y * (mCalcCellExt.y + mCalcCellSpace.y));
+	}
+	else if (mOrderMode == RLBT)
+	{
+		y = (ChainCount - 1) - y;
+		x = (mCalcChainLength - 1) - x;
+		S32 delta = innerExtent.x - ((mCalcChainLength * mCalcCellExt.x) + ((mCalcChainLength - 1) * mCalcCellSpace.x));
+		result.set((x * (mCalcCellExt.x + mCalcCellSpace.x)) + delta, y * (mCalcCellExt.y + mCalcCellSpace.y));
+	}
+	else if (mOrderMode == TBRL)
+	{
+		y = (ChainCount - 1) - y;
+		result.set(y * (mCalcCellExt.x + mCalcCellSpace.x), x * (mCalcCellExt.y + mCalcCellSpace.y));
+	}
+	else if (mOrderMode == BTRL)
+	{
+		y = (ChainCount - 1) - y;
+		x = (mCalcChainLength - 1) - x;
+		S32 delta = innerExtent.y - ((mCalcChainLength * mCalcCellExt.y) + ((mCalcChainLength - 1) * mCalcCellSpace.y));
+		result.set(y * (mCalcCellExt.x + mCalcCellSpace.x), (x * (mCalcCellExt.y + mCalcCellSpace.y)) + delta);
 	}
 	}
 
 
-	GuiControl *parent = getParent();
-
-	if (parent)
-		parent->childResized(this);
-
-	setUpdate();
+	return result;
 }
 }
 
 
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 
 
-RectI GuiGridControl::GetGridRect(GuiControl* ctrl)
+void GuiGridCtrl::AdjustGrid(const Point2I& innerExtent)
 {
 {
-	S32 col = dAtoi(ctrl->getDataField( StringTable->insert("Col"), NULL));
-	S32 row = dAtoi(ctrl->getDataField( StringTable->insert("Row"), NULL));
-	S32 colSpan = dAtoi(ctrl->getDataField( StringTable->insert("ColSpan"), NULL));
-	S32 rowSpan = dAtoi(ctrl->getDataField( StringTable->insert("RowSpan"), NULL));
-
-	AssertFatal (col < mColSizes.size(), "Col is out of bounds");
-	AssertFatal (row < mRowSizes.size(), "Row is out of bounds");
-
-	if (colSpan < 1)
-        colSpan = 1;
-
-	if (rowSpan < 1)
-        rowSpan = 1;
+	Point2F cellExtX, cellExtY;
+	if (mOrderMode == LRTB || mOrderMode == LRBT || mOrderMode == RLTB || mOrderMode == RLBT)
+	{
+		cellExtX = GetGridItemWidth(innerExtent.x, mMaxColCount, mCellSizeX, mCellSpacingX, mCellModeX);
+		cellExtY = GetGridItemHeight(innerExtent.y, mMaxRowCount, mCellSizeY, mCellSpacingY, mCellModeY);
+	}
+	else
+	{
+		cellExtY = GetGridItemWidth(innerExtent.y, mMaxRowCount, mCellSizeY, mCellSpacingY, mCellModeY);
+		cellExtX = GetGridItemHeight(innerExtent.x, mMaxColCount, mCellSizeX, mCellSpacingX, mCellModeX);
+	}
+	mCalcCellExt.set(cellExtX.x, cellExtY.x);
+	mCalcCellSpace.set(cellExtX.y, cellExtY.y);
+}
 
 
-	RectI newRect(0,0,0,0);
+Point2F GuiGridCtrl::GetGridItemWidth(const S32 totalArea, const S32 maxChainLength, const F32 itemSize, const F32 spaceSize, const CellMode cellMode)
+{
+	//The two values returned are the extent and spacing held in the x and y respectively
+	if (cellMode == GuiGridCtrl::Percent)
+	{
+		mCalcChainLength = (U16)getMax((100 + spaceSize) / (itemSize + spaceSize), 1.f);
+	}
+	else
+	{
+		mCalcChainLength = (U16)getMax((totalArea + spaceSize) / (itemSize + spaceSize), 1.f);
+	}
 
 
-	for(int i = 0; i < col; i++)
+	if (maxChainLength > 0)
 	{
 	{
-		newRect.point.x += mColSizes[i];
+		mCalcChainLength = (U16)getMin((S32)mCalcChainLength, maxChainLength);
 	}
 	}
 
 
-	for(int i =col; i < col+colSpan; i++)
+	if (cellMode == GuiGridCtrl::Absolute)
 	{
 	{
-		newRect.extent.x += mColSizes[i];
+		return Point2F(mFloor(itemSize), mFloor(spaceSize));
 	}
 	}
-	
-	for(int i = 0; i < row; i++)
+	else if (cellMode == GuiGridCtrl::Variable)
 	{
 	{
-		newRect.point.y += mRowSizes[i];
+		F32 remainder = totalArea - ((mCalcChainLength * itemSize) + ((mCalcChainLength - 1) * spaceSize));
+		return Point2F(mFloor(itemSize + (remainder / mCalcChainLength)), mFloor(spaceSize));
 	}
 	}
+	else if (cellMode == GuiGridCtrl::Percent)
+	{
+		F32 calcCellSize = mFloor(getMin((F32)(totalArea * (itemSize / 100)), (F32)(totalArea)));
+		F32 calcSpaceSize = mFloor(getMin((F32)(totalArea * (spaceSize / 100)), (F32)(totalArea)));
+		return Point2F(calcCellSize, calcSpaceSize);
+	}
+	return Point2F(1,1);
+}
 
 
-	for(int i =row; i < row+rowSpan; i++)
+Point2F GuiGridCtrl::GetGridItemHeight(const S32 totalArea, const S32 maxChainLength, const F32 itemSize, const F32 spaceSize, const CellMode cellMode)
+{
+	if (mIsExtentDynamic || cellMode == CellMode::Absolute)
+	{
+		return Point2F(mFloor(itemSize), mFloor(spaceSize));
+	}
+	else if (cellMode == CellMode::Variable)
+	{
+		U16 length = (U16)mClamp((totalArea + spaceSize) / (itemSize + spaceSize), 1, maxChainLength);
+		F32 remainder = totalArea - ((length * itemSize) + ((length - 1) * spaceSize));
+		return Point2F(mFloor(itemSize + (remainder / mCalcChainLength)), mFloor(spaceSize));
+	}
+	else if (cellMode == CellMode::Percent)
 	{
 	{
-		newRect.extent.y += mRowSizes[i];
+		F32 calcCellSize = mFloor(getMin((F32)(totalArea * (itemSize / 100)), (F32)(totalArea)));
+		F32 calcSpaceSize = mFloor(getMin((F32)(totalArea * (spaceSize / 100)), (F32)(totalArea)));
+		return Point2F(calcCellSize, calcSpaceSize);
 	}
 	}
+	return Point2F(1, 1);
+}
 
 
-	return newRect;
+void GuiGridCtrl::onChildAdded(GuiControl *child)
+{
+	resize(getPosition(), getExtent());
 }
 }
 
 
-//------------------------------------------------------------------------------
+void GuiGridCtrl::onChildRemoved(SimObject *child)
+{
+	resize(getPosition(), getExtent());
+}
 
 
-void GuiGridControl::AdjustGrid(const Point2I& newExtent)
+void GuiGridCtrl::setCellSize(F32 width, F32 height)
 {
 {
-	mColSizes.clear();
-	mRowSizes.clear();
-	AdjustGridItems(newExtent.x, mGridCols, mColSizes);
-	AdjustGridItems(newExtent.y, mGridRows, mRowSizes);
+	mCellSizeX = mAbs(width);
+	mCellSizeY = mAbs(height);
+	resize(getPosition(), getExtent());
 }
 }
 
 
-//------------------------------------------------------------------------------
+void GuiGridCtrl::setCellSpacing(F32 x, F32 y)
+{
+	mCellSpacingX = mAbs(x);
+	mCellSpacingY = mAbs(y);
+	resize(getPosition(), getExtent());
+}
 
 
-void GuiGridControl::AdjustGridItems(S32 size, Vector<StringTableEntry>& strItems, Vector<S32>& items)
+void GuiGridCtrl::setCellModeX(const CellMode mode)
 {
 {
-	Vector<GridItem> GridItems;
-    S32 bFoundStar;
-	bFoundStar = false;
-	S32 IndexRemaining = -1;
-	S32 totalSize = 0;
-	S32 idx =0;
-
-	//First step : Convert the string based column data into a GridItem vector.
-	for(Vector<char const*>::iterator col = strItems.begin(); col != strItems.end(); ++col, idx++)
-	{
-		StringTableEntry str = *col;
+	// Sanity!
+	AssertFatal(mode == Percent || mode == Variable || mode == Absolute, "Invalid cell mode.");
 
 
-		int len = dStrlen(str);
-		AssertFatal(len >= 1, "Item can not be blank.");
-		
-		//we support three types of values (absolute size in pixels, percentage based, and remaining size in pixels).
-		if (str[0] == '*') // use the remaining space left in the columns.
-		{
-			AssertFatal(!bFoundStar, "Can only use one * item field");
-			GridItem gi;
-			gi.IsAbsolute = false;
-			gi.IsPercentage = false;
-			gi.IsRemaining = true;
-			gi.Size = 0;
-			GridItems.push_back(gi);
-		}
-		else if ( len > 1 && str[len-1] == '%' ) //percentage based
-		{
-			char* tmp = new char[len-1];
-			dStrncpy(tmp, str, len-1);
-			int perc = dAtoi(tmp);
-			delete[] tmp;
-
-			GridItem gi;
-			gi.IsAbsolute = false;
-			gi.IsPercentage = true;
-			gi.IsRemaining = false;
-			gi.Size = perc;
-			GridItems.push_back(gi);
+	mCellModeX = mode;
+	resize(getPosition(), getExtent());
+}
 
 
-		}
-		else //standard absolute pixel based
-		{
-			int px = dAtoi(str);
+void GuiGridCtrl::setCellModeY(const CellMode mode)
+{
+	// Sanity!
+	AssertFatal(mode == Percent || mode == Variable || mode == Absolute, "Invalid cell mode.");
 
 
-			GridItem gi;
-			gi.IsAbsolute = true;
-			gi.IsPercentage = false;
-			gi.IsRemaining = false;
-			gi.Size = px;
-			GridItems.push_back(gi);
+	mCellModeY = mode;
+	resize(getPosition(), getExtent());
+}
 
 
-			totalSize += px;
-		}
+GuiGridCtrl::CellMode GuiGridCtrl::getCellModeEnum(const char* label)
+{
+	// Search for Mnemonic.
+	for (U32 i = 0; i < (sizeof(cellModeEnums) / sizeof(EnumTable::Enums)); i++)
+	{
+		if (dStricmp(cellModeEnums[i].label, label) == 0)
+			return (CellMode)cellModeEnums[i].index;
 	}
 	}
 
 
-    //step two: iterate the grid columns again, and fill in any percentage based sizing, and setup the correct grid array.
-	int remainingSize = size - totalSize;
-	int sizeForPerc = remainingSize;
-	for(int i = 0; i < GridItems.size(); ++i)
-	{
-		GridItem gi = GridItems[i];
+	// Warn.
+	Con::warnf("GuiGridCtrl::getCellModeEnum() - Invalid cell mode of '%s'", label);
 
 
-		if (gi.IsAbsolute)
-		{
-			items.push_back(gi.Size);
-		}
-		else if (gi.IsPercentage)
-		{
-			F32 perc = gi.Size / 100.0f;
-			S32 realSize = sizeForPerc * (S32)perc;
-			remainingSize -= realSize;
-			items.push_back(realSize);
-		}
-		else if(gi.IsRemaining)
-		{
-			//place holder for the moment.
-			items.push_back(0);
-			IndexRemaining = i;
-		}			
-	}
+	return (CellMode)-1;
+}
 
 
-	if (IndexRemaining >= 0)
+const char* GuiGridCtrl::getCellModeDescription(const GuiGridCtrl::CellMode mode)
+{
+	// Search for Mnemonic.
+	for (U32 i = 0; i < (sizeof(cellModeEnums) / sizeof(EnumTable::Enums)); i++)
 	{
 	{
-		items[IndexRemaining] = remainingSize;
-		remainingSize = 0;
+		if (cellModeEnums[i].index == mode)
+			return cellModeEnums[i].label;
 	}
 	}
+
+	// Warn.
+	Con::warnf("GuiGridCtrl::getCellModeDescription() - Invalid cell mode.");
+
+	return StringTable->EmptyString;
 }
 }
+
+const char* GuiGridCtrl::getOrderModeDescription(const GuiGridCtrl::OrderMode mode)
+{
+	// Search for Mnemonic.
+	for (U32 i = 0; i < (sizeof(orderModeEnums) / sizeof(EnumTable::Enums)); i++)
+	{
+		if (orderModeEnums[i].index == mode)
+			return orderModeEnums[i].label;
+	}
+
+	// Warn.
+	Con::warnf("GuiGridCtrl::getOrderModeDescription() - Invalid order mode.");
+
+	return StringTable->EmptyString;
+}

+ 61 - 25
engine/source/gui/containers/guiGridCtrl.h

@@ -5,51 +5,87 @@
 #include "gui/guiControl.h"
 #include "gui/guiControl.h"
 #endif
 #endif
 
 
+#ifndef _VECTOR2_H_
+#include "2d/core/Vector2.h"
+#endif
+
 #include "graphics/dgl.h"
 #include "graphics/dgl.h"
 #include "console/console.h"
 #include "console/console.h"
 #include "console/consoleTypes.h"
 #include "console/consoleTypes.h"
 
 
-class GuiGridControl : public GuiControl
+class GuiGridCtrl : public GuiControl
 {
 {
 private:
 private:
+	typedef GuiControl Parent;
+	Point2I mCalcCellExt;
+	Point2I mCalcCellSpace;
+	U16 mCalcChainLength;
 
 
-    struct GridItem
+public:
+	enum CellMode
 	{
 	{
-		int Size;
-		bool IsPercentage;
-		bool IsRemaining;
-		bool IsAbsolute;
+		Absolute,
+		Variable,
+		Percent
 	};
 	};
+	CellMode mCellModeX, mCellModeY;
+	F32 mCellSizeX, mCellSizeY;
+	F32 mCellSpacingX, mCellSpacingY;
+	S32 mMaxColCount, mMaxRowCount;
 
 
-private:
-	typedef GuiControl Parent;
-
-	Vector<StringTableEntry> mGridRows;
-	Vector<StringTableEntry> mGridCols;
-
-	Vector<S32> mRowSizes;
-	Vector<S32> mColSizes;
-	Vector<Point2I> mOrginalControlPos;
-
-	void AdjustGrid(const Point2I& newExtent);
-	void AdjustGridItems(S32 size, Vector<StringTableEntry>& strItems, Vector<S32>& items);
-	RectI GetGridRect(GuiControl* ctrl);
-	bool IsPointInGridControl(GuiControl* ctrl, const Point2I& pt);
+	//LRTB means Left to Right, Top to Bottom (the normal way we read english)
+	enum OrderMode
+	{
+		LRTB,
+		RLTB,
+		TBLR,
+		TBRL,
+		LRBT,
+		RLBT,
+		BTLR,
+		BTRL
+	};
+	OrderMode mOrderMode;
+	bool mIsExtentDynamic;
 
 
+private:
+	void AdjustGrid(const Point2I& innerExtent);
+	Point2F GetGridItemWidth(const S32 totalArea, const S32 maxChainLength, const F32 itemSize, const F32 spaceSize, const CellMode cellMode);
+	Point2F GetGridItemHeight(const S32 totalArea, const S32 maxChainLength, const F32 itemSize, const F32 spaceSize, const CellMode cellMode);
+	Point2I getCellPosition(U16 num, const Point2I &innerExtent);
 
 
 public:
 public:
-	GuiGridControl();
+	GuiGridCtrl();
 
 
 	void resize(const Point2I &newPosition, const Point2I &newExtent);
 	void resize(const Point2I &newPosition, const Point2I &newExtent);
+	//void childResized(GuiControl *child);
 	void inspectPostApply();
 	void inspectPostApply();
-
-	void addObject(SimObject *obj);
-	void removeObject(SimObject *obj);
 	bool onWake();
 	bool onWake();
 	void onSleep();
 	void onSleep();
+	void onChildAdded(GuiControl *child);
+	void onChildRemoved(SimObject *child);
+
+	void setCellSize(F32 width, F32 height);
+	inline Vector2 getCellSize(void) const { return Vector2(mCellSizeX, mCellSizeY); }
+	void setCellSpacing(F32 x, F32 y);
+	inline Vector2 getCellSpacing(void) const { return Vector2(mCellSpacingX, mCellSpacingY); }
+
+	void setCellModeX(const CellMode mode);
+	void setCellModeY(const CellMode mode);
+	inline CellMode getCellModeX(void) const { return mCellModeX; }
+	inline CellMode getCellModeY(void) const { return mCellModeY; }
+	static CellMode getCellModeEnum(const char* label);
+	static const char* getCellModeDescription(const CellMode mode);
+	inline void setMaxColCount(S32 max) { mMaxColCount = max; resize(getPosition(), getExtent()); }
+	inline void setMaxRowCount(S32 max) { mMaxRowCount = max; resize(getPosition(), getExtent()); }
+	inline S32 getMaxColCount(void) const { return mMaxColCount; }
+	inline S32 getMaxRowCount(void) const { return mMaxRowCount; }
+	inline OrderMode getOrderMode(void) const { return mOrderMode; }
+	static const char* getOrderModeDescription(const OrderMode mode);
+	inline bool getIsExtentDynamic(void) { return mIsExtentDynamic; }
 
 
 	static void initPersistFields();
 	static void initPersistFields();
-	DECLARE_CONOBJECT(GuiGridControl);
+	DECLARE_CONOBJECT(GuiGridCtrl);
 };
 };
 
 
 #endif // _GUIGRIDCTRL_H_
 #endif // _GUIGRIDCTRL_H_

+ 220 - 0
engine/source/gui/containers/guiGridCtrl_ScriptBinding.h

@@ -0,0 +1,220 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2013 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+ConsoleMethodGroupBeginWithDocs(GuiGridCtrl, GuiControl)
+
+/*! Sets the size assigned to each child control.
+	@param width The width of the child.
+	@param height The height of the child.
+	@return No return value.
+*/
+ConsoleMethodWithDocs(GuiGridCtrl, setCellSize, ConsoleVoid, 3, 4, (float width, float height))
+{
+	F32 width, height;
+
+	const U32 elementCount = Utility::mGetStringElementCount(argv[2]);
+
+	// ("width height")
+	if ((elementCount == 2) && (argc == 3))
+	{
+		width = dAtof(Utility::mGetStringElement(argv[2], 0));
+		height = dAtof(Utility::mGetStringElement(argv[2], 1));
+	}
+
+	// (width, [height])
+	else if (elementCount == 1)
+	{
+		width = dAtof(argv[2]);
+
+		if (argc > 3)
+			height = dAtof(argv[3]);
+		else
+			height = width;
+	}
+
+	// Invalid
+	else
+	{
+		Con::warnf("GuiGridCtrl::setCellSize() - Invalid number of parameters!");
+		return;
+	}
+
+	// Set Position.
+	object->setCellSize(width, height);
+}
+
+/*! Gets the size assigned to child controls. Results should be interpreted based on CellMode.
+	@return (float width/float height) The width and height of the cells.
+*/
+ConsoleMethodWithDocs(GuiGridCtrl, getCellSize, ConsoleString, 2, 2, ())
+{
+	return object->getCellSize().stringThis();
+}
+
+/*! Sets the spacing used between each child control. Note that if child controls use margin, there will appear to be additional spacing.
+	@param x The horizontal spacing.
+	@param y The vertical spacing.
+	@return No return value.
+*/
+ConsoleMethodWithDocs(GuiGridCtrl, setCellSpacing, ConsoleVoid, 3, 4, (float x, float y))
+{
+	F32 width, height;
+
+	const U32 elementCount = Utility::mGetStringElementCount(argv[2]);
+
+	// ("width height")
+	if ((elementCount == 2) && (argc == 3))
+	{
+		width = dAtof(Utility::mGetStringElement(argv[2], 0));
+		height = dAtof(Utility::mGetStringElement(argv[2], 1));
+	}
+
+	// (width, [height])
+	else if (elementCount == 1)
+	{
+		width = dAtof(argv[2]);
+
+		if (argc > 3)
+			height = dAtof(argv[3]);
+		else
+			height = width;
+	}
+
+	// Invalid
+	else
+	{
+		Con::warnf("GuiGridCtrl::setCellSpacing() - Invalid number of parameters!");
+		return;
+	}
+
+	// Set Position.
+	object->setCellSpacing(width, height);
+}
+
+/*! Gets the spacing that will be between each child control. Results should be interpreted based on CellMode.
+	@return (float x/float y) The horizontal and vertical spacing between the cells.
+*/
+ConsoleMethodWithDocs(GuiGridCtrl, getCellSpacing, ConsoleString, 2, 2, ())
+{
+	return object->getCellSpacing().stringThis();
+}
+
+/*! Sets the cell mode in the horizontal direction.
+	@return No return value.
+*/
+ConsoleMethodWithDocs(GuiGridCtrl, setCellModeX, ConsoleVoid, 3, 3, (cellMode mode))
+{
+	// Fetch cell mode.
+	const GuiGridCtrl::CellMode mode = GuiGridCtrl::getCellModeEnum(argv[2]);
+
+	// Check for error.
+	if (mode != GuiGridCtrl::Percent && mode != GuiGridCtrl::Variable && mode != GuiGridCtrl::Absolute)
+		return;
+
+	// Set body type.
+	object->setCellModeX(mode);
+}
+
+/*! Sets the cell mode in the vertical direction.
+	@return No return value.
+*/
+ConsoleMethodWithDocs(GuiGridCtrl, setCellModeY, ConsoleVoid, 3, 3, (cellMode mode))
+{
+	// Fetch cell mode.
+	const GuiGridCtrl::CellMode mode = GuiGridCtrl::getCellModeEnum(argv[2]);
+
+	// Check for error.
+	if (mode != GuiGridCtrl::Percent && mode != GuiGridCtrl::Variable && mode != GuiGridCtrl::Absolute)
+		return;
+
+	// Set body type.
+	object->setCellModeY(mode);
+}
+
+/*! Gets the horizontal cell mode.
+	@return The horizontal cell mode.
+*/
+ConsoleMethodWithDocs(GuiGridCtrl, getCellModeX, ConsoleString, 2, 2, ())
+{
+	return GuiGridCtrl::getCellModeDescription(object->getCellModeX());
+}
+
+
+/*! Gets the vertical cell mode.
+	@return The vertical cell mode.
+*/
+ConsoleMethodWithDocs(GuiGridCtrl, getCellModeY, ConsoleString, 2, 2, ())
+{
+	return GuiGridCtrl::getCellModeDescription(object->getCellModeY());
+}
+
+/*! Sets the max number of columns. This will be ignored by Order Modes that end in L or R.
+	@param max The max number of columns. Use zero for auto.
+	@return No return value.
+*/
+ConsoleMethodWithDocs(GuiGridCtrl, setMaxColCount, ConsoleVoid, 3, 3, (int max))
+{
+	object->setMaxColCount(dAtoi(argv[2]));
+}
+
+/*! Sets the max number of rows. This will be ignored by Order Modes that end in T or B.
+	@param max The max number of rows. Use zero for auto.
+	@return No return value.
+*/
+ConsoleMethodWithDocs(GuiGridCtrl, setMaxRowCount, ConsoleVoid, 3, 3, (int max))
+{
+	object->setMaxRowCount(dAtoi(argv[2]));
+}
+
+/*! Gets the max column count.
+	@return The max column count.
+*/
+ConsoleMethodWithDocs(GuiGridCtrl, getMaxColCount, ConsoleInt, 2, 2, ())
+{
+	return object->getMaxColCount();
+}
+
+/*! Gets the max row count.
+	@return The max row count.
+*/
+ConsoleMethodWithDocs(GuiGridCtrl, getMaxRowCount, ConsoleInt, 2, 2, ())
+{
+	return object->getMaxRowCount();
+}
+
+/*! Gets the order mode.
+	@return The order mode.
+*/
+ConsoleMethodWithDocs(GuiGridCtrl, getOrderMode, ConsoleString, 2, 2, ())
+{
+	return GuiGridCtrl::getOrderModeDescription(object->getOrderMode());
+}
+
+/*! Gets if the extent will change based on the size of the contents. Expansion will happen in the direction of the final letter of the order mode.
+	@return The dynamic extent.
+*/
+ConsoleMethodWithDocs(GuiGridCtrl, getIsExtentDynamic, ConsoleBool, 2, 2, ())
+{
+	return object->getIsExtentDynamic();
+}
+
+ConsoleMethodGroupEndWithDocs(GuiGridCtrl)

+ 9 - 7
engine/source/gui/containers/guiScrollCtrl_ScriptBinding.h

@@ -41,7 +41,7 @@ ConsoleMethodWithDocs(GuiScrollCtrl, scrollToTop, void, 2, 2, "()")
 	@sa scrollToRight
 	@sa scrollToRight
 	@sa scrollToPosition
 	@sa scrollToPosition
 */
 */
-ConsoleMethod(GuiScrollCtrl, scrollToBottom, void, 2, 2, "()")
+ConsoleMethodWithDocs(GuiScrollCtrl, scrollToBottom, void, 2, 2, "()")
 {
 {
 	object->scrollTo(object->mScrollOffset.x, 0x7FFFFFFF);
 	object->scrollTo(object->mScrollOffset.x, 0x7FFFFFFF);
 }
 }
@@ -65,7 +65,7 @@ ConsoleMethodWithDocs(GuiScrollCtrl, scrollToLeft, void, 2, 2, "()")
 	@sa scrollToLeft
 	@sa scrollToLeft
 	@sa scrollToPosition
 	@sa scrollToPosition
 */
 */
-ConsoleMethod(GuiScrollCtrl, scrollToRight, void, 2, 2, "()")
+ConsoleMethodWithDocs(GuiScrollCtrl, scrollToRight, void, 2, 2, "()")
 {
 {
 	object->scrollTo(0x7FFFFFFF, object->mScrollOffset.x);
 	object->scrollTo(0x7FFFFFFF, object->mScrollOffset.x);
 }
 }
@@ -75,7 +75,7 @@ ConsoleMethod(GuiScrollCtrl, scrollToRight, void, 2, 2, "()")
 	@param y The vertical target position.
 	@param y The vertical target position.
 	@return No return value.
 	@return No return value.
 */
 */
-ConsoleMethod(GuiScrollCtrl, setScrollPosition, void, 4, 4, "(x, y)")
+ConsoleMethodWithDocs(GuiScrollCtrl, setScrollPosition, void, 4, 4, "(x, y)")
 {
 {
 	object->scrollTo(dAtoi(argv[2]), dAtoi(argv[3]));
 	object->scrollTo(dAtoi(argv[2]), dAtoi(argv[3]));
 }
 }
@@ -83,7 +83,7 @@ ConsoleMethod(GuiScrollCtrl, setScrollPosition, void, 4, 4, "(x, y)")
 /*! Gets the current horizontal scroll position.
 /*! Gets the current horizontal scroll position.
 	@return The position of the content in the horizontal direction.
 	@return The position of the content in the horizontal direction.
 */
 */
-ConsoleMethod(GuiScrollCtrl, getScrollPositionX, S32, 2, 2, "()")
+ConsoleMethodWithDocs(GuiScrollCtrl, getScrollPositionX, S32, 2, 2, "()")
 {
 {
 	return object->mScrollOffset.x;
 	return object->mScrollOffset.x;
 }
 }
@@ -91,7 +91,7 @@ ConsoleMethod(GuiScrollCtrl, getScrollPositionX, S32, 2, 2, "()")
 /*! Gets the current vertical scroll position.
 /*! Gets the current vertical scroll position.
 	@return The position of the content in the vertical direction.
 	@return The position of the content in the vertical direction.
 */
 */
-ConsoleMethod(GuiScrollCtrl, getScrollPositionY, S32, 2, 2, "()")
+ConsoleMethodWithDocs(GuiScrollCtrl, getScrollPositionY, S32, 2, 2, "()")
 {
 {
 	return object->mScrollOffset.y;
 	return object->mScrollOffset.y;
 }
 }
@@ -99,7 +99,7 @@ ConsoleMethod(GuiScrollCtrl, getScrollPositionY, S32, 2, 2, "()")
 /*! Refreshes all the contents of the scroll container.
 /*! Refreshes all the contents of the scroll container.
 	@return No return value.
 	@return No return value.
 */
 */
-ConsoleMethod(GuiScrollCtrl, computeSizes, void, 2, 2, "()")
+ConsoleMethodWithDocs(GuiScrollCtrl, computeSizes, void, 2, 2, "()")
 {
 {
 	object->computeSizes();
 	object->computeSizes();
 }
 }
@@ -138,4 +138,6 @@ ConsoleMethodWithDocs(GuiScrollCtrl, setArrowProfile, ConsoleVoid, 3, 3, (GuiCon
 
 
 	if (Sim::findObject(argv[2], profile))
 	if (Sim::findObject(argv[2], profile))
 		object->setControlArrowProfile(profile);
 		object->setControlArrowProfile(profile);
-}
+}
+
+ConsoleMethodGroupEndWithDocs(GuiScrollCtrl)

+ 1 - 1
engine/source/gui/guiArrayCtrl.h

@@ -30,7 +30,7 @@
 #include "gui/guiTextCtrl.h"
 #include "gui/guiTextCtrl.h"
 #endif
 #endif
 
 
-/// Renders a grid of cells.
+/// Renders a grid of cells. Gives common functionality to a few controls that inherit from it, but has no conObject.
 class GuiArrayCtrl : public GuiControl
 class GuiArrayCtrl : public GuiControl
 {
 {
    typedef GuiControl Parent;
    typedef GuiControl Parent;

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

@@ -445,10 +445,7 @@ void GuiControl::parentResized(const Point2I &oldParentExtent, const Point2I &ne
       newExtent.y = newBottom - newTop;
       newExtent.y = newBottom - newTop;
    }
    }
 
 
-   // Resizing Re factor [9/18/2006]
-   // Only resize if our minExtent is satisfied with it.
-   //if( newExtent.x >= mMinExtent.x && newExtent.y >= mMinExtent.y )
-      resize(newPosition, newExtent);
+   resize(newPosition, newExtent);
 }
 }
 
 
 //----------------------------------------------------------------
 //----------------------------------------------------------------
@@ -1011,21 +1008,16 @@ void GuiControl::write(Stream &stream, U32 tabStop, U32 flags)
 
 
 
 
 
 
+//This is only called if the control is deleted, not when the control is removed from its parent.
 void GuiControl::onRemove()
 void GuiControl::onRemove()
 {
 {
-   clearFirstResponder();
-
-   Parent::onRemove();
-
-  // If we are a child, notify our parent that we've been removed
-  GuiControl *parent = getParent();
-  if( parent )
-     parent->onChildRemoved( this );
+	Parent::onRemove();
 }
 }
 
 
-void GuiControl::onChildRemoved( GuiControl *child )
+//For GuiControls, this will always just before it is actually removed.
+void GuiControl::onGroupRemove()
 {
 {
-   // Base does nothing with this
+	clearFirstResponder();
 }
 }
 
 
 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- //
 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- //

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

@@ -458,16 +458,16 @@ public:
     /// Do special pre-render proecessing
     /// Do special pre-render proecessing
     virtual void onPreRender();
     virtual void onPreRender();
 
 
-    /// Called when this object is removed
+    /// Called when this object is removed using delete.
     virtual void onRemove();
     virtual void onRemove();
 
 
-    /// Called when one of this objects children is removed
-    virtual void onChildRemoved( GuiControl *child );
+	/// Called when this object is removed using delete or parent.remove().
+	virtual void onGroupRemove();
 
 
     /// Called when this object is added to the scene
     /// Called when this object is added to the scene
     bool onAdd();
     bool onAdd();
 
 
-    /// Called when this object has a new child
+    /// Called when this object has a new child. Congratulations!
     virtual void onChildAdded( GuiControl *child );
     virtual void onChildAdded( GuiControl *child );
 
 
     /// @}
     /// @}

+ 6 - 0
engine/source/sim/simSet.cc

@@ -377,10 +377,16 @@ void SimGroup::removeObject(SimObject* obj)
       nameDictionary.remove(obj);
       nameDictionary.remove(obj);
       objectList.remove(obj);
       objectList.remove(obj);
       obj->mGroup = 0;
       obj->mGroup = 0;
+	  onChildRemoved(obj);
    }
    }
    unlock();
    unlock();
 }
 }
 
 
+void SimGroup::onChildRemoved(SimObject* obj)
+{
+	//Left blank...
+}
+
 //////////////////////////////////////////////////////////////////////////
 //////////////////////////////////////////////////////////////////////////
 
 
 void SimGroup::onRemove()
 void SimGroup::onRemove()

+ 2 - 0
engine/source/sim/simSet.h

@@ -310,6 +310,8 @@ public:
 
 
    virtual void onRemove();
    virtual void onRemove();
 
 
+   virtual void onChildRemoved(SimObject*);
+
    /// Find an object in the group.
    /// Find an object in the group.
    virtual SimObject* findObject(const char* name);
    virtual SimObject* findObject(const char* name);
 
 

+ 7 - 6
toybox/Sandbox/1/gui/ToolboxDialog.gui.taml

@@ -344,7 +344,7 @@
 				constantThumbHeight="0"
 				constantThumbHeight="0"
 				childMargin="2 3" >
 				childMargin="2 3" >
 
 
-				<GuiDynamicCtrlArrayControl
+				<GuiGridCtrl
 					Name="ToyListArray"
 					Name="ToyListArray"
 					canSaveDynamicFields="0"
 					canSaveDynamicFields="0"
 					internalName="objectList"
 					internalName="objectList"
@@ -360,11 +360,12 @@
 					Active="1"
 					Active="1"
 					tooltipprofile="GuiToolTipProfile"
 					tooltipprofile="GuiToolTipProfile"
 					hovertime="1000"
 					hovertime="1000"
-					colCount="1"
-					colSize="180"
-					rowSize="50"
-					rowSpacing="8"
-					colSpacing="8" />
+					MaxColCount="1"
+					CellSizeX="180"
+					CellSizeY="50"
+					CellSpacingX="8"
+					CellSpacingY="8"
+					CellModeX="Variable" />
 			</GuiScrollCtrl>
 			</GuiScrollCtrl>
 		</GuiControl>
 		</GuiControl>
 	</GuiControl>
 	</GuiControl>

+ 71 - 70
toybox/Sandbox/1/scripts/customToolboxGui.cs

@@ -40,7 +40,7 @@ function resetCustomControls()
 {
 {
     Sandbox.lastControlBottom = "0";
     Sandbox.lastControlBottom = "0";
     Sandbox.customControlCount = 0;
     Sandbox.customControlCount = 0;
-    
+
     %customControlExtent = ToyCustomControls.Extent;
     %customControlExtent = ToyCustomControls.Extent;
     %newExtent = getWord(ToyCustomControls.Extent, 0) SPC 705;
     %newExtent = getWord(ToyCustomControls.Extent, 0) SPC 705;
     ToyCustomControls.Extent = %newExtent;
     ToyCustomControls.Extent = %newExtent;
@@ -138,15 +138,15 @@ function addFlagOption( %label, %callback, %startingValue, %shouldReset, %toolti
     ToyCustomControls.add(%container);
     ToyCustomControls.add(%container);
 
 
     Sandbox.lastControlBottom = getWord(%container.position, 1) + getWord(%container.extent, 1);
     Sandbox.lastControlBottom = getWord(%container.position, 1) + getWord(%container.extent, 1);
-    
+
     if (Sandbox.lastControlBottom > getWord(ToyCustomControls.Extent, 1))
     if (Sandbox.lastControlBottom > getWord(ToyCustomControls.Extent, 1))
     {
     {
         %rootContainerExtent = getWord(ToyCustomControls.Extent, 0) SPC Sandbox.lastControlBottom + 20;
         %rootContainerExtent = getWord(ToyCustomControls.Extent, 0) SPC Sandbox.lastControlBottom + 20;
-    
+
         ToyCustomControls.Extent = %rootContainerExtent;
         ToyCustomControls.Extent = %rootContainerExtent;
         CustomControlsScroller.computeSizes();
         CustomControlsScroller.computeSizes();
     }
     }
-    
+
     Sandbox.customControlCount++;
     Sandbox.customControlCount++;
 }
 }
 
 
@@ -156,14 +156,14 @@ function FlagController::updateToy(%this)
 {
 {
     if (%this.toy $= "")
     if (%this.toy $= "")
         return;
         return;
-        
+
     if (%this.callback !$= "")
     if (%this.callback !$= "")
     {
     {
         %setter = "%this.toy." @ %this.callback @ "(" @ %this.getStateOn() @ ");";
         %setter = "%this.toy." @ %this.callback @ "(" @ %this.getStateOn() @ ");";
 
 
         eval(%setter);
         eval(%setter);
     }
     }
-    
+
     if (%this.shouldResetToy && %this.toy.isMethod("reset"))
     if (%this.shouldResetToy && %this.toy.isMethod("reset"))
         %this.toy.reset();
         %this.toy.reset();
 }
 }
@@ -223,11 +223,11 @@ function addButtonOption( %label, %callback, %shouldReset, %tooltipText)
     if (Sandbox.lastControlBottom > getWord(ToyCustomControls.Extent, 1))
     if (Sandbox.lastControlBottom > getWord(ToyCustomControls.Extent, 1))
     {
     {
         %rootContainerExtent = getWord(ToyCustomControls.Extent, 0) SPC Sandbox.lastControlBottom + 20;
         %rootContainerExtent = getWord(ToyCustomControls.Extent, 0) SPC Sandbox.lastControlBottom + 20;
-    
+
         ToyCustomControls.Extent = %rootContainerExtent;
         ToyCustomControls.Extent = %rootContainerExtent;
         CustomControlsScroller.computeSizes();
         CustomControlsScroller.computeSizes();
     }
     }
-    
+
     Sandbox.customControlCount++;
     Sandbox.customControlCount++;
 }
 }
 
 
@@ -370,11 +370,11 @@ function addNumericOption( %label, %min, %max, %step, %callback, %startingValue,
     if (Sandbox.lastControlBottom > getWord(ToyCustomControls.Extent, 1))
     if (Sandbox.lastControlBottom > getWord(ToyCustomControls.Extent, 1))
     {
     {
         %rootContainerExtent = getWord(ToyCustomControls.Extent, 0) SPC Sandbox.lastControlBottom + 20;
         %rootContainerExtent = getWord(ToyCustomControls.Extent, 0) SPC Sandbox.lastControlBottom + 20;
-    
+
         ToyCustomControls.Extent = %rootContainerExtent;
         ToyCustomControls.Extent = %rootContainerExtent;
         CustomControlsScroller.computeSizes();
         CustomControlsScroller.computeSizes();
     }
     }
-    
+
     Sandbox.customControlCount++;
     Sandbox.customControlCount++;
 }
 }
 
 
@@ -388,20 +388,20 @@ function SpinnerController::updateTarget(%this)
     {
     {
         %value = %target.getText();
         %value = %target.getText();
         %value += %this.step;
         %value += %this.step;
-        
+
         if (%value > %target.max)
         if (%value > %target.max)
             %value = %target.max;
             %value = %target.max;
-        
+
         %target.setText(%value);
         %target.setText(%value);
     }
     }
     else if (%this.action $= "decrease")
     else if (%this.action $= "decrease")
     {
     {
         %value = %target.getText();
         %value = %target.getText();
         %value -= %this.step;
         %value -= %this.step;
-        
+
         if (%value < %target.min)
         if (%value < %target.min)
             %value = %target.min;
             %value = %target.min;
-            
+
         %target.setText(%value);
         %target.setText(%value);
     }
     }
 
 
@@ -414,18 +414,18 @@ function TextEditController::updateToy(%this)
 {
 {
     if (%this.toy $= "")
     if (%this.toy $= "")
         return;
         return;
-    
+
     if (%this.getText() > %this.max)
     if (%this.getText() > %this.max)
         %this.setText(%this.max);
         %this.setText(%this.max);
     else if (%this.getText() < %this.min)
     else if (%this.getText() < %this.min)
         %this.setText(%this.min);
         %this.setText(%this.min);
-    
+
     if (%this.callback !$= "" && %this.getValue() !$= "")
     if (%this.callback !$= "" && %this.getValue() !$= "")
     {
     {
         %setter = "%this.toy." @ %this.callback @ "(" @ %this.getValue() @ ");";
         %setter = "%this.toy." @ %this.callback @ "(" @ %this.getValue() @ ");";
         eval(%setter);
         eval(%setter);
     }
     }
-    
+
     if (%this.shouldResetToy && %this.toy.isMethod("reset"))
     if (%this.shouldResetToy && %this.toy.isMethod("reset"))
         %this.toy.reset();
         %this.toy.reset();
 }
 }
@@ -436,47 +436,47 @@ function addSelectionOption( %entries, %label, %maxDisplay, %callback, %shouldRe
 {
 {
     // Combined Y extent of the up/down buttons
     // Combined Y extent of the up/down buttons
     %buttonExtentAddition = 46;
     %buttonExtentAddition = 46;
-    
+
     // Extra padding
     // Extra padding
-    %buffer = 15;  
-    
-    // Size of each button added to the list  
+    %buffer = 15;
+
+    // Size of each button added to the list
     %buttonSize = 50;
     %buttonSize = 50;
     %buttonSpacing = %maxDisplay;// * 8;
     %buttonSpacing = %maxDisplay;// * 8;
-    
-    // Starting location of the main container    
+
+    // Starting location of the main container
     %containerPosition = nextCustomControlPosition(Sandbox.customControlCount);
     %containerPosition = nextCustomControlPosition(Sandbox.customControlCount);
-    
+
     // Main container base width
     // Main container base width
     %containerWidth = getWord(Sandbox.customContainerExtent, 0);
     %containerWidth = getWord(Sandbox.customContainerExtent, 0);
-    
+
     // Main container base height
     // Main container base height
     %containerHeight = getWord(Sandbox.customContainerExtent, 1) + getWord(Sandbox.listOptionExtent, 1) + Sandbox.customLabelHeight;
     %containerHeight = getWord(Sandbox.customContainerExtent, 1) + getWord(Sandbox.listOptionExtent, 1) + Sandbox.customLabelHeight;
-    
+
     // Main container buffer (accounts for size of list, up/down buttons, and buffer)
     // Main container buffer (accounts for size of list, up/down buttons, and buffer)
     %containerHeight += ((%maxDisplay+1) * %buttonSize) + %buttonExtentAddition + %buffer;
     %containerHeight += ((%maxDisplay+1) * %buttonSize) + %buttonExtentAddition + %buffer;
-    
+
     // X position of buttons
     // X position of buttons
     %buttonX = "90";
     %buttonX = "90";
-    
-    // Y position for up button 
+
+    // Y position for up button
     %upButtonY = Sandbox.customLabelSpacing;
     %upButtonY = Sandbox.customLabelSpacing;
-    
+
     // List container
     // List container
     %listContainerPosition = "0" SPC %upButtonY + 22;
     %listContainerPosition = "0" SPC %upButtonY + 22;
     %listContainerWidth = %containerWidth;
     %listContainerWidth = %containerWidth;
     %listContainerHeight = ((%maxDisplay+1) * %buttonSize) + %buttonSpacing;
     %listContainerHeight = ((%maxDisplay+1) * %buttonSize) + %buttonSpacing;
-    
+
     %scrollContainerWidth = %listContainerWidth - 5;
     %scrollContainerWidth = %listContainerWidth - 5;
     %scrollContainerHeight = %listContainerHeight;
     %scrollContainerHeight = %listContainerHeight;
-    
+
     // Array control
     // Array control
     %arrayListWidth = %scrollContainerWidth - 25;
     %arrayListWidth = %scrollContainerWidth - 25;
     %arrayListHeight = 0;
     %arrayListHeight = 0;
-    
+
     // Y position for the down button
     // Y position for the down button
     %downButtonY = getWord(%listContainerPosition, 1) + %listContainerHeight;
     %downButtonY = getWord(%listContainerPosition, 1) + %listContainerHeight;
-    
+
     // Create the base container
     // Create the base container
     %container = new GuiControl()
     %container = new GuiControl()
     {
     {
@@ -487,11 +487,11 @@ function addSelectionOption( %entries, %label, %maxDisplay, %callback, %shouldRe
         extent = %containerWidth SPC %containerHeight;
         extent = %containerWidth SPC %containerHeight;
         Profile = GuiTransparentProfile;
         Profile = GuiTransparentProfile;
     };
     };
-    
+
     // Create and add the text label
     // Create and add the text label
     %customLabel = createCustomLabel(%label);
     %customLabel = createCustomLabel(%label);
     %container.add(%customLabel);
     %container.add(%customLabel);
-    
+
     %listContainer = new GuiControl()
     %listContainer = new GuiControl()
     {
     {
         isContainer = 1;
         isContainer = 1;
@@ -501,7 +501,7 @@ function addSelectionOption( %entries, %label, %maxDisplay, %callback, %shouldRe
         extent = %listContainerWidth SPC %listContainerHeight;
         extent = %listContainerWidth SPC %listContainerHeight;
         Profile = GuiSunkenContainerProfile;
         Profile = GuiSunkenContainerProfile;
     };
     };
-    
+
     %scrollControl = new GuiScrollCtrl()
     %scrollControl = new GuiScrollCtrl()
     {
     {
         canSaveDynamicFields = "1";
         canSaveDynamicFields = "1";
@@ -523,10 +523,10 @@ function addSelectionOption( %entries, %label, %maxDisplay, %callback, %shouldRe
         constantThumbHeight = "0";
         constantThumbHeight = "0";
         childMargin = "2 3";
         childMargin = "2 3";
         toolTipProfile = "GuiToolTipProfile";
         toolTipProfile = "GuiToolTipProfile";
-        toolTip = %tooltipText;        
+        toolTip = %tooltipText;
     };
     };
-    
-    %arrayList = new GuiDynamicCtrlArrayControl()
+
+    %arrayList = new GuiGridCtrl()
     {
     {
         canSaveDynamicFields = "0";
         canSaveDynamicFields = "0";
         isContainer = "1";
         isContainer = "1";
@@ -542,23 +542,24 @@ function addSelectionOption( %entries, %label, %maxDisplay, %callback, %shouldRe
         Active = "1";
         Active = "1";
         tooltipprofile = "GuiToolTipProfile";
         tooltipprofile = "GuiToolTipProfile";
         hovertime = "1000";
         hovertime = "1000";
-        colCount = "1";
-        colSize = %arrayListWidth-10;
-        rowSize = "50";
-        rowSpacing = "8";
-        colSpacing = "8";
+        MaxColCount = "1";
+        CellSizeX = %arrayListWidth-10;
+        CellSizeY = "50";
+        CellSpacingX = "8";
+        CellSpacingY = "8";
+		CellModeX = "variable";
         toolTipProfile = "GuiToolTipProfile";
         toolTipProfile = "GuiToolTipProfile";
-        toolTip = %tooltipText;       
+        toolTip = %tooltipText;
     };
     };
-    
+
     %scrollControl.add(%arrayList);
     %scrollControl.add(%arrayList);
-    
+
     %listContainer.add(%scrollControl);
     %listContainer.add(%scrollControl);
-        
+
     %container.add(%listContainer);
     %container.add(%listContainer);
-    
+
     // Populate the list
     // Populate the list
-    
+
     for (%i = 0; %i < getUnitCount(%entries, ","); %i++)
     for (%i = 0; %i < getUnitCount(%entries, ","); %i++)
     {
     {
         %button = new GuiButtonCtrl()
         %button = new GuiButtonCtrl()
@@ -582,14 +583,14 @@ function addSelectionOption( %entries, %label, %maxDisplay, %callback, %shouldRe
             buttonType = "ToggleButton";
             buttonType = "ToggleButton";
             useMouseEvents = "0";
             useMouseEvents = "0";
             toolTipProfile = "GuiToolTipProfile";
             toolTipProfile = "GuiToolTipProfile";
-            toolTip = %tooltipText;            
+            toolTip = %tooltipText;
         };
         };
-        
+
         %button.command = %arrayList @ ".clearSelections();" @ %button @ ".updateToy();";
         %button.command = %arrayList @ ".clearSelections();" @ %button @ ".updateToy();";
-        
+
         %arrayList.add(%button);
         %arrayList.add(%button);
     }
     }
-    
+
     // Create and add the up button
     // Create and add the up button
     %upButton = new GuiImageButtonCtrl()
     %upButton = new GuiImageButtonCtrl()
     {
     {
@@ -611,11 +612,11 @@ function addSelectionOption( %entries, %label, %maxDisplay, %callback, %shouldRe
         HoverImage = "Sandbox:northArrowHover";
         HoverImage = "Sandbox:northArrowHover";
         DownImage = "Sandbox:northArrowDown";
         DownImage = "Sandbox:northArrowDown";
         toolTipProfile = "GuiToolTipProfile";
         toolTipProfile = "GuiToolTipProfile";
-        toolTip = %tooltipText;       
+        toolTip = %tooltipText;
     };
     };
-    
+
     %upButton.command = %scrollControl @ ".scrollToPrevious();";
     %upButton.command = %scrollControl @ ".scrollToPrevious();";
-    
+
     // Create and add the down button
     // Create and add the down button
     %downButton = new GuiImageButtonCtrl()
     %downButton = new GuiImageButtonCtrl()
     {
     {
@@ -637,26 +638,26 @@ function addSelectionOption( %entries, %label, %maxDisplay, %callback, %shouldRe
         HoverImage = "Sandbox:southArrowHover";
         HoverImage = "Sandbox:southArrowHover";
         DownImage = "Sandbox:southArrowDown";
         DownImage = "Sandbox:southArrowDown";
         toolTipProfile = "GuiToolTipProfile";
         toolTipProfile = "GuiToolTipProfile";
-        toolTip = %tooltipText;        
+        toolTip = %tooltipText;
     };
     };
-    
+
     %downButton.command = %scrollControl @ ".scrollToNext();";
     %downButton.command = %scrollControl @ ".scrollToNext();";
-    
-    %container.add(%upButton);    
+
+    %container.add(%upButton);
     %container.add(%downButton);
     %container.add(%downButton);
-    
+
     ToyCustomControls.add(%container);
     ToyCustomControls.add(%container);
-        
+
     Sandbox.lastControlBottom = getWord(%container.position, 1) + getWord(%container.extent, 1);
     Sandbox.lastControlBottom = getWord(%container.position, 1) + getWord(%container.extent, 1);
-    
+
     if (Sandbox.lastControlBottom > getWord(ToyCustomControls.Extent, 1))
     if (Sandbox.lastControlBottom > getWord(ToyCustomControls.Extent, 1))
     {
     {
         %rootContainerExtent = getWord(ToyCustomControls.Extent, 0) SPC Sandbox.lastControlBottom + 20;
         %rootContainerExtent = getWord(ToyCustomControls.Extent, 0) SPC Sandbox.lastControlBottom + 20;
-    
+
         ToyCustomControls.Extent = %rootContainerExtent;
         ToyCustomControls.Extent = %rootContainerExtent;
         CustomControlsScroller.computeSizes();
         CustomControlsScroller.computeSizes();
     }
     }
-    
+
     Sandbox.customControlCount++;
     Sandbox.customControlCount++;
 }
 }
 
 
@@ -667,7 +668,7 @@ function CustomOptionArrayClass::clearSelections(%this)
     for (%i = 0; %i < %count; %i++)
     for (%i = 0; %i < %count; %i++)
     {
     {
         %button = %this.getObject(%i);
         %button = %this.getObject(%i);
-        
+
         %button.setStateOn(false);
         %button.setStateOn(false);
     }
     }
 }
 }
@@ -697,7 +698,7 @@ function SelectionController::updateToy(%this)
         return;
         return;
 
 
     %this.setStateOn(true);
     %this.setStateOn(true);
-    
+
     if (%this.callback !$= "")
     if (%this.callback !$= "")
     {
     {
         %value = %this.getText();
         %value = %this.getText();
@@ -707,4 +708,4 @@ function SelectionController::updateToy(%this)
 
 
     if (%this.shouldResetToy && %this.toy.isMethod("reset"))
     if (%this.shouldResetToy && %this.toy.isMethod("reset"))
         %this.toy.reset();
         %this.toy.reset();
-}
+}