Browse Source

Adds the NEW GuiMenuBarCtrl!

This adds the brand new GuiMenuBarCtrl! It also removes the  old GuiMenuBar and the  GuiFormCtrl.
Peter Robinson 4 years ago
parent
commit
6045ff0788
33 changed files with 2680 additions and 2611 deletions
  1. 69 5
      editor/EditorCore/EditorCore.cs
  2. 177 6
      editor/EditorCore/Themes/BaseTheme/BaseTheme.cs
  3. 2 2
      editor/EditorCore/Themes/ThemeManager.cs
  4. 171 0
      editor/EditorCore/Themes/TorqueSuit/TorqueSuitTheme.cs
  5. 51 0
      engine/compilers/VisualStudio 2017/GuiBlank.gui
  6. 3 4
      engine/compilers/VisualStudio 2017/Torque 2D.vcxproj
  7. 9 12
      engine/compilers/VisualStudio 2017/Torque 2D.vcxproj.filters
  8. 1 1
      engine/source/gui/buttons/guiDropDownCtrl.cc
  9. 28 21
      engine/source/gui/containers/guiChainCtrl.cc
  10. 4 1
      engine/source/gui/containers/guiChainCtrl.h
  11. 0 450
      engine/source/gui/containers/guiFormCtrl.cc
  12. 0 113
      engine/source/gui/containers/guiFormCtrl.h
  13. 0 4
      engine/source/gui/containers/guiTabBookCtrl.h
  14. 1 1
      engine/source/gui/containers/guiWindowCtrl.cc
  15. 0 4
      engine/source/gui/containers/guiWindowCtrl.h
  16. 0 1679
      engine/source/gui/editor/guiMenuBar.cc
  17. 0 215
      engine/source/gui/editor/guiMenuBar.h
  18. 1441 0
      engine/source/gui/editor/guiMenuBarCtrl.cc
  19. 223 0
      engine/source/gui/editor/guiMenuBarCtrl.h
  20. 109 0
      engine/source/gui/editor/guiMenuBarCtrl_ScriptBinding.h
  21. 1 1
      engine/source/gui/guiCanvas.cc
  22. 9 0
      engine/source/gui/guiCanvas.h
  23. 0 1
      engine/source/gui/guiControl.cc
  24. 2 2
      engine/source/gui/guiControl.h
  25. 38 9
      engine/source/gui/guiDefaultControlRender.cc
  26. 2 2
      engine/source/gui/guiDefaultControlRender.h
  27. 1 2
      engine/source/gui/guiListBoxCtrl.cc
  28. 0 5
      engine/source/gui/guiProgressCtrl.h
  29. 10 2
      engine/source/input/actionMap.cc
  30. 1 0
      engine/source/input/actionMap.h
  31. 193 0
      toybox/GuiEditorToy/1/assets/gui/guiEditorCtrl.gui
  32. 0 69
      toybox/GuiEditorToy/1/main.cs
  33. 134 0
      toybox/Sandbox/1/gui/guiProfiles.cs

+ 69 - 5
editor/EditorCore/EditorCore.cs

@@ -41,24 +41,88 @@ function EditorCore::destroy( %this )
 
 
 function EditorCore::initGui(%this)
 function EditorCore::initGui(%this)
 {
 {
-	%this.tabBook = new GuiTabBookCtrl()
+	%this.baseGui = new GuiControl()
 	{
 	{
-		Class = EditorCoreTabBook;
 		HorizSizing = width;
 		HorizSizing = width;
 		VertSizing = height;
 		VertSizing = height;
 		Position = "0 0";
 		Position = "0 0";
 		Extent = "1024 768";
 		Extent = "1024 768";
+	};
+	ThemeManager.setProfile(%this.baseGui, "emptyProfile");
+
+	%this.menuBar = new GuiMenuBarCtrl()
+	{
+		new GuiMenuItemCtrl() {
+			Text = "Tools";
+
+			new GuiMenuItemCtrl() {
+				Text = "Close Tools";
+				Command = "EditorCore.close();";
+			};
+		};
+		new GuiMenuItemCtrl() {
+			Text = "Theme";
+
+			new GuiMenuItemCtrl() {
+				Text = "Construction Vest";
+				Radio = true;
+				IsOn = true;
+				Command = "ThemeManager.setTheme(0);";
+				Accelerator = "Ctrl 1";
+			};
+
+			new GuiMenuItemCtrl() {
+				Text = "Lab Coat";
+				Radio = true;
+				Command = "ThemeManager.setTheme(1);";
+				Accelerator = "Ctrl 2";
+			};
+
+			new GuiMenuItemCtrl() {
+				Text = "Forest Robe";
+				Radio = true;
+				Command = "ThemeManager.setTheme(2);";
+				Accelerator = "Ctrl 3";
+			};
+
+			new GuiMenuItemCtrl() {
+				Text = "Torque Suit";
+				Radio = true;
+				Command = "ThemeManager.setTheme(3);";
+				Accelerator = "Ctrl 4";
+			};
+		};
+	};
+	ThemeManager.setProfile(%this.menuBar, "menuBarProfile");
+	ThemeManager.setProfile(%this.menuBar, "menuProfile", "MenuProfile");
+	ThemeManager.setProfile(%this.menuBar, "menuItemProfile", "MenuItemProfile");
+	ThemeManager.setProfile(%this.menuBar, "menuContentProfile", "MenuContentProfile");
+	ThemeManager.setProfile(%this.menuBar, "scrollingPanelThumbProfile", "ThumbProfile");
+	ThemeManager.setProfile(%this.menuBar, "scrollingPanelArrowProfile", "ArrowProfile");
+	ThemeManager.setProfile(%this.menuBar, "scrollingPanelTrackProfile", "TrackProfile");
+
+	%this.baseGui.add(%this.menuBar);
+
+	%this.tabBook = new GuiTabBookCtrl()
+	{
+		Class = EditorCoreTabBook;
+		HorizSizing = width;
+		VertSizing = height;
+		Position = "0 26";
+		Extent = "1024 742";
 		TabPosition = top;
 		TabPosition = top;
 		Core = %this;
 		Core = %this;
 	};
 	};
 	ThemeManager.setProfile(%this.tabBook, "tabBookProfileTop");
 	ThemeManager.setProfile(%this.tabBook, "tabBookProfileTop");
 	ThemeManager.setProfile(%this.tabBook, "tabProfileTop", "TabProfile");
 	ThemeManager.setProfile(%this.tabBook, "tabProfileTop", "TabProfile");
+
+	%this.baseGui.add(%this.tabBook);
 }
 }
 
 
 function EditorCore::toggleEditor(%this)
 function EditorCore::toggleEditor(%this)
 {
 {
     // Is the console awake?
     // Is the console awake?
-    if ( %this.tabBook.isAwake() )
+    if ( %this.baseGui.isAwake() )
     {
     {
         // Yes, so deactivate it.
         // Yes, so deactivate it.
         %this.close();
         %this.close();
@@ -74,7 +138,7 @@ function EditorCore::open(%this)
 	if ( $enableDirectInput )
 	if ( $enableDirectInput )
         deactivateKeyboard();
         deactivateKeyboard();
 
 
-    Canvas.pushDialog(%this.tabBook);
+    Canvas.pushDialog(%this.baseGui);
 
 
 	%this.tabBook.selectPage(0);
 	%this.tabBook.selectPage(0);
 }
 }
@@ -83,7 +147,7 @@ function EditorCore::close(%this)
 {
 {
 	if ( $enableDirectInput )
 	if ( $enableDirectInput )
 		activateKeyboard();
 		activateKeyboard();
-	Canvas.popDialog(%this.tabBook);
+	Canvas.popDialog(%this.baseGui);
 }
 }
 
 
 function EditorCore::RegisterEditor(%this, %name, %editor)
 function EditorCore::RegisterEditor(%this, %name, %editor)

+ 177 - 6
editor/EditorCore/Themes/BaseTheme/BaseTheme.cs

@@ -53,6 +53,7 @@ function BaseTheme::onAdd(%this)
 	%this.makeTextEditProfile();
 	%this.makeTextEditProfile();
 	%this.makeScrollProfile();
 	%this.makeScrollProfile();
 	%this.makeConsoleProfile();
 	%this.makeConsoleProfile();
+	%this.makeMenuProfile();
 }
 }
 
 
 function BaseTheme::init(%this)
 function BaseTheme::init(%this)
@@ -75,11 +76,6 @@ function BaseTheme::init(%this)
 	%this.borderSize = 3;
 	%this.borderSize = 3;
 }
 }
 
 
-function BaseTheme::createProfile(%this, %profileName, %parentName, %settings)
-{
-
-}
-
 function BaseTheme::makeTipProfile(%this)
 function BaseTheme::makeTipProfile(%this)
 {
 {
 	%tipBorder = new GuiBorderProfile()
 	%tipBorder = new GuiBorderProfile()
@@ -159,7 +155,11 @@ function BaseTheme::makeGeneralProfiles(%this)
 
 
 	%this.spriteProfile = new GuiControlProfile()
 	%this.spriteProfile = new GuiControlProfile()
 	{
 	{
-		fillColor = "255 255 255 255";
+		fillColor = "0 0 0 0";
+		align = center;
+		vAlign = middle;
+
+		borderDefault = %this.emptyBorder;
 		useInput = false;
 		useInput = false;
 	};
 	};
 }
 }
@@ -764,6 +764,177 @@ function BaseTheme::makeConsoleProfile(%this)
 	};
 	};
 }
 }
 
 
+function BaseTheme::makeMenuProfile(%this)
+{
+	%menuBarBorder = new GuiBorderProfile()
+	{
+		padding = 2;
+	};
+
+	%this.menuBarProfile = new GuiControlProfile()
+	{
+		fillColor = %this.adjustValue(%this.color1, -7);
+		canKeyFocus = true;
+		borderDefault = %menuBarBorder;
+	};
+
+	%menuBorder = new GuiBorderProfile()
+	{
+		margin = 2;
+		marginHL = 0;
+		marginSL = 0;
+		marginNA = 2;
+
+		border = 0;
+		borderHL = 2;
+		borderSL = 2;
+		borderNA = 0;
+
+		borderColorHL = "255 255 255 30";
+		borderColorSL = %this.color5;
+	};
+
+	%menuBottomBorder = new GuiBorderProfile()
+	{
+		paddingSL = 2;
+
+		margin = 2;
+		marginHL = 0;
+		marginSL = 0;
+		marginNA = 2;
+
+		border = 0;
+		borderHL = 2;
+		borderSL = 2;
+		borderNA = 0;
+
+		borderColorHL = "255 255 255 30";
+		borderColorSL = %this.color5;
+	};
+
+	%menuSideBorder = new GuiBorderProfile()
+	{
+		border = 0;
+		borderHL = 2;
+		borderSL = 2;
+		borderNA = 0;
+
+		padding = 10;
+		paddingHL = 8;
+		paddingSL = 8;
+		paddingNA = 10;
+
+		borderColorHL = "255 255 255 30";
+		borderColorSL = %this.color5;
+	};
+
+	%this.menuProfile = new GuiControlProfile()
+	{
+		fillColor = "0 0 0 0";
+		fillColorHL = "255 255 255 10";
+		fillColorSL = %this.adjustValue(%this.color5, -15);
+		fillColorNA = "0 0 0 0";
+
+		borderDefault = %menuBorder;
+		borderLeft = %menuSideBorder;
+		borderRight = %menuSideBorder;
+		borderBottom = %menuBottomBorder;
+
+		fontType = %this.font[3];
+		fontDirectory = %this.fontDirectory;
+		fontSize = %this.fontSize;
+
+		fontColor = %this.color4;
+		fontColorHL = %this.adjustValue(%this.color4, 10);
+		fontColorSL = %this.color4;
+		fontColorNA = %this.adjustValue(%this.color4, 100);
+
+		canKeyFocus = true;
+	};
+
+	%menuContentVertBorder = new GuiBorderProfile()
+	{
+		border = 2;
+		padding = 4;
+		borderColor = %this.color5;
+	};
+
+	%menuContentSideBorder = new GuiBorderProfile()
+	{
+		border = 2;
+		padding = 0;
+		borderColor = %this.color5;
+	};
+
+	%this.menuContentProfile = new GuiControlProfile()
+	{
+		fillColor = %this.adjustValue(%this.color1, -5);
+
+		borderDefault = %menuContentSideBorder;
+		borderTop = %menuContentVertBorder;
+		borderBottom = %menuContentVertBorder;
+	};
+
+	%menuItemBorderTop = new GuiBorderProfile()
+	{
+		padding = 6;
+		paddingHL = 6;
+		paddingSL = 0;
+		paddingNA = 6;
+
+		marginSL = 4;
+		borderSL = 1;
+		borderColorSL = "0 0 0 50";
+	};
+
+	%menuItemBorderBottom = new GuiBorderProfile()
+	{
+		padding = 6;
+		paddingHL = 6;
+		paddingSL = 0;
+		paddingNA = 6;
+
+		marginSL = 4;
+		borderSL = 1;
+		borderColorSL = "255 255 255 50";
+	};
+
+	%menuItemBorderSide = new GuiBorderProfile()
+	{
+		padding = 6;
+		paddingHL = 6;
+		paddingSL = 0;
+		paddingNA = 6;
+
+		marginSL = 0;
+		borderSL = 0;
+		paddingSL = 6;
+	};
+
+	%this.menuItemProfile = new GuiControlProfile()
+	{
+		fillColor = %this.adjustValue(%this.color1, -5);
+		fillColorHL = %this.adjustValue(%this.color5, -15);
+		fillColorNA = %this.color1;
+		align = left;
+
+		tab = false;
+		canKeyFocus = true;
+
+		fontType = %this.font[3];
+		fontDirectory = %this.fontDirectory;
+		fontSize = %this.fontSize;
+
+		fontColor = %this.color4;
+		fontColorHL = %this.adjustValue(%this.color4, 10);
+		fontColorNA = %this.setAlpha(%this.color4, 150);
+
+		borderDefault = %menuItemBorderSide;
+		borderTop = %menuItemBorderTop;
+		borderBottom = %menuItemBorderBottom;
+	};
+}
+
 //Positive values are brighter, negative are darker
 //Positive values are brighter, negative are darker
 function BaseTheme::adjustValue(%this, %color, %percent)
 function BaseTheme::adjustValue(%this, %color, %percent)
 {
 {

+ 2 - 2
editor/EditorCore/Themes/ThemeManager.cs

@@ -97,7 +97,7 @@ function ThemeManager::refreshProfiles(%this)
 				error("ThemeManager::setProfile - Unable to find profile" SPC %obj.profileName SPC "for theme" SPC %this.activeTheme.name @ "!");
 				error("ThemeManager::setProfile - Unable to find profile" SPC %obj.profileName SPC "for theme" SPC %this.activeTheme.name @ "!");
 			}
 			}
 
 
-			%obj.gui.setFieldValue(%obj.profileTag, %this.activeTheme.getFieldValue(%obj.profileName));
+			%obj.gui.setEditFieldValue(%obj.profileTag, %this.activeTheme.getFieldValue(%obj.profileName));
 		}
 		}
 		else
 		else
 		{
 		{
@@ -120,7 +120,7 @@ function ThemeManager::setProfile(%this, %gui, %profileName, %profileTag)
 		error("ThemeManager::setProfile - Unable to find profile" SPC %profileName SPC "for theme" SPC %this.activeTheme.name @ "!");
 		error("ThemeManager::setProfile - Unable to find profile" SPC %profileName SPC "for theme" SPC %this.activeTheme.name @ "!");
 	}
 	}
 
 
-	%gui.setFieldValue(%profileTag, %this.activeTheme.getFieldValue(%profileName));
+	%gui.setEditFieldValue(%profileTag, %this.activeTheme.getFieldValue(%profileName));
 	%this.controlList.add(
 	%this.controlList.add(
 		new ScriptObject()
 		new ScriptObject()
 		{
 		{

+ 171 - 0
editor/EditorCore/Themes/TorqueSuit/TorqueSuitTheme.cs

@@ -432,3 +432,174 @@ function TorqueSuitTheme::makeConsoleProfile(%this)
 		fontColorNA = %this.color5; //Errors
 		fontColorNA = %this.color5; //Errors
 	};
 	};
 }
 }
+
+function TorqueSuitTheme::makeMenuProfile(%this)
+{
+	%menuBarBorder = new GuiBorderProfile()
+	{
+		padding = 2;
+	};
+
+	%this.menuBarProfile = new GuiControlProfile()
+	{
+		fillColor = %this.adjustValue(%this.color1, -7);
+		canKeyFocus = true;
+		borderDefault = %menuBarBorder;
+	};
+
+	%menuBorder = new GuiBorderProfile()
+	{
+		margin = 2;
+		marginHL = 0;
+		marginSL = 0;
+		marginNA = 2;
+
+		border = 0;
+		borderHL = 2;
+		borderSL = 2;
+		borderNA = 0;
+
+		borderColorHL = "255 255 255 30";
+		borderColorSL = %this.color5;
+	};
+
+	%menuBottomBorder = new GuiBorderProfile()
+	{
+		paddingSL = 2;
+
+		margin = 2;
+		marginHL = 0;
+		marginSL = 0;
+		marginNA = 2;
+
+		border = 0;
+		borderHL = 2;
+		borderSL = 2;
+		borderNA = 0;
+
+		borderColorHL = "255 255 255 30";
+		borderColorSL = %this.color5;
+	};
+
+	%menuSideBorder = new GuiBorderProfile()
+	{
+		border = 0;
+		borderHL = 2;
+		borderSL = 2;
+		borderNA = 0;
+
+		padding = 10;
+		paddingHL = 8;
+		paddingSL = 8;
+		paddingNA = 10;
+
+		borderColorHL = "255 255 255 30";
+		borderColorSL = %this.color5;
+	};
+
+	%this.menuProfile = new GuiControlProfile()
+	{
+		fillColor = "0 0 0 0";
+		fillColorHL = "255 255 255 10";
+		fillColorSL = %this.adjustValue(%this.color5, -15);
+		fillColorNA = "0 0 0 0";
+
+		borderDefault = %menuBorder;
+		borderLeft = %menuSideBorder;
+		borderRight = %menuSideBorder;
+		borderBottom = %menuBottomBorder;
+
+		fontType = %this.font[3];
+		fontDirectory = %this.fontDirectory;
+		fontSize = %this.fontSize;
+
+		fontColor = %this.color4;
+		fontColorHL = %this.adjustValue(%this.color4, 10);
+		fontColorSL = %this.color1;
+		fontColorNA = %this.adjustValue(%this.color4, 100);
+
+		canKeyFocus = true;
+	};
+
+	%menuContentVertBorder = new GuiBorderProfile()
+	{
+		border = 2;
+		padding = 4;
+		borderColor = %this.color5;
+	};
+
+	%menuContentSideBorder = new GuiBorderProfile()
+	{
+		border = 2;
+		padding = 0;
+		borderColor = %this.color5;
+	};
+
+	%this.menuContentProfile = new GuiControlProfile()
+	{
+		fillColor = %this.adjustValue(%this.color1, -5);
+
+		borderDefault = %menuContentSideBorder;
+		borderTop = %menuContentVertBorder;
+		borderBottom = %menuContentVertBorder;
+	};
+
+	%menuItemBorderTop = new GuiBorderProfile()
+	{
+		padding = 6;
+		paddingHL = 6;
+		paddingSL = 0;
+		paddingNA = 6;
+
+		marginSL = 4;
+		borderSL = 1;
+		borderColorSL = "0 0 0 50";
+	};
+
+	%menuItemBorderBottom = new GuiBorderProfile()
+	{
+		padding = 6;
+		paddingHL = 6;
+		paddingSL = 0;
+		paddingNA = 6;
+
+		marginSL = 4;
+		borderSL = 1;
+		borderColorSL = "255 255 255 50";
+	};
+
+	%menuItemBorderSide = new GuiBorderProfile()
+	{
+		padding = 6;
+		paddingHL = 6;
+		paddingSL = 0;
+		paddingNA = 6;
+
+		marginSL = 0;
+		borderSL = 0;
+		paddingSL = 6;
+	};
+
+	%this.menuItemProfile = new GuiControlProfile()
+	{
+		fillColor = %this.adjustValue(%this.color1, -5);
+		fillColorHL = %this.adjustValue(%this.color5, -15);
+		fillColorNA = %this.color1;
+		align = left;
+
+		tab = false;
+		canKeyFocus = true;
+
+		fontType = %this.font[3];
+		fontDirectory = %this.fontDirectory;
+		fontSize = %this.fontSize;
+
+		fontColor = %this.color4;
+		fontColorHL = %this.adjustValue(%this.color1, 10);
+		fontColorNA = %this.setAlpha(%this.color1, 150);
+
+		borderDefault = %menuItemBorderSide;
+		borderTop = %menuItemBorderTop;
+		borderBottom = %menuItemBorderBottom;
+	};
+}

+ 51 - 0
engine/compilers/VisualStudio 2017/GuiBlank.gui

@@ -0,0 +1,51 @@
+//--- Created With GUIEDITORTOY ---//
+%guiContent = new GuiControl(GuiBlank) {
+   Name = "GuiBlank";
+   canSaveDynamicFields = "0";
+   hidden = "0";
+   locked = "0";
+   isContainer = "1";
+   Profile = "GuiDefaultProfile";
+   HorizSizing = "width";
+   VertSizing = "height";
+   Position = "0 0";
+   Extent = "1920 1017";
+   MinExtent = "8 2";
+   canSave = "1";
+   Visible = "1";
+   Active = "0";
+   tooltipWidth = "250";
+   hovertime = "1000";
+
+   new GuiWindowCtrl() {
+      canSaveDynamicFields = "0";
+      hidden = "0";
+      locked = "0";
+      isContainer = "1";
+      Profile = "GuiWindowProfile";
+      HorizSizing = "right";
+      VertSizing = "bottom";
+      Position = "256 456";
+      Extent = "300 240";
+      MinExtent = "8 2";
+      canSave = "1";
+      Visible = "1";
+      Active = "1";
+      tooltipWidth = "250";
+      hovertime = "1000";
+      resizeWidth = "1";
+      resizeHeight = "1";
+      canMove = "1";
+      canClose = "1";
+      canMinimize = "1";
+      canMaximize = "1";
+      titleHeight = "20";
+      resizeRightWidth = "10";
+      resizeBottomHeight = "10";
+      contentProfile = "GuiWindowContentProfile";
+      closeButtonProfile = "GuiWindowCloseButtonProfile";
+      minButtonProfile = "GuiWindowMinButtonProfile";
+      maxButtonProfile = "GuiWindowMaxButtonProfile";
+   };
+};
+//--- GUIEDITORTOY END ---//

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

@@ -618,6 +618,7 @@
     <ClCompile Include="..\..\source\gui\containers\guiFrameCtrl.cc" />
     <ClCompile Include="..\..\source\gui\containers\guiFrameCtrl.cc" />
     <ClCompile Include="..\..\source\gui\containers\guiGridCtrl.cc" />
     <ClCompile Include="..\..\source\gui\containers\guiGridCtrl.cc" />
     <ClCompile Include="..\..\source\gui\containers\guiTabPageCtrl.cc" />
     <ClCompile Include="..\..\source\gui\containers\guiTabPageCtrl.cc" />
+    <ClCompile Include="..\..\source\gui\editor\guiMenuBarCtrl.cc" />
     <ClCompile Include="..\..\source\gui\guiArrayCtrl.cc" />
     <ClCompile Include="..\..\source\gui\guiArrayCtrl.cc" />
     <ClCompile Include="..\..\source\gui\guiBubbleTextCtrl.cc" />
     <ClCompile Include="..\..\source\gui\guiBubbleTextCtrl.cc" />
     <ClCompile Include="..\..\source\gui\guiCanvas.cc" />
     <ClCompile Include="..\..\source\gui\guiCanvas.cc" />
@@ -867,7 +868,6 @@
     <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\guiDragAndDropCtrl.cc" />
     <ClCompile Include="..\..\source\gui\containers\guiDragAndDropCtrl.cc" />
-    <ClCompile Include="..\..\source\gui\containers\guiFormCtrl.cc" />
     <ClCompile Include="..\..\source\gui\containers\guiPanelCtrl.cc" />
     <ClCompile Include="..\..\source\gui\containers\guiPanelCtrl.cc" />
     <ClCompile Include="..\..\source\gui\containers\guiRolloutCtrl.cc" />
     <ClCompile Include="..\..\source\gui\containers\guiRolloutCtrl.cc" />
     <ClCompile Include="..\..\source\gui\containers\guiScrollCtrl.cc" />
     <ClCompile Include="..\..\source\gui\containers\guiScrollCtrl.cc" />
@@ -880,7 +880,6 @@
     <ClCompile Include="..\..\source\gui\editor\guiGraphCtrl.cc" />
     <ClCompile Include="..\..\source\gui\editor\guiGraphCtrl.cc" />
     <ClCompile Include="..\..\source\gui\editor\guiInspector.cc" />
     <ClCompile Include="..\..\source\gui\editor\guiInspector.cc" />
     <ClCompile Include="..\..\source\gui\editor\guiInspectorTypes.cc" />
     <ClCompile Include="..\..\source\gui\editor\guiInspectorTypes.cc" />
-    <ClCompile Include="..\..\source\gui\editor\guiMenuBar.cc" />
     <ClCompile Include="..\..\source\testing\tests\platformFileIoTests.cc" />
     <ClCompile Include="..\..\source\testing\tests\platformFileIoTests.cc" />
     <ClCompile Include="..\..\source\testing\tests\platformMemoryTests.cc" />
     <ClCompile Include="..\..\source\testing\tests\platformMemoryTests.cc" />
     <ClCompile Include="..\..\source\testing\tests\platformStringTests.cc" />
     <ClCompile Include="..\..\source\testing\tests\platformStringTests.cc" />
@@ -1162,6 +1161,8 @@
     <ClInclude Include="..\..\source\gui\containers\guiTabBookCtrl_ScriptBinding.h" />
     <ClInclude Include="..\..\source\gui\containers\guiTabBookCtrl_ScriptBinding.h" />
     <ClInclude Include="..\..\source\gui\containers\guiTabPageCtrl.h" />
     <ClInclude Include="..\..\source\gui\containers\guiTabPageCtrl.h" />
     <ClInclude Include="..\..\source\gui\containers\guiWindowCtrl_ScriptBinding.h" />
     <ClInclude Include="..\..\source\gui\containers\guiWindowCtrl_ScriptBinding.h" />
+    <ClInclude Include="..\..\source\gui\editor\guiMenuBarCtrl.h" />
+    <ClInclude Include="..\..\source\gui\editor\guiMenuBarCtrl_ScriptBinding.h" />
     <ClInclude Include="..\..\source\gui\guiArrayCtrl.h" />
     <ClInclude Include="..\..\source\gui\guiArrayCtrl.h" />
     <ClInclude Include="..\..\source\gui\guiBubbleTextCtrl.h" />
     <ClInclude Include="..\..\source\gui\guiBubbleTextCtrl.h" />
     <ClInclude Include="..\..\source\gui\guiCanvas.h" />
     <ClInclude Include="..\..\source\gui\guiCanvas.h" />
@@ -1499,7 +1500,6 @@
     <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\guiDragAndDropCtrl.h" />
     <ClInclude Include="..\..\source\gui\containers\guiDragAndDropCtrl.h" />
-    <ClInclude Include="..\..\source\gui\containers\guiFormCtrl.h" />
     <ClInclude Include="..\..\source\gui\containers\guiPanelCtrl.h" />
     <ClInclude Include="..\..\source\gui\containers\guiPanelCtrl.h" />
     <ClInclude Include="..\..\source\gui\containers\guiRolloutCtrl.h" />
     <ClInclude Include="..\..\source\gui\containers\guiRolloutCtrl.h" />
     <ClInclude Include="..\..\source\gui\containers\guiScrollCtrl.h" />
     <ClInclude Include="..\..\source\gui\containers\guiScrollCtrl.h" />
@@ -1511,7 +1511,6 @@
     <ClInclude Include="..\..\source\gui\editor\guiGraphCtrl.h" />
     <ClInclude Include="..\..\source\gui\editor\guiGraphCtrl.h" />
     <ClInclude Include="..\..\source\gui\editor\guiInspector.h" />
     <ClInclude Include="..\..\source\gui\editor\guiInspector.h" />
     <ClInclude Include="..\..\source\gui\editor\guiInspectorTypes.h" />
     <ClInclude Include="..\..\source\gui\editor\guiInspectorTypes.h" />
-    <ClInclude Include="..\..\source\gui\editor\guiMenuBar.h" />
     <ClInclude Include="..\..\source\testing\unitTesting.h" />
     <ClInclude Include="..\..\source\testing\unitTesting.h" />
     <ClInclude Include="..\..\source\testing\unitTesting_ScriptBinding.h" />
     <ClInclude Include="..\..\source\testing\unitTesting_ScriptBinding.h" />
     <ClInclude Include="..\..\source\torqueConfig.h" />
     <ClInclude Include="..\..\source\torqueConfig.h" />

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

@@ -471,9 +471,6 @@
     <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\guiFormCtrl.cc">
-      <Filter>gui\containers</Filter>
-    </ClCompile>
     <ClCompile Include="..\..\source\gui\containers\guiRolloutCtrl.cc">
     <ClCompile Include="..\..\source\gui\containers\guiRolloutCtrl.cc">
       <Filter>gui\containers</Filter>
       <Filter>gui\containers</Filter>
     </ClCompile>
     </ClCompile>
@@ -507,9 +504,6 @@
     <ClCompile Include="..\..\source\gui\editor\guiInspectorTypes.cc">
     <ClCompile Include="..\..\source\gui\editor\guiInspectorTypes.cc">
       <Filter>gui\editor</Filter>
       <Filter>gui\editor</Filter>
     </ClCompile>
     </ClCompile>
-    <ClCompile Include="..\..\source\gui\editor\guiMenuBar.cc">
-      <Filter>gui\editor</Filter>
-    </ClCompile>
     <ClCompile Include="..\..\source\Box2D\Collision\b2BroadPhase.cpp">
     <ClCompile Include="..\..\source\Box2D\Collision\b2BroadPhase.cpp">
       <Filter>Box2D\Collision</Filter>
       <Filter>Box2D\Collision</Filter>
     </ClCompile>
     </ClCompile>
@@ -1486,6 +1480,9 @@
     <ClCompile Include="..\..\source\gui\buttons\guiDropDownCtrl.cc">
     <ClCompile Include="..\..\source\gui\buttons\guiDropDownCtrl.cc">
       <Filter>gui\buttons</Filter>
       <Filter>gui\buttons</Filter>
     </ClCompile>
     </ClCompile>
+    <ClCompile Include="..\..\source\gui\editor\guiMenuBarCtrl.cc">
+      <Filter>gui\editor</Filter>
+    </ClCompile>
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
     <ClInclude Include="..\..\source\audio\audio.h">
     <ClInclude Include="..\..\source\audio\audio.h">
@@ -1773,9 +1770,6 @@
     <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\guiFormCtrl.h">
-      <Filter>gui\containers</Filter>
-    </ClInclude>
     <ClInclude Include="..\..\source\gui\containers\guiRolloutCtrl.h">
     <ClInclude Include="..\..\source\gui\containers\guiRolloutCtrl.h">
       <Filter>gui\containers</Filter>
       <Filter>gui\containers</Filter>
     </ClInclude>
     </ClInclude>
@@ -1806,9 +1800,6 @@
     <ClInclude Include="..\..\source\gui\editor\guiInspectorTypes.h">
     <ClInclude Include="..\..\source\gui\editor\guiInspectorTypes.h">
       <Filter>gui\editor</Filter>
       <Filter>gui\editor</Filter>
     </ClInclude>
     </ClInclude>
-    <ClInclude Include="..\..\source\gui\editor\guiMenuBar.h">
-      <Filter>gui\editor</Filter>
-    </ClInclude>
     <ClInclude Include="..\..\source\Box2D\Box2D.h">
     <ClInclude Include="..\..\source\Box2D\Box2D.h">
       <Filter>Box2D</Filter>
       <Filter>Box2D</Filter>
     </ClInclude>
     </ClInclude>
@@ -3355,6 +3346,12 @@
     <ClInclude Include="..\..\source\gui\buttons\guiDropDownCtrl_ScriptBinding.h">
     <ClInclude Include="..\..\source\gui\buttons\guiDropDownCtrl_ScriptBinding.h">
       <Filter>gui\buttons</Filter>
       <Filter>gui\buttons</Filter>
     </ClInclude>
     </ClInclude>
+    <ClInclude Include="..\..\source\gui\editor\guiMenuBarCtrl.h">
+      <Filter>gui\editor</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\source\gui\editor\guiMenuBarCtrl_ScriptBinding.h">
+      <Filter>gui\editor</Filter>
+    </ClInclude>
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
     <ResourceCompile Include="Torque 2D.rc" />
     <ResourceCompile Include="Torque 2D.rc" />

+ 1 - 1
engine/source/gui/buttons/guiDropDownCtrl.cc

@@ -178,7 +178,7 @@ void GuiDropDownCtrl::onRender(Point2I offset, const RectI& updateRect)
 	if(mProfile->usesDefaultRendering(currentState))
 	if(mProfile->usesDefaultRendering(currentState))
 	{
 	{
 		RectI drawArea = RectI(contentRect.point.x + contentRect.extent.x - contentRect.extent.y, contentRect.point.y, contentRect.extent.y, contentRect.extent.y);
 		RectI drawArea = RectI(contentRect.point.x + contentRect.extent.x - contentRect.extent.y, contentRect.point.y, contentRect.extent.y, contentRect.extent.y);
-		renderTriangleIcon(drawArea, ColorI(mProfile->getFontColor(currentState)), false, 8);
+		renderTriangleIcon(drawArea, ColorI(mProfile->getFontColor(currentState)), GuiDirection::Down, 8);
 		contentRect.extent.x -= contentRect.extent.y;
 		contentRect.extent.x -= contentRect.extent.y;
 	}
 	}
 
 

+ 28 - 21
engine/source/gui/containers/guiChainCtrl.cc

@@ -94,6 +94,33 @@ void GuiChainCtrl::calculateExtent()
 {
 {
 	RectI innerRect = getInnerRect(mBounds.point.Zero, getExtent(), NormalState, mProfile);
 	RectI innerRect = getInnerRect(mBounds.point.Zero, getExtent(), NormalState, mProfile);
 
 
+	S32 length = positionChildren(innerRect);
+
+	if (!mIsVertical)
+	{
+		innerRect.extent.x = length;
+	}
+	else
+	{
+		innerRect.extent.y = length;
+	}
+
+	//call set update both before and after
+	setUpdate();
+
+	Point2I oldExtent = getExtent();
+	mBounds.extent = getOuterExtent(innerRect.extent, NormalState, mProfile);
+	GuiControl *parent = getParent();
+
+	if(oldExtent != getExtent() && parent)
+	{
+		parent->childResized(this);
+	}
+	setUpdate();
+}
+
+S32 GuiChainCtrl::positionChildren(RectI &innerRect)
+{
 	iterator i;
 	iterator i;
 	S32 length = 0;
 	S32 length = 0;
 	for (i = begin(); i != end(); i++)
 	for (i = begin(); i != end(); i++)
@@ -119,25 +146,5 @@ void GuiChainCtrl::calculateExtent()
 		}
 		}
 	}
 	}
 
 
-	if (!mIsVertical)
-	{
-		innerRect.extent.x = length;
-	}
-	else
-	{
-		innerRect.extent.y = length;
-	}
-
-	//call set update both before and after
-	setUpdate();
-
-	Point2I oldExtent = getExtent();
-	mBounds.extent = getOuterExtent(innerRect.extent, NormalState, mProfile);
-	GuiControl *parent = getParent();
-
-	if(oldExtent != getExtent() && parent)
-	{
-		parent->childResized(this);
-	}
-	setUpdate();
+	return length;
 }
 }

+ 4 - 1
engine/source/gui/containers/guiChainCtrl.h

@@ -17,10 +17,13 @@ class GuiChainCtrl : public GuiControl
 {
 {
 private:
 private:
 	typedef GuiControl Parent;
 	typedef GuiControl Parent;
+
+protected:
 	S32 mChildSpacing;
 	S32 mChildSpacing;
 	bool mIsVertical;
 	bool mIsVertical;
 
 
-	void calculateExtent();
+	virtual void calculateExtent();
+	virtual S32 positionChildren(RectI &innerRect);
 
 
 public:
 public:
 	GuiChainCtrl();
 	GuiChainCtrl();

+ 0 - 450
engine/source/gui/containers/guiFormCtrl.cc

@@ -1,450 +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/editor/guiMenuBar.h"
-#include "gui/containers/guiFormCtrl.h"
-#include "gui/guiDefaultControlRender.h"
-
-IMPLEMENT_CONOBJECT(GuiFormCtrl);
-
-ConsoleMethod(GuiFormCtrl, getMenuID, S32, 2, 2, "Returns the ID of the Form Menu")
-{
-   return object->getMenuBarID();
-}
-
-ConsoleMethod(GuiFormCtrl, setCaption, void, 3, 3, "setCaption(caption) - Sets the title of the Form Menu")
-{
-   object->setCaption(argv[2]);
-}
-
-GuiFormCtrl::GuiFormCtrl()
-{
-   mMinExtent.set(10, 10);
-   mActive        = true;
-   mMouseOver     = false;
-   mDepressed     = false;
-   mCanMove       = false;
-   mCaption = StringTable->insert("[none]");
-   mUseSmallCaption = false;
-   mSmallCaption = StringTable->EmptyString;
-
-   mContentLibrary = StringTable->EmptyString;
-   mContent = StringTable->EmptyString;
-
-   mCanSaveFieldDictionary = true;
-
-   mHasMenu = false;
-   
-   mIsContainer = true;
-
-   // The attached menu bar
-   mMenuBar = NULL;
-}
-
-GuiFormCtrl::~GuiFormCtrl()
-{
-   if(mMenuBar)
-   {
-      removeObject(mMenuBar);
-      //mMenuBar->deleteObject();
-   }
-}
-
-void GuiFormCtrl::initPersistFields()
-{
-
-   addField("Caption",       TypeString,  Offset(mCaption,     GuiFormCtrl));
-   addField("ContentLibrary",TypeString,  Offset(mContentLibrary, GuiFormCtrl));
-   addField("Content",       TypeString,  Offset(mContent, GuiFormCtrl));
-   addField("Movable",       TypeBool,  Offset(mCanMove, GuiFormCtrl));
-   addField("HasMenu",       TypeBool,  Offset(mHasMenu, GuiFormCtrl));
-
-   Parent::initPersistFields();
-
-
-}
-
-void GuiFormCtrl::setCaption(const char* caption)
-{
-   if(caption)
-   {
-      mCaption = StringTable->insert(caption, true);
-   }
-}
-
-bool GuiFormCtrl::onWake()
-{
-   if ( !Parent::onWake() )
-      return false;
-
-   mFont = mProfile->mFont;
-   AssertFatal(mFont, "GuiFormCtrl::onWake: invalid font in profile" );
-
-   mProfile->constructBitmapArray();
-
-   if(mProfile->mBitmapArrayRects.size())
-   {
-      mThumbSize.set(   mProfile->mBitmapArrayRects[0].extent.x, mProfile->mBitmapArrayRects[0].extent.y );
-      mThumbSize.setMax( mProfile->mBitmapArrayRects[1].extent );
-
-      if(mFont->getHeight() > (U32)mThumbSize.y)
-         mThumbSize.y = mFont->getHeight();
-   }
-   else
-   {
-      mThumbSize.set(20, 20);
-   }
-
-   return true;
-}
-
-
-void GuiFormCtrl::addObject(SimObject *newObj )
-{
-   if( ( mHasMenu && size() > 1) || (!mHasMenu && size() > 0 ) )
-   {
-      Con::warnf("GuiFormCtrl::addObject - Forms may only have one *direct* child - Placing on Parent!");
-      GuiControl *parent = getParent();
-      if( parent  )
-         parent->addObject( newObj );
-
-      return;
-   }
-   GuiControl *newCtrl = dynamic_cast<GuiControl*>( newObj );
-   GuiFormCtrl*formCtrl = dynamic_cast<GuiFormCtrl*>( newObj );
-   if( newCtrl && formCtrl )
-      newCtrl->setCanSave( true );
-   else if ( newCtrl )
-      newCtrl->setCanSave( false );
-
-   Parent::addObject( newObj );
-}
-
-void GuiFormCtrl::onSleep()
-{
-   Parent::onSleep();
-   mFont = NULL;
-}
-
-bool GuiFormCtrl::onAdd()
-{
-   if(!Parent::onAdd())
-      return false;
-
-   if( !mMenuBar && mHasMenu )
-   {
-      mMenuBar = new GuiMenuBar();
-      AssertFatal(mMenuBar, "GuiFormCtrl::onWake: cannot create form menu" );
-      if( mMenuBar )
-      {
-         mMenuBar->setField("profile","GuiFormMenuBarProfile");
-         mMenuBar->setField("horizSizing", "right");
-         mMenuBar->setField("vertSizing", "bottom");
-         mMenuBar->setField("extent", "16 16");
-         mMenuBar->setField("minExtent", "16 16");
-         mMenuBar->setField("position", "0 0");
-         mMenuBar->setField("class", "FormMenuBarClass"); // Give a generic class to the menu bar so that one set of functions may be used for all of them.
-
-         mMenuBar->registerObject();
-         mMenuBar->setProcessTicks(true); // Activate the processing of ticks to track if the mouse pointer has been hovering within the menu
-         addObject(mMenuBar); // Add the menu bar to the form
-      }
-   }
-
-   return true;
-}
-
-U32 GuiFormCtrl::getMenuBarID()
-{
-   if(mMenuBar)
-   {
-      return mMenuBar->getId();
-   }
-
-   return 0;
-}
-
-void GuiFormCtrl::resize(const Point2I &newPosition, const Point2I &newExtent)
-{
-   Parent::resize(newPosition, newExtent);
-
-   if( !mAwake || !mProfile->mBitmapArrayRects.size() )
-      return;
-
-   // Should the caption be modified because the title bar is too small?
-   S32 textWidth = mProfile->mFont->getStrWidth(mCaption);
-   S32 newTextArea = mBounds.extent.x - mThumbSize.x - mProfile->mBitmapArrayRects[4].extent.x;
-   if(newTextArea < textWidth)
-   {
-      static char buf[256];
-
-      mUseSmallCaption = true;
-      mSmallCaption = StringTable->EmptyString;
-
-      S32 strlen = dStrlen((const char*)mCaption);
-      for(S32 i=strlen; i>=0; --i)
-      {
-         dStrcpy(buf, "");
-         dStrncat(buf, (const char*)mCaption, i);
-         dStrcat(buf, "...");
-
-         textWidth = mProfile->mFont->getStrWidth(buf);
-
-         if(textWidth < newTextArea)
-         {
-            mSmallCaption = StringTable->insert(buf, true);
-            break;
-         }
-      }
-
-   } else
-   {
-      mUseSmallCaption = false;
-   }
-
-   Con::executef(this, 1, "onResize");
-
-}
-
-void GuiFormCtrl::onRender(Point2I offset, const RectI &updateRect)
-{
-   // Fill in the control's child area
-   RectI boundsRect(offset, mBounds.extent);
-   boundsRect.point.y += mThumbSize.y;
-   boundsRect.extent.y -= mThumbSize.y;
-
-   // draw the border of the form if specified
-   dglDrawRectFill(boundsRect, mProfile->mFillColor);
-
-   //if (mProfile->mBorder)
-      //renderBorder(boundsRect, mProfile);
-
-   // If we don't have a child (other than the menu), put some text in the child area
-   if(size() <= 1)
-   {
-      dglSetBitmapModulation(ColorI(0,0,0));
-      renderText(boundsRect.point, boundsRect.extent, "[none]", mProfile);
-   }
-
-   S32 textWidth = 0;
-
-   // Draw our little bar, too
-   if(mProfile->mBitmapArrayRects.size() >= 5)
-   {
-      dglClearBitmapModulation();
-
-      S32 barStart = 0;//(mHasMenu ? mThumbSize.x : 1 + mProfile->mBorderSize) + offset.x + textWidth;
-      S32 barTop   = mThumbSize.y/2 + offset.y - mProfile->mBitmapArrayRects[3].extent.y /2;
-
-      Point2I barOffset(barStart, barTop);
-
-      // Draw the start of the bar...
-      dglDrawBitmapStretchSR(mProfile->mTextureHandle,RectI(barOffset, mProfile->mBitmapArrayRects[2].extent), mProfile->mBitmapArrayRects[2] );
-
-      // Now draw the middle...
-      barOffset.x += mProfile->mBitmapArrayRects[2].extent.x;
-
-      S32 barMiddleSize = (getExtent().x - (barOffset.x - offset.x)) - mProfile->mBitmapArrayRects[4].extent.x;
-
-      if(barMiddleSize>0)
-      {
-         // We have to do this inset to prevent nasty stretching artifacts
-         RectI foo = mProfile->mBitmapArrayRects[3];
-         foo.inset(1,0);
-
-         dglDrawBitmapStretchSR(
-            mProfile->mTextureHandle,
-            RectI(barOffset, Point2I(barMiddleSize, mProfile->mBitmapArrayRects[3].extent.y)),
-            foo
-            );
-      }
-
-      // And the end
-      barOffset.x += barMiddleSize;
-
-      dglDrawBitmapStretchSR( mProfile->mTextureHandle, RectI(barOffset, mProfile->mBitmapArrayRects[4].extent),
-         mProfile->mBitmapArrayRects[4]);
-
-      dglSetBitmapModulation((mMouseOver ? mProfile->mFontColorHL : mProfile->mFontColor));
-      renderText(Point2I(mThumbSize.x, 0) + offset, Point2I(mBounds.extent.x - mThumbSize.x - mProfile->mBitmapArrayRects[4].extent.x, mThumbSize.y), (mUseSmallCaption ? mSmallCaption : mCaption), mProfile);
-
-   }
-
-   // Render the children
-   renderChildControls(offset, mBounds, updateRect);
-}
-
-void GuiFormCtrl::onTouchDragged(const GuiEvent &event)
-{
-   GuiControl *parent = getParent();
-   GuiCanvas *root = getRoot();
-   if (! root) return;
-
-   Point2I deltaMousePosition = event.mousePoint - mMouseDownPosition;
-
-   Point2I newPosition = mBounds.point;
-   Point2I newExtent = mBounds.extent;
-   if (mMouseMovingWin && parent)
-   {
-      newPosition.x = getMax(0, getMin(parent->mBounds.extent.x - mBounds.extent.x, mOrigBounds.point.x + deltaMousePosition.x));
-      newPosition.y = getMax(0, getMin(parent->mBounds.extent.y - mBounds.extent.y, mOrigBounds.point.y + deltaMousePosition.y));
-      Point2I pos = parent->localToGlobalCoord(mBounds.point);
-      root->addUpdateRegion(pos, mBounds.extent);
-      resize(newPosition, newExtent);
-
-   }
-}
-
-
-void GuiFormCtrl::onTouchMove(const GuiEvent &event)
-{
-   Point2I localMove = globalToLocalCoord(event.mousePoint);
-
-   // If we're clicking in the header then resize
-   mMouseOver = (localMove.y < mThumbSize.y);
-   if(isMouseLocked())
-      mDepressed = mMouseOver;
-
-}
-
-void GuiFormCtrl::onTouchEnter(const GuiEvent &event)
-{
-   setUpdate();
-   if(isMouseLocked())
-   {
-      mDepressed = true;
-      mMouseOver = true;
-   }
-   else
-   {
-      mMouseOver = true;
-   }
-
-}
-
-void GuiFormCtrl::onTouchLeave(const GuiEvent &event)
-{
-   setUpdate();
-   if(isMouseLocked())
-      mDepressed = false;
-   mMouseOver = false;
-}
-
-void GuiFormCtrl::onTouchDown(const GuiEvent &event)
-{
-   Point2I localClick = globalToLocalCoord(event.mousePoint);
-
-   // If we're clicking in the header then resize
-   if(localClick.y < mThumbSize.y)
-   {
-      mouseLock();
-      mDepressed = true;
-      mMouseMovingWin = mCanMove;
-
-      //update
-      setUpdate();
-   }
-
-   mOrigBounds = mBounds;
-
-   mMouseDownPosition = event.mousePoint;
-
-   ////if we clicked within the title bar
-   //if (localPoint.y < mTitleHeight)
-   //{
-   //   //if we clicked on the close button
-   //   if (mCanClose && mCloseButton.pointInRect(localPoint))
-   //   {
-   //      mPressClose = mCanClose;
-   //   }
-   //   else if (mCanMaximize && mMaximizeButton.pointInRect(localPoint))
-   //   {
-   //      mPressMaximize = mCanMaximize;
-   //   }
-   //   else if (mCanMinimize && mMinimizeButton.pointInRect(localPoint))
-   //   {
-   //      mPressMinimize = mCanMinimize;
-   //   }
-
-   //   //else we clicked within the title
-   //   else
-   //   {
-   //      mMouseMovingWin = mCanMove;
-   //      mMouseResizeWidth = false;
-   //      mMouseResizeHeight = false;
-   //   }
-   //}
-   //else
-   //{
-   //   mMouseMovingWin = false;
-
-   //   //see if we clicked on the right edge
-   //   if (mResizeWidth && (localPoint.x > mBounds.extent.x - mResizeRightWidth))
-   //   {
-   //      mMouseResizeWidth = true;
-   //   }
-
-   //   //see if we clicked on the bottom edge (as well)
-   //   if (mResizeHeight && (localPoint.y > mBounds.extent.y - mResizeBottomHeight))
-   //   {
-   //      mMouseResizeHeight = true;
-   //   }
-   //}
-
-
-   if (mMouseMovingWin )//|| mMouseResizeWidth || mMouseResizeHeight ||
-      //mPressClose || mPressMaximize || mPressMinimize)
-   {
-      mouseLock();
-   }
-   else
-   {
-
-      GuiControl *ctrl = findHitControl(localClick);
-      if (ctrl && ctrl != this)
-         ctrl->onTouchDown(event);
-
-   }
-
-}
-
-void GuiFormCtrl::onTouchUp(const GuiEvent &event)
-{
-   // Make sure we only get events we ought to be getting...
-   if (! mActive)
-      return; 
-
-   mouseUnlock();
-   setUpdate();
-
-   //mMouseMovingWin = false;
-   //mMouseResizeWidth = false;
-   //mMouseResizeHeight = false;
-
-
-   //Point2I localClick = globalToLocalCoord(event.mousePoint);
-
-   // If we're clicking in the header then resize
-   //if(localClick.y < mThumbSize.y && mDepressed)
-   //   setCollapsed(!mCollapsed);
-}
-

+ 0 - 113
engine/source/gui/containers/guiFormCtrl.h

@@ -1,113 +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 _GUIFORMCTRL_H_
-#define _GUIFORMCTRL_H_
-
-#ifndef _GUICONTROL_H_
-#include "gui/guiControl.h"
-#endif
-
-#ifndef _GUICANVAS_H_
-#include "gui/guiCanvas.h"
-#endif
-
-#include "graphics/dgl.h"
-#include "console/console.h"
-#include "console/consoleTypes.h"
-
-class GuiMenuBar;
-
-/// Collapsable pane control.
-///
-/// This class wraps a single child control and displays a header with caption
-/// above it. If you click the header it will collapse or expand. The control
-/// resizes itself based on its collapsed/expanded size.
-///
-/// In the GUI editor, if you just want the header you can make collapsable 
-/// false. The caption field lets you set the caption. It expects a bitmap
-/// (from the GuiControlProfile) that contains two images - the first is
-/// displayed when the control is expanded and the second is displayed when
-/// it is collapsed. The header is sized based off of the first image.
-class GuiFormCtrl : public GuiControl
-{
-private:
-   typedef GuiControl Parent;
-
-   Resource<GFont>  mFont;
-   StringTableEntry mCaption;
-   bool             mCanMove;
-   bool             mUseSmallCaption;
-   StringTableEntry mSmallCaption;
-   StringTableEntry mContentLibrary;
-   StringTableEntry mContent;
-
-   Point2I          mThumbSize;
-   bool             mHasMenu;
-
-   GuiMenuBar*      mMenuBar;
-
-   bool mMouseMovingWin;
-
-   Point2I mMouseDownPosition;
-   RectI mOrigBounds;
-   RectI mStandardBounds;
-
-   RectI mCloseButton;
-   RectI mMinimizeButton;
-   RectI mMaximizeButton;
-
-   bool mMouseOver;
-   bool mDepressed;
-
-public:
-   GuiFormCtrl();
-   virtual ~GuiFormCtrl();
-
-   void setCaption(const char* caption);
-
-   void resize(const Point2I &newPosition, const Point2I &newExtent);
-   void onRender(Point2I offset, const RectI &updateRect);
-
-   // DAW: Called when the GUI theme changes and a bitmap arrary may need updating
-  // void onThemeChange();
-
-   U32  getMenuBarID();
-
-   bool onAdd();
-   bool onWake();
-   void onSleep();
-
-   virtual void addObject(SimObject *newObj );
-
-   void onTouchDragged(const GuiEvent &event);
-   void onTouchDown(const GuiEvent &event);
-   void onTouchUp(const GuiEvent &event);
-   void onTouchMove(const GuiEvent &event);
-   void onTouchLeave(const GuiEvent &event);
-   void onTouchEnter(const GuiEvent &event);
-
-   static void initPersistFields();
-   DECLARE_CONOBJECT(GuiFormCtrl);
-};
-
-#endif

+ 0 - 4
engine/source/gui/containers/guiTabBookCtrl.h

@@ -143,10 +143,6 @@ private:
    /// @param   tabRect   the rectangle to render the tab into
    /// @param   tabRect   the rectangle to render the tab into
    /// @param   tab   pointer to the tab page control for which to render the tab
    /// @param   tab   pointer to the tab page control for which to render the tab
    void renderTab( RectI tabRect, GuiTabPageCtrl* tab );
    void renderTab( RectI tabRect, GuiTabPageCtrl* tab );
-
-   void renderJustifiedTextRot(Point2I offset, Point2I extent, const char *text, F32 rot );
-
-
    /// @}
    /// @}
 
 
    /// @name Page Management
    /// @name Page Management

+ 1 - 1
engine/source/gui/containers/guiWindowCtrl.cc

@@ -636,7 +636,7 @@ void GuiWindowCtrl::onRender(Point2I offset, const RectI &updateRect)
 	//Does this window have focus (does it or a child receive key events)?
 	//Does this window have focus (does it or a child receive key events)?
 	GuiCanvas *root = getRoot();
 	GuiCanvas *root = getRoot();
 	GuiControl *firstResponder = root ? root->getFirstResponder() : NULL;
 	GuiControl *firstResponder = root ? root->getFirstResponder() : NULL;
-	bool hasFocus = (!firstResponder || ControlIsChild(firstResponder));
+	bool hasFocus = (firstResponder && ControlIsChild(firstResponder));
 
 
 	GuiControlState currentState = NormalState;
 	GuiControlState currentState = NormalState;
 	if (mMinimized)
 	if (mMinimized)

+ 0 - 4
engine/source/gui/containers/guiWindowCtrl.h

@@ -23,10 +23,6 @@
 #ifndef _GUIWINDOWCTRL_H_
 #ifndef _GUIWINDOWCTRL_H_
 #define _GUIWINDOWCTRL_H_
 #define _GUIWINDOWCTRL_H_
 
 
-#ifndef _GUITEXTCTRL_H_
-#include "gui/guiTextCtrl.h"
-#endif
-
 /// @addtogroup gui_container_group Containers
 /// @addtogroup gui_container_group Containers
 ///
 ///
 /// @ingroup gui_group Gui System
 /// @ingroup gui_group Gui System

+ 0 - 1679
engine/source/gui/editor/guiMenuBar.cc

@@ -1,1679 +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 "console/consoleTypes.h"
-#include "console/console.h"
-#include "graphics/dgl.h"
-#include "gui/guiCanvas.h"
-#include "gui/guiDefaultControlRender.h"
-#include "gui/guiTextListCtrl.h"
-#include "input/actionMap.h"
-#include "gui/editor/guiMenuBar.h"
-
-// menu bar:
-// basic idea - fixed height control bar at the top of a window, placed and sized in gui editor
-// menu text for menus or menu items should not begin with a digit
-// all menus can be removed via the clearMenus() console command
-// each menu is added via the addMenu(menuText, menuId) console command
-// each menu is added with a menu id
-// menu items are added to menus via that addMenuItem(menu, menuItemText, menuItemId, accelerator, checkGroup) console command
-// each menu item is added with a menu item id and an optional accelerator
-// menu items are initially enabled, but can be disabled/re-enabled via the setMenuItemEnable(menu,menuItem,bool)
-// menu text can be set via the setMenuText(menu, newMenuText) console method
-// menu item text can be set via the setMenuItemText console method
-// menu items can be removed via the removeMenuItem(menu, menuItem) console command
-// menu items can be cleared via the clearMenuItems(menu) console command
-// menus can be hidden or shown via the setMenuVisible(menu, bool) console command
-// menu items can be hidden or shown via the setMenuItemVisible(menu, menuItem, bool) console command
-// menu items can be check'd via the setMenuItemChecked(menu, menuItem, bool) console command
-//    if the bool is true, any other items in that menu item's check group become unchecked.
-//
-// menu items can have a bitmap set on them via the setMenuItemBitmap(menu, menuItem, bitmapIndex)
-//    passing -1 for the bitmap index will result in no bitmap being shown
-//    the index paramater is an index into the bitmap array of the associated profile
-//    this can be used, for example, to display a check next to a selected menu item
-//    bitmap indices are actually multiplied by 3 when indexing into the bitmap
-//    since bitmaps have normal, selected and disabled states.
-//
-// menus can be removed via the removeMenu console command
-// specification arguments for menus and menu items can be either the id or the text of the menu or menu item
-// adding the menu item "-" will add an un-selectable seperator to the menu
-// callbacks:
-// when a menu is clicked, before it is displayed, the menu calls its onMenuSelect(menuId, menuText) method -
-//    this allows the callback to enable/disable menu items, or add menu items in a context-sensitive way
-// when a menu item is clicked, the menu removes itself from display, then calls onMenuItemSelect(menuId, menuText, menuItemId, menuItemText)
-
-// the initial implementation does not support:
-//    hierarchal menus
-//    keyboard accelerators on menu text (i.e. via alt-key combos)
-
-//------------------------------------------------------------------------------
-
-IMPLEMENT_CONOBJECT(GuiMenuBar);
-
-//------------------------------------------------------------------------------
-// console methods
-//------------------------------------------------------------------------------
-
-ConsoleMethod(GuiMenuBar, clearMenus, void, 2, 2, "() Clears all menus and sub-menus from the menu bar.\n"
-                                                                "@return No return value")
-{
-   object->clearMenus();
-}
-
-ConsoleMethod(GuiMenuBar, setMenuMargins, void, 5, 5, "(S32 horizontalMargin, S32 verticalMargin, S32 bitmapToTextSpacing) Sets the menu rendering margins: horizontal, vertical, bitmap spacing.")
-{
-   object->mHorizontalMargin = dAtoi(argv[2]);
-   object->mVerticalMargin = dAtoi(argv[3]);
-   object->mBitmapMargin = dAtoi(argv[4]);
-}
-
-ConsoleMethod(GuiMenuBar, addMenu, void, 4, 4, "( menuName , menuID ) Adds a new menu to the menu bar.\n"
-                                                                "@param menuName The text (name) of the new menu entry.\n"
-                                                                "@param menuID The ID of the new menu entry.\n"
-                                                                "@return No return value")
-{
-   if(dIsdigit(argv[2][0]))
-   {
-      Con::errorf("Cannot add menu %s (id = %s).  First character of a menu's text cannot be a digit.", argv[2], argv[3]);
-      return;
-   }
-   object->addMenu(argv[2], dAtoi(argv[3]));
-}
-
-ConsoleMethod(GuiMenuBar, addMenuItem, void, 5, 7, "( menuID | menuName , menuItemName , menuItemID , [ accelerator ] , [ checkGroup ] ) Adds a sub-menu entry to the specified menu.\n"
-                                                                "@param menuID The ID of the menu.\n"
-                                                                "@param menuName The text (name) of the menu.\n"
-                                                                "@param menuItemID The ID of the menu item.\n"
-                                                                "@param menuItemName The text (name) of the menu item.\n"
-                                                                "@param accelerator A boolean value. If set to true, the sub-menu entry is checked, otherwise it is unchecked.\n"
-                                                                "@param checkGroup The check group this item should belong to, if any.\n"
-                                                                "@return No return value")
-{
-   if(dIsdigit(argv[3][0]))
-   {
-      Con::errorf("Cannot add menu item %s (id = %s).  First character of a menu item's text cannot be a digit.", argv[3], argv[4]);
-      return;
-   }
-   GuiMenuBar::Menu *menu = object->findMenu(argv[2]);
-   if(!menu)
-   {
-      Con::errorf("Cannot find menu %s for addMenuItem.", argv[2]);
-      return;
-   }
-   object->addMenuItem(menu, argv[3], dAtoi(argv[4]), argc == 5 ? "" : argv[5], argc < 7 ? -1 : dAtoi(argv[6]));
-}
-
-ConsoleMethod(GuiMenuBar, setMenuItemEnable, void, 5, 5, "( menuID | menuName , menuItemID | menuItemName , enabled ) Sets the menu item to enabled or disabled.\n"
-                                                                "@param menuID The ID of the menu.\n"
-                                                                "@param menuName The text (name) of the menu.\n"
-                                                                "@param menuItemID The ID of the menu item.\n"
-                                                                "@param menuItemName The text (name) of the menu item.\n"
-                                                                "@param enabled A boolean value. If set to true, the sub-menu entry is enabled, otherwise it is disabled.\n"
-                                                                "@return No return value")
-{
-   GuiMenuBar::Menu *menu = object->findMenu(argv[2]);
-   if(!menu)
-   {
-      Con::errorf("Cannot find menu %s for setMenuItemEnable.", argv[2]);
-      return;
-   }
-   GuiMenuBar::MenuItem *menuItem = object->findMenuItem(menu, argv[3]);
-   if(!menuItem)
-   {
-      Con::errorf("Cannot find menu item %s for setMenuItemEnable.", argv[3]);
-      return;
-   }
-   menuItem->enabled = dAtob(argv[4]);
-}
-
-ConsoleMethod(GuiMenuBar, setCheckmarkBitmapIndex, void, 3, 3, "(S32 bitmapindex) - sets the menu bitmap index for the check mark image.\n"
-              "@return No Return Value.")
-{
-   object->mCheckmarkBitmapIndex = dAtoi(argv[2]);
-}
-
-ConsoleMethod(GuiMenuBar, setMenuItemChecked, void, 5, 5, "( menuID | menuName , menuItemID | menuItemName , checked ) Sets the menu item bitmap to a check mark, which must be the first element in the bitmap array. Any other menu items in the menu with the same check group become unchecked if they are checked.\n"
-                                                                "@param menuID The ID of the menu.\n"
-                                                                "@param menuName The text (name) of the menu.\n"
-                                                                "@param menuItemID The ID of the menu item.\n"
-                                                                "@param menuItemName The text (name) of the menu item.\n"
-                                                                "@param checked A boolean value. If set to true, the sub-menu entry is checked, otherwise it is unchecked.\n"
-                                                                "@return No return value")
-{
-   GuiMenuBar::Menu *menu = object->findMenu(argv[2]);
-   if(!menu)
-   {
-      Con::errorf("Cannot find menu %s for setMenuItemChecked.", argv[2]);
-      return;
-   }
-   GuiMenuBar::MenuItem *menuItem = object->findMenuItem(menu, argv[3]);
-   if(!menuItem)
-   {
-      Con::errorf("Cannot find menu item %s for setMenuItemChecked.", argv[3]);
-      return;
-   }
-   bool checked = dAtob(argv[4]);
-   if(checked && menuItem->checkGroup != -1)
-   {
-      // first, uncheck everything in the group:
-      for(GuiMenuBar::MenuItem *itemWalk = menu->firstMenuItem; itemWalk; itemWalk = itemWalk->nextMenuItem)
-         if(itemWalk->checkGroup == menuItem->checkGroup && itemWalk->bitmapIndex == object->mCheckmarkBitmapIndex)
-            itemWalk->bitmapIndex = -1;
-   }
-   menuItem->bitmapIndex = checked ? object->mCheckmarkBitmapIndex : -1;
-}
-
-ConsoleMethod(GuiMenuBar, setMenuText, void, 4, 4, "( menuID | menuName , newMenuText ) Sets the text of the specified menu to the new string.\n"
-                                                                "@param menuID The ID of the menu.\n"
-                                                                "@param menuName The text (name) of the menu.\n"
-                                                                "@param newMenuText The new text to give the menu entry.\n"
-                                                                "@return No return value")
-{
-   if(dIsdigit(argv[3][0]))
-   {
-      Con::errorf("Cannot name menu %s to %s.  First character of a menu's text cannot be a digit.", argv[2], argv[3]);
-      return;
-   }
-   GuiMenuBar::Menu *menu = object->findMenu(argv[2]);
-   if(!menu)
-   {
-      Con::errorf("Cannot find menu %s for setMenuText.", argv[2]);
-      return;
-   }
-   dFree(menu->text);
-   menu->text = dStrdup(argv[3]);
-   object->menuBarDirty = true;
-}
-ConsoleMethod(GuiMenuBar, setMenuBitmapIndex, void, 6, 6, "(string menu, S32 bitmapindex, bool bitmaponly, bool drawborder) Sets the bitmap index for the menu and toggles rendering only the bitmap.\n"
-              "@return No return value.")
-{
-   GuiMenuBar::Menu *menu = object->findMenu(argv[2]);
-   if(!menu)
-   {
-      Con::errorf("Cannot find menu %s for setMenuBitmapIndex.", argv[2]);
-      return;
-   }
-
-   menu->bitmapIndex = dAtoi(argv[3]);
-   menu->drawBitmapOnly = dAtob(argv[4]);
-   menu->drawBorder = dAtob(argv[5]);
-
-   object->menuBarDirty = true;
-}
-
-ConsoleMethod(GuiMenuBar, setMenuVisible, void, 4, 4, "( menuID | menuName , visible ) Use the setMenuVisible method to enable or disable the visibility of a specific menu entry.\n"
-                                                                "@param menuID The ID of the menu.\n"
-                                                                "@param menuName The text (name) of the menu.\n"
-                                                                "@param visible A boolean value. If set to true, this menu entry will be shown, otherwise it will be hidden.\n"
-                                                                "@return No return value")
-{
-   GuiMenuBar::Menu *menu = object->findMenu(argv[2]);
-   if(!menu)
-   {
-      Con::errorf("Cannot find menu %s for setMenuVisible.", argv[2]);
-      return;
-   }
-   menu->visible = dAtob(argv[3]);
-   object->menuBarDirty = true;
-   object->setUpdate();
-}
-
-ConsoleMethod(GuiMenuBar, setMenuItemText, void, 5, 5, "( menuID | menuName , menuItemID | menuItemName , newMenuItemText ) Sets the text of the specified menu item to the new string.\n"
-                                                                "@param menuID The ID of the menu.\n"
-                                                                "@param menuName The text (name) of the menu.\n"
-                                                                "@param menuItemID The ID of the menu item.\n"
-                                                                "@param menuItemName The text (name) of the menu item.\n"
-                                                                "@param newMenuItemText The new text for the specified sub-menu entry.\n"
-                                                                "@return No return value")
-{
-   if(dIsdigit(argv[4][0]))
-   {
-      Con::errorf("Cannot name menu item %s to %s.  First character of a menu item's text cannot be a digit.", argv[3], argv[4]);
-      return;
-   }
-   GuiMenuBar::Menu *menu = object->findMenu(argv[2]);
-   if(!menu)
-   {
-      Con::errorf("Cannot find menu %s for setMenuItemText.", argv[2]);
-      return;
-   }
-   GuiMenuBar::MenuItem *menuItem = object->findMenuItem(menu, argv[3]);
-   if(!menuItem)
-   {
-      Con::errorf("Cannot find menu item %s for setMenuItemText.", argv[3]);
-      return;
-   }
-   dFree(menuItem->text);
-   menuItem->text = dStrdup(argv[4]);
-}
-
-ConsoleMethod(GuiMenuBar, setMenuItemVisible, void, 5, 5, "( menuID | menuName, menuItemID | menuItemName, visible ) Use the setMenuItemVisible method to enable or disable the visibility of a specific sub-menu entry.\n"
-                                                                "@param menuID The ID of the menu.\n"
-                                                                "@param menuName The text (name) of the menu.\n"
-                                                                "@param menuItemID The ID of the menu item.\n"
-                                                                "@param menuItemName The text (name) of the menu item.\n"
-                                                                "@param visible A boolean value. If set to true, this sub-menu entry will be shown, otherwise it will be hidden.\n"
-                                                                "@return No return value")
-{
-   GuiMenuBar::Menu *menu = object->findMenu(argv[2]);
-   if(!menu)
-   {
-      Con::errorf("Cannot find menu %s for setMenuItemVisible.", argv[2]);
-      return;
-   }
-   GuiMenuBar::MenuItem *menuItem = object->findMenuItem(menu, argv[3]);
-   if(!menuItem)
-   {
-      Con::errorf("Cannot find menu item %s for setMenuItemVisible.", argv[3]);
-      return;
-   }
-   menuItem->visible = dAtob(argv[4]);
-}
-
-ConsoleMethod(GuiMenuBar, setMenuItemBitmap, void, 5, 5, "( menuID | menuName , menuItemID | menuItemName , bitmapIndex ) Sets the specified menu item bitmap index in the bitmap array. Setting the item's index to -1 will remove any bitmap.\n"
-                                                                "@param menuID The ID of the menu.\n"
-                                                                "@param menuName The text (name) of the menu.\n"
-                                                                "@param menuItemID The ID of the menu item.\n"
-                                                                "@param menuItemName The text (name) of the menu item.\n"
-                                                                "@param bitMapIndex An integer value specifying the row of bitmap entries to use for sub-menu entry.\n"
-                                                                "@return No return value")
-{
-   GuiMenuBar::Menu *menu = object->findMenu(argv[2]);
-   if(!menu)
-   {
-      Con::errorf("Cannot find menu %s for setMenuItemBitmap.", argv[2]);
-      return;
-   }
-   GuiMenuBar::MenuItem *menuItem = object->findMenuItem(menu, argv[3]);
-   if(!menuItem)
-   {
-      Con::errorf("Cannot find menu item %s for setMenuItemBitmap.", argv[3]);
-      return;
-   }
-   menuItem->bitmapIndex = dAtoi(argv[4]);
-}
-
-ConsoleMethod(GuiMenuBar, removeMenuItem, void, 4, 4, "( menuID | menuName , menuItemID | menuItemName ) Removes the specified menu item from the menu.\n"
-                                                                "@param menuID The ID of the menu.\n"
-                                                                "@param menuName The text (name) of the menu.\n"
-                                                                "@param menuItemID The ID of the menu item.\n"
-                                                                "@param menuItemName The text (name) of the menu item.\n"
-                                                                "@return No return value")
-{
-   GuiMenuBar::Menu *menu = object->findMenu(argv[2]);
-   if(!menu)
-   {
-      Con::errorf("Cannot find menu %s for removeMenuItem.", argv[2]);
-      return;
-   }
-   GuiMenuBar::MenuItem *menuItem = object->findMenuItem(menu, argv[3]);
-   if(!menuItem)
-   {
-      Con::errorf("Cannot find menu item %s for removeMenuItem.", argv[3]);
-      return;
-   }
-   object->removeMenuItem(menu, menuItem);
-}
-
-ConsoleMethod(GuiMenuBar, clearMenuItems, void, 3, 3, "( menuID | menuName ) Removes all the sub-menu items from the specified menu.\n"
-                                                                "@param menuID The ID of the menu.\n"
-                                                                "@param menuName The text (name) of the menu.\n"
-                                                                "@return No return value")
-{
-   GuiMenuBar::Menu *menu = object->findMenu(argv[2]);
-   if(!menu)
-   {
-      //Con::errorf("Cannot find menu %s for clearMenuItems.", argv[2]);
-      return;
-   }
-   object->clearMenuItems(menu);
-}
-
-ConsoleMethod(GuiMenuBar, removeMenu, void, 3, 3, "( menuID | menuName ) Removes the specified menu from the menu bar.\n"
-                                                                "@param menuID The ID of the menu.\n"
-                                                                "@param menuName The text (name) of the menu.\n"
-                                                                "@param menuItemID The ID of the menu item.\n"
-                                                                "@param menuItemName The text (name) of the menu item.\n"
-                                                                "@param checked A boolean value. If set to true, the sub-menu entry is checked, otherwise it is unchecked.\n"
-                                                                "@return No return value")
-{
-   GuiMenuBar::Menu *menu = object->findMenu(argv[2]);
-   if(!menu)
-   {
-      //Con::errorf("Cannot find menu %s for removeMenu.", argv[2]);
-      return;
-   }
-   object->clearMenuItems(menu);
-   object->menuBarDirty = true;
-}
-
-//------------------------------------------------------------------------------
-// DAW: Submenu console methods
-//------------------------------------------------------------------------------
-
-ConsoleMethod(GuiMenuBar, setMenuItemSubmenuState, void, 5, 5, "(string menu, string menuItem, bool isSubmenu) Sets the given menu item to be a submenu\n"
-              "@param menu The menu where the sub menu is located.\n"
-              "@param menuItem The menu item to set as a sub menu.\n"
-              "@param inSubmenu A boolean value signifying whether or not it is a submenu.\n"
-              "@return No return value.")
-{
-
-   GuiMenuBar::Menu *menu = object->findMenu(argv[2]);
-   if(!menu)
-   {
-      Con::errorf("Cannot find menu %s for setMenuItemSubmenuState.", argv[2]);
-      return;
-   }
-
-   GuiMenuBar::MenuItem *menuitem = object->findMenuItem(menu, argv[3]);
-   if(!menuitem)
-   {
-      Con::errorf("Cannot find menuitem %s for setMenuItemSubmenuState.", argv[3]);
-      return;
-   }
-
-   menuitem->isSubmenu = dAtob(argv[4]);
-}
-
-ConsoleMethod(GuiMenuBar, addSubmenuItem, void, 6, 8, "(string menu, string menuItem, string submenuItemText, int submenuItemId, string accelerator = NULL, int checkGroup = -1) Adds a menu item to the specified menu.  The menu argument can be either the text of a menu or its id.")
-{
-   if(dIsdigit(argv[4][0]))
-   {
-      Con::errorf("Cannot add submenu item %s (id = %s).  First character of a menu item's text cannot be a digit.", argv[4], argv[5]);
-      return;
-   }
-
-   GuiMenuBar::Menu *menu = object->findMenu(argv[2]);
-   if(!menu)
-   {
-      Con::errorf("Cannot find menu %s for addMenuItem.", argv[2]);
-      return;
-   }
-
-   GuiMenuBar::MenuItem *menuitem = object->findMenuItem(menu, argv[3]);
-   if(!menuitem)
-   {
-      Con::errorf("Cannot find menuitem %s for addSubmenuItem.", argv[3]);
-      return;
-   }
-
-   object->addSubmenuItem(menu, menuitem, argv[4], dAtoi(argv[5]), argc == 6 ? "" : argv[6], argc < 8 ? -1 : dAtoi(argv[7]));
-}
-
-ConsoleMethod(GuiMenuBar, clearSubmenuItems, void, 4, 4, "(string menu, string menuItem) Removes all the menu items from the specified submenu.\n"
-              "@return No return value.")
-{
-   GuiMenuBar::Menu *menu = object->findMenu(argv[2]);
-   if(!menu)
-   {
-      Con::errorf("Cannot find menu %s for clearSubmenuItems.", argv[2]);
-      return;
-   }
-
-   GuiMenuBar::MenuItem *menuitem = object->findMenuItem(menu, argv[3]);
-   if(!menuitem)
-   {
-      Con::errorf("Cannot find menuitem %s for clearSubmenuItems.", argv[3]);
-      return;
-   }
-
-   object->clearSubmenuItems(menuitem);
-}
-
-ConsoleMethod(GuiMenuBar, setSubmenuItemChecked, void, 6, 6, "(string menu, string menuItem, string submenuItemText, bool checked) Sets the menu item bitmap to a check mark, which by default is the first element in the bitmap array (although this may be changed with setCheckmarkBitmapIndex()).  Any other menu items in the menu with the same check group become unchecked if they are checked.")
-{
-   // Find the parent menu
-   GuiMenuBar::Menu *menu = object->findMenu(argv[2]);
-   if(!menu)
-   {
-      Con::errorf("Cannot find menu %s for setSubmenuItemChecked.", argv[2]);
-      return;
-   }
-
-   // Find the parent menu item
-   GuiMenuBar::MenuItem *menuItem = object->findMenuItem(menu, argv[3]);
-   if(!menuItem)
-   {
-      Con::errorf("Cannot find menu item %s for setSubmenuItemChecked.", argv[3]);
-      return;
-   }
-
-   // Find the submenu item
-   GuiMenuBar::MenuItem *submenuItem = object->findSubmenuItem(menu, argv[3], argv[4]);
-   if(!submenuItem)
-   {
-      Con::errorf("Cannot find submenu item %s for setSubmenuItemChecked.", argv[4]);
-      return;
-   }
-
-   bool checked = dAtob(argv[5]);
-   if(checked && submenuItem->checkGroup != -1)
-   {
-      // first, uncheck everything in the group:
-      for(GuiMenuBar::MenuItem *itemWalk = menuItem->firstSubmenuItem; itemWalk; itemWalk = itemWalk->nextMenuItem)
-         if(itemWalk->checkGroup == submenuItem->checkGroup && itemWalk->bitmapIndex == object->mCheckmarkBitmapIndex)
-            itemWalk->bitmapIndex = -1;
-   }
-   submenuItem->bitmapIndex = checked ? object->mCheckmarkBitmapIndex : -1;
-}
-
-//------------------------------------------------------------------------------
-// menu management methods
-//------------------------------------------------------------------------------
-
-void GuiMenuBar::addMenu(const char *menuText, U32 menuId)
-{
-   // allocate the menu
-   Menu *newMenu = new Menu;
-   newMenu->text = dStrdup(menuText);
-   newMenu->id = menuId;
-   newMenu->nextMenu = NULL;
-   newMenu->firstMenuItem = NULL;
-   newMenu->visible = true;
-
-   // Menu bitmap variables
-   newMenu->bitmapIndex = -1;
-   newMenu->drawBitmapOnly = false;
-   newMenu->drawBorder = true;
-   
-   // add it to the menu list
-   menuBarDirty = true;
-   Menu **walk;
-    for(walk = &menuList; *walk; walk = &(*walk)->nextMenu)
-      ;
-   *walk = newMenu;
-}
-
-GuiMenuBar::Menu *GuiMenuBar::findMenu(const char *menu)
-{
-    if(dIsdigit(menu[0]))
-    {
-        U32 id = dAtoi(menu);
-        for(Menu *walk = menuList; walk; walk = walk->nextMenu)
-            if(id == walk->id)
-                return walk;
-        return NULL;
-    }
-    else
-    {
-        for(Menu *walk = menuList; walk; walk = walk->nextMenu)
-            if(!dStricmp(menu, walk->text))
-                return walk;
-        return NULL;
-    }
-}
-
-GuiMenuBar::MenuItem *GuiMenuBar::findMenuItem(Menu *menu, const char *menuItem)
-{
-   if(dIsdigit(menuItem[0]))
-   {
-      U32 id = dAtoi(menuItem);
-      for(MenuItem *walk = menu->firstMenuItem; walk; walk = walk->nextMenuItem)
-         if(id == walk->id)
-            return walk;
-      return NULL;
-   }
-   else
-   {
-      for(MenuItem *walk = menu->firstMenuItem; walk; walk = walk->nextMenuItem)
-         if(!dStricmp(menuItem, walk->text))
-            return walk;
-      return NULL;
-   }
-}
-
-void GuiMenuBar::removeMenu(Menu *menu)
-{
-   menuBarDirty = true;
-   clearMenuItems(menu);
-   for(Menu **walk = &menuList; *walk; walk = &(*walk)->nextMenu)
-   {
-      if(*walk == menu)
-      {
-         *walk = menu->nextMenu;
-         break;
-      }
-   }
-   dFree(menu->text);
-   delete menu;
-}
-
-void GuiMenuBar::removeMenuItem(Menu *menu, MenuItem *menuItem)
-{
-   for(MenuItem **walk = &menu->firstMenuItem; *walk; walk = &(*walk)->nextMenuItem)
-   {
-      if(*walk == menuItem)
-      {
-         *walk = menuItem->nextMenuItem;
-         break;
-      }
-   }
-
-   // DAW: If this is a submenu, then be sure to clear the submenu's items
-   if(menuItem->isSubmenu)
-   {
-      clearSubmenuItems(menuItem);
-   }
-
-   dFree(menuItem->text);
-   dFree(menuItem->accelerator);
-   delete menuItem;
-}
-
-void GuiMenuBar::addMenuItem(Menu *menu, const char *text, U32 id, const char *accelerator, S32 checkGroup)
-{
-   // allocate the new menu item
-   MenuItem *newMenuItem = new MenuItem;
-   newMenuItem->text = dStrdup(text);
-   if(accelerator[0])
-      newMenuItem->accelerator = dStrdup(accelerator);
-   else
-      newMenuItem->accelerator = NULL;
-   newMenuItem->id = id;
-   newMenuItem->checkGroup = checkGroup;
-   newMenuItem->nextMenuItem = NULL;
-   newMenuItem->acceleratorIndex = 0;
-   newMenuItem->enabled = text[0] != '-';
-   newMenuItem->visible = true;
-   newMenuItem->bitmapIndex = -1;
-
-   // DAW: Default to not having a submenu
-   newMenuItem->isSubmenu = false;
-   newMenuItem->firstSubmenuItem = NULL;
-   newMenuItem->submenuParentMenu = NULL;
-
-   // link it into the menu's menu item list
-   MenuItem **walk = &menu->firstMenuItem;
-   while(*walk)
-      walk = &(*walk)->nextMenuItem;
-   *walk = newMenuItem;
-
-}
-
-void GuiMenuBar::clearMenuItems(Menu *menu)
-{
-   while(menu->firstMenuItem)
-      removeMenuItem(menu, menu->firstMenuItem);
-}
-
-void GuiMenuBar::clearMenus()
-{
-   while(menuList)
-      removeMenu(menuList);
-}
-
-//------------------------------------------------------------------------------
-// DAW: Submenu methods
-//------------------------------------------------------------------------------
-
-// DAW: This method will return the MenuItem class of of a submenu's menu item given
-// its parent menu and parent menuitem.  If the menuitem ID is used, then the submenu
-// ID must also be used.
-GuiMenuBar::MenuItem *GuiMenuBar::findSubmenuItem(Menu *menu, const char *menuItem, const char *submenuItem)
-{
-   if(dIsdigit(menuItem[0]))
-   {
-      // DAW: Search by ID
-      U32 id = dAtoi(menuItem);
-      for(MenuItem *walk = menu->firstMenuItem; walk; walk = walk->nextMenuItem)
-         if(id == walk->id)
-         {
-            if(walk->isSubmenu)
-            {
-               U32 subid = dAtoi(submenuItem);
-               for(MenuItem *subwalk = walk->firstSubmenuItem; subwalk; subwalk = subwalk->nextMenuItem)
-               {
-                  if(subid == walk->id)
-                  {
-                     return subwalk;
-                  }
-               }
-            }
-            return NULL;
-         }
-      return NULL;
-   }
-   else
-   {
-      // DAW: Search by name
-      for(MenuItem *walk = menu->firstMenuItem; walk; walk = walk->nextMenuItem)
-         if(!dStricmp(menuItem, walk->text))
-         {
-            if(walk->isSubmenu)
-            {
-               for(MenuItem *subwalk = walk->firstSubmenuItem; subwalk; subwalk = subwalk->nextMenuItem)
-               {
-                  if(!dStricmp(submenuItem, subwalk->text))
-                      return subwalk;
-               }
-            }
-            return NULL;
-         }
-      return NULL;
-   }
-}
-
-// DAW: Add a menuitem to the given submenu
-void GuiMenuBar::addSubmenuItem(Menu *menu, MenuItem *submenu, const char *text, U32 id, const char *accelerator, S32 checkGroup)
-{
-   // Check that the given menu item supports a submenu
-   if(submenu && !submenu->isSubmenu)
-   {
-      Con::errorf("GuiMenuBar::addSubmenuItem: Attempting to add menuitem '%s' to an invalid submenu",text);
-      return;
-   }
-
-   // allocate the new menu item
-   MenuItem *newMenuItem = new MenuItem;
-   newMenuItem->text = dStrdup(text);
-   if(accelerator[0])
-      newMenuItem->accelerator = dStrdup(accelerator);
-   else
-      newMenuItem->accelerator = NULL;
-   newMenuItem->id = id;
-   newMenuItem->checkGroup = checkGroup;
-   newMenuItem->nextMenuItem = NULL;
-   newMenuItem->acceleratorIndex = 0;
-   newMenuItem->enabled = text[0] != '-';
-   newMenuItem->visible = true;
-   newMenuItem->bitmapIndex = -1;
-
-   // DAW: Default to not having a submenu
-   newMenuItem->isSubmenu = false;
-   newMenuItem->firstSubmenuItem = NULL;
-
-   // DAW: Point back to the submenu's menu
-   newMenuItem->submenuParentMenu = menu;
-
-   // link it into the menu's menu item list
-   MenuItem **walk = &submenu->firstSubmenuItem;
-   while(*walk)
-      walk = &(*walk)->nextMenuItem;
-   *walk = newMenuItem;
-
-}
-
-// DAW: Remove a submenu item
-void GuiMenuBar::removeSubmenuItem(MenuItem *menuItem, MenuItem *submenuItem)
-{
-   // Check that the given menu item supports a submenu
-   if(menuItem && !menuItem->isSubmenu)
-   {
-      Con::errorf("GuiMenuBar::removeSubmenuItem: Attempting to remove submenuitem '%s' from an invalid submenu",submenuItem->text);
-      return;
-   }
-
-   for(MenuItem **subwalk = &menuItem->firstSubmenuItem; *subwalk; subwalk = &(*subwalk)->nextMenuItem)
-   {
-      if(*subwalk == submenuItem)
-      {
-         *subwalk = submenuItem->nextMenuItem;
-         break;
-      }
-   }
-   dFree(submenuItem->text);
-   dFree(submenuItem->accelerator);
-   delete submenuItem;
-}
-
-// DAW: Clear all menuitems from a submenu
-void GuiMenuBar::clearSubmenuItems(MenuItem *menuitem)
-{
-   // Check that the given menu item supports a submenu
-   if(menuitem && !menuitem->isSubmenu)
-   {
-      Con::errorf("GuiMenuBar::clearSubmenuItems: Attempting to clear an invalid submenu");
-      return;
-   }
-
-   while(menuitem->firstSubmenuItem)
-      removeSubmenuItem(menuitem, menuitem->firstSubmenuItem);
-}
-
-//------------------------------------------------------------------------------
-// initialization, input and render methods
-//------------------------------------------------------------------------------
-
-GuiMenuBar::GuiMenuBar()
-{
-    menuList = NULL;
-   menuBarDirty = true;
-   mouseDownMenu = NULL;
-   mouseOverMenu = NULL;
-   mCurAcceleratorIndex = 0;
-   mBackground = NULL;
-   mPadding = 0;
-
-   mCheckmarkBitmapIndex = 0; // Default to the first image in the bitmap array for the check mark
-
-   mHorizontalMargin = 6; // Default number of pixels on the left and right side of a manu's text
-   mVerticalMargin = 1;   // Default number of pixels on the top and bottom of a menu's text
-   mBitmapMargin = 2;     // Default number of pixels between a menu's bitmap and text
-
-   // DAW: Added:
-   mouseDownSubmenu = NULL;
-   mouseOverSubmenu = NULL;
-   mSubmenuBackground = NULL;
-   mSubmenuTextList = NULL;
-   mMouseOverCounter = 0;
-   mCountMouseOver = false;
-   mMouseHoverAmount = 30;
-   setProcessTicks(false);
-}
-
-void GuiMenuBar::initPersistFields()
-{
-   Parent::initPersistFields();
-
-   addField("Padding", TypeS32, Offset( mPadding, GuiMenuBar ) );
-}
-
-bool GuiMenuBar::onWake()
-{
-   if(!Parent::onWake())
-      return false;
-   mProfile->constructBitmapArray();  // if a bitmap was specified...
-   maxBitmapSize.set(0,0);
-   S32 numBitmaps = mProfile->mBitmapArrayRects.size();
-   if(numBitmaps)
-   {
-      RectI *bitmapBounds = mProfile->mBitmapArrayRects.address();
-      for(S32 i = 0; i < numBitmaps; i++)
-      {
-         if(bitmapBounds[i].extent.x > maxBitmapSize.x)
-            maxBitmapSize.x = bitmapBounds[i].extent.x;
-         if(bitmapBounds[i].extent.y > maxBitmapSize.y)
-            maxBitmapSize.y = bitmapBounds[i].extent.y;
-      }
-   }
-   return true;
-}
-
-GuiMenuBar::Menu *GuiMenuBar::findHitMenu(Point2I mousePoint)
-{
-   Point2I pos = globalToLocalCoord(mousePoint);
-
-   for(Menu *walk = menuList; walk; walk = walk->nextMenu)
-      if(walk->visible && walk->bounds.pointInRect(pos))
-         return walk;
-   return NULL;
-}
-
-void GuiMenuBar::onPreRender()
-{
-   Parent::onPreRender();
-   if(menuBarDirty)
-   {
-      menuBarDirty = false;
-      U32 curX = mPadding;
-      for(Menu *walk = menuList; walk; walk = walk->nextMenu)
-      {
-         if(!walk->visible)
-            continue;
-
-         // Bounds depends on if there is a bitmap to be drawn or not
-         if(walk->bitmapIndex == -1)
-         {
-            // Text only
-            walk->bounds.set(curX, 0, mProfile->mFont->getStrWidth(walk->text) + (mHorizontalMargin * 2), mBounds.extent.y - (mVerticalMargin * 2));
-
-         } else
-         {
-            // Will the bitmap and text be draw?
-            if(!walk->drawBitmapOnly)
-            {
-               // Draw the bitmap and the text
-               RectI *bitmapBounds = mProfile->mBitmapArrayRects.address();
-               walk->bounds.set(curX, 0, bitmapBounds[walk->bitmapIndex].extent.x + mProfile->mFont->getStrWidth(walk->text) + (mHorizontalMargin * 2), mBounds.extent.y + (mVerticalMargin * 2));
-
-            } else
-            {
-               // Only the bitmap will be drawn
-               RectI *bitmapBounds = mProfile->mBitmapArrayRects.address();
-               walk->bounds.set(curX, 0, bitmapBounds[walk->bitmapIndex].extent.x + mBitmapMargin + (mHorizontalMargin * 2), mBounds.extent.y + (mVerticalMargin * 2));
-            }
-         }
-
-         curX += walk->bounds.extent.x;
-      }
-        mouseOverMenu = NULL;
-        mouseDownMenu = NULL;
-   }
-}
-
-void GuiMenuBar::checkMenuMouseMove(const GuiEvent &event)
-{
-   Menu *hit = findHitMenu(event.mousePoint);
-   if(hit && hit != mouseDownMenu)
-   {
-      // gotta close out the current menu...
-      mTextList->setSelectedCell(Point2I(-1, -1));
-      closeMenu();
-      mouseOverMenu = mouseDownMenu = hit;
-      setUpdate();
-      onAction();
-   }
-}
-
-void GuiMenuBar::onTouchMove(const GuiEvent &event)
-{
-   Menu *hit = findHitMenu(event.mousePoint);
-    if(hit != mouseOverMenu)
-    {
-        // DAW: If we need to, reset the mouse over menu counter and indicate
-        // that we should track it.
-        if(hit)
-           mMouseOverCounter = 0;
-        if(!mCountMouseOver)
-        {
-           // DAW: We've never started the counter, so start it.
-           if(hit)
-              mCountMouseOver = true;
-        }
-
-        mouseOverMenu = hit;
-        setUpdate();
-    }
-}
-
-void GuiMenuBar::onTouchLeave(const GuiEvent &event)
-{
-   if(mouseOverMenu)
-        setUpdate();
-    mouseOverMenu = NULL;
-
-   // DAW: As we've left the control, don't track how long the mouse has been
-   // within it.
-   if(mCountMouseOver && mMouseOverCounter >= mMouseHoverAmount)
-   {
-      Con::executef( this, 3, "onMouseInMenu", "0"); // Last parameter indicates if we've entered or left the menu
-   }
-   mCountMouseOver = false;
-   mMouseOverCounter = 0;
-}
-
-void GuiMenuBar::onTouchDragged(const GuiEvent &event)
-{
-   Menu *hit = findHitMenu(event.mousePoint);
-    
-    if(hit != mouseOverMenu)
-    {
-        // DAW: If we need to, reset the mouse over menu counter and indicate
-        // that we should track it.
-        if(hit)
-           mMouseOverCounter = 0;
-        if(!mCountMouseOver)
-        {
-           // DAW: We've never started the counter, so start it.
-           if(hit)
-              mCountMouseOver = true;
-        }
-
-        mouseOverMenu = hit;
-      mouseDownMenu = hit;
-        setUpdate();
-      onAction();
-    }
-}
-
-void GuiMenuBar::onTouchDown(const GuiEvent &event)
-{
-   mouseDownMenu = mouseOverMenu = findHitMenu(event.mousePoint);
-    setUpdate();
-   onAction();
-}
-
-void GuiMenuBar::onTouchUp(const GuiEvent &event)
-{
-   mouseDownMenu = NULL;
-    setUpdate();
-}
-
-void GuiMenuBar::onRender(Point2I offset, const RectI &updateRect)
-{
-
-   RectI ctrlRect(offset, mBounds.extent);
-
-   //fill the update rect with the fill color
-   dglDrawRectFill(RectI(offset, mBounds.extent), mProfile->mFillColor);
-
-   //if there's a border, draw the border
-   //if (mProfile->mBorder)
-   //   renderBorder(ctrlRect, mProfile);
-
-   for(Menu *walk = menuList; walk; walk = walk->nextMenu)
-   {
-      if(!walk->visible)
-         continue;
-      ColorI fontColor = mProfile->mFontColor;
-      RectI bounds = walk->bounds;
-      bounds.point += offset;
-      
-      Point2I start;
-
-      start.x = walk->bounds.point.x + mHorizontalMargin;
-      start.y = walk->bounds.point.y + ( walk->bounds.extent.y - mProfile->mFont->getHeight() ) / 2;
-
-      // Draw the border
-      if(walk->drawBorder)
-      {
-        RectI highlightBounds = bounds;
-        highlightBounds.inset(1,1);
-         if(walk == mouseDownMenu)
-		 {
-			 renderUniversalRect(highlightBounds, mProfile, GuiControlState::HighlightState);
-         }
-		 else if(walk == mouseOverMenu && mouseDownMenu == NULL)
-		 {
-			 renderUniversalRect(highlightBounds, mProfile, GuiControlState::NormalState);
-		 }
-	  }
-
-      // Do we draw a bitmap?
-      if(walk->bitmapIndex != -1)
-      {
-         S32 index = walk->bitmapIndex * 3;
-         if(walk == mouseDownMenu)
-            ++index;
-         else if(walk == mouseOverMenu && mouseDownMenu == NULL)
-            index += 2;
-
-         RectI rect = mProfile->mBitmapArrayRects[index];
-
-         Point2I bitmapstart(start);
-         bitmapstart.y = walk->bounds.point.y + ( walk->bounds.extent.y - rect.extent.y ) / 2;
-
-         dglClearBitmapModulation();
-         dglDrawBitmapSR(mProfile->mTextureHandle, offset + bitmapstart, rect);
-
-         // Should we also draw the text?
-         if(!walk->drawBitmapOnly)
-         {
-            start.x += mBitmapMargin;
-            dglSetBitmapModulation( fontColor );
-            dglDrawText( mProfile->mFont, start + offset, walk->text, mProfile->mFontColors );
-         }
-      } else
-      {
-         dglSetBitmapModulation( fontColor );
-         dglDrawText( mProfile->mFont, start + offset, walk->text, mProfile->mFontColors );
-      }
-   }
-
-   renderChildControls( offset, mBounds, updateRect );
-}
-
-void GuiMenuBar::buildAcceleratorMap()
-{
-   Parent::buildAcceleratorMap();
-   // ok, accelerator map is cleared...
-   // add all our keys:
-   mCurAcceleratorIndex = 1;
-
-   for(Menu *menu = menuList; menu; menu = menu->nextMenu)
-   {
-      for(MenuItem *item = menu->firstMenuItem; item; item = item->nextMenuItem)
-      {
-         if(!item->accelerator)
-         {
-            item->accelerator = 0;
-            continue;
-         }
-         EventDescriptor accelEvent;
-            ActionMap::createEventDescriptor(item->accelerator, &accelEvent);
-   
-         //now we have a modifier, and a key, add them to the canvas
-         GuiCanvas *root = getRoot();
-         if (root)
-            root->addAcceleratorKey(this, mCurAcceleratorIndex, accelEvent.eventCode, accelEvent.flags);
-         item->acceleratorIndex = mCurAcceleratorIndex;
-         mCurAcceleratorIndex++;
-      }
-   }
-}
-
-void GuiMenuBar::acceleratorKeyPress(U32 index)
-{
-   // loop through all the menus
-   // and find the item that corresponds to the accelerator index
-   for(Menu *menu = menuList; menu; menu = menu->nextMenu)
-   {
-      if(!menu->visible)
-         continue;
-
-      for(MenuItem *item = menu->firstMenuItem; item; item = item->nextMenuItem)
-      {
-         if(item->acceleratorIndex == index)
-         {
-            // first, call the script callback for menu selection:
-            Con::executef( this, 4, "onMenuSelect", Con::getIntArg(menu->id), 
-                        menu->text);
-            if(item->visible)
-               menuItemSelected(menu, item);
-            return;
-         }
-      }
-   }
-}
-
-//------------------------------------------------------------------------------
-// Menu display class methods
-//------------------------------------------------------------------------------
-
-GuiMenuBackgroundCtrl::GuiMenuBackgroundCtrl(GuiMenuBar *ctrl, GuiMenuTextListCtrl *textList)
-{
-   mMenuBarCtrl = ctrl;
-   mTextList = textList;
-}
-
-void GuiMenuBackgroundCtrl::onTouchDown(const GuiEvent &event)
-{
-   mTextList->setSelectedCell(Point2I(-1,-1));
-   mMenuBarCtrl->closeMenu();
-}
-
-void GuiMenuBackgroundCtrl::onTouchMove(const GuiEvent &event)
-{
-   GuiCanvas *root = getRoot();
-   GuiControl *ctrlHit = root->findHitControl(event.mousePoint, mLayer - 1);
-   if(ctrlHit == mMenuBarCtrl)  // see if the current mouse over menu is right...
-      mMenuBarCtrl->checkMenuMouseMove(event);
-}
-
-void GuiMenuBackgroundCtrl::onTouchDragged(const GuiEvent &event)
-{
-   GuiCanvas *root = getRoot();
-   GuiControl *ctrlHit = root->findHitControl(event.mousePoint, mLayer - 1);
-   if(ctrlHit == mMenuBarCtrl)  // see if the current mouse over menu is right...
-      mMenuBarCtrl->checkMenuMouseMove(event);
-}
-
-GuiMenuTextListCtrl::GuiMenuTextListCtrl(GuiMenuBar *ctrl)
-{
-   mMenuBarCtrl = ctrl;
-   isSubMenu = false; // DAW: Added
-}
-
-void GuiMenuTextListCtrl::onRenderCell(Point2I offset, Point2I cell, bool selected, bool mouseOver)
-{
-   if(dStrcmp(mList[cell.y].text + 3, "-\t")) // DAW: Was: dStrcmp(mList[cell.y].text + 2, "-\t")) but has been changed to take into account the submenu flag
-      Parent::onRenderCell(offset, cell, selected, mouseOver);
-   else
-   {
-      S32 yp = offset.y + mCellSize.y / 2;
-      dglDrawLine(offset.x, yp, offset.x + mCellSize.x, yp, ColorI(128,128,128));
-      dglDrawLine(offset.x, yp+1, offset.x + mCellSize.x, yp+1, ColorI(255,255,255));
-   }
-   // now see if there's a bitmap...
-   U8 idx = mList[cell.y].text[0];
-   if(idx != 1)
-   {
-      // there's a bitmap...
-      U32 index = U32(idx - 2) * 3;
-      if(!mList[cell.y].active)
-         index += 2;
-      else if(selected || mouseOver)
-         index ++;
-
-      RectI rect = mProfile->mBitmapArrayRects[index];
-      Point2I off = mMenuBarCtrl->maxBitmapSize - rect.extent;
-      off /= 2;
-
-      dglClearBitmapModulation();
-      dglDrawBitmapSR(mProfile->mTextureHandle, offset + off, rect);
-
-   } 
-
-   // DAW: Check if this is a submenu
-   idx = mList[cell.y].text[1];
-   if(idx != 1)
-   {
-#if defined(TORQUE_OS_IOS) || defined(TORQUE_OS_ANDROID) || defined(TORQUE_OS_EMSCRIPTEN)
-// PUAP -Mat untested	
-//How are these used/made? cannot create in TGB GUI editor
-       if(selected || mouseOver)
-       {
-           glColor4f(mProfile->mFontColorHL.red,mProfile->mFontColorHL.green,mProfile->mFontColorHL.blue, 255 );//full alpha
-       }
-            else
-       {
-           glColor4f(mProfile->mFontColor.red,mProfile->mFontColor.green,mProfile->mFontColor.blue, 255);
-       }
-       glDrawArrays(GL_TRIANGLES, 0, 3 );
-#else
-      // This is a submenu, so draw an arrow
-      F32 left = (F32)(offset.x + mCellSize.x - 12);
-      F32 right = (F32)(left + 8);
-      F32 top = (F32)(mCellSize.y / 2 + offset.y - 4);
-      F32 bottom = (F32)(top + 8);
-      F32 middle = (F32)(top + 4);
-
-      glBegin(GL_TRIANGLES);
-         if(selected || mouseOver)
-         {
-            glColor3ub(mProfile->mFontColorHL.red,mProfile->mFontColorHL.green,mProfile->mFontColorHL.blue);
-
-         } else
-         {
-            glColor3ub(mProfile->mFontColor.red,mProfile->mFontColor.green,mProfile->mFontColor.blue);
-         }
-         glVertex2fv( Point3F(left, top, 0.0f) );
-         glVertex2fv( Point3F(right, middle, 0.0f) );
-         glVertex2fv( Point3F(left, bottom, 0.0f) );
-      glEnd();
-#endif
-   }
-}
-
-bool GuiMenuTextListCtrl::onKeyDown(const GuiEvent &event)
-{
-   //if the control is a dead end, don't process the input:
-   if ( !mVisible || !mActive || !mAwake )
-      return false;
-   
-   //see if the key down is a <return> or not
-   if ( event.modifier == 0 )
-   {
-      if ( event.keyCode == KEY_RETURN )
-      {
-         mMenuBarCtrl->closeMenu();
-         return true;
-      }
-      else if ( event.keyCode == KEY_ESCAPE )
-      {
-         mSelectedCell.set( -1, -1 );
-         mMenuBarCtrl->closeMenu();
-         return true;
-      }
-   }
-   
-   //otherwise, pass the event to it's parent
-   return Parent::onKeyDown(event);
-}
-
-void GuiMenuTextListCtrl::onTouchDown(const GuiEvent &event)
-{
-   Parent::onTouchDown(event);
-   mMenuBarCtrl->closeMenu();
-}
-
-void GuiMenuTextListCtrl::onTouchUp(const GuiEvent &event)
-{
-   // ok, this is kind of strange... but!
-   // here's the deal: if we get a mouse up in this control
-   // it means the mouse was dragged from the initial menu mouse click
-   // so: activate the menu result as though this event were,
-   // instead, a mouse down.
-
-   onTouchDown(event);
-}
-
-void GuiMenuTextListCtrl::onCellHighlighted(Point2I cell)
-{
-    // If this text list control is part of a submenu, then don't worry about
-    // passing this along
-    if(!isSubMenu)
-    {
-        RectI globalbounds(mBounds);
-        Point2I globalpoint = localToGlobalCoord(globalbounds.point);
-        globalbounds.point = globalpoint;
-        mMenuBarCtrl->highlightedMenuItem(cell.y, globalbounds, mCellSize);
-    }
-}
-
-//------------------------------------------------------------------------------
-// Submenu display class methods
-//------------------------------------------------------------------------------
-
-GuiSubmenuBackgroundCtrl::GuiSubmenuBackgroundCtrl(GuiMenuBar *ctrl, GuiMenuTextListCtrl *textList) : GuiMenuBackgroundCtrl(ctrl, textList)
-{
-}
-
-void GuiSubmenuBackgroundCtrl::onTouchDown(const GuiEvent &event)
-{
-   mTextList->setSelectedCell(Point2I(-1,-1));
-   mMenuBarCtrl->closeMenu();
-}
-
-bool GuiSubmenuBackgroundCtrl::pointInControl(const Point2I& parentCoordPoint)
-{
-   S32 xt = parentCoordPoint.x - mBounds.point.x;
-   S32 yt = parentCoordPoint.y - mBounds.point.y;
-
-   if(findHitControl(Point2I(xt,yt)) == this)
-       return false;
-   else
-       return true;
-//   return xt >= 0 && yt >= 0 && xt < mBounds.extent.x && yt < mBounds.extent.y;
-}
-
-//------------------------------------------------------------------------------
-
-void GuiMenuBar::menuItemSelected(GuiMenuBar::Menu *menu, GuiMenuBar::MenuItem *item)
-{
-   if(item->enabled)
-      Con::executef( this, 6, "onMenuItemSelect", Con::getIntArg(menu->id), 
-               menu->text, Con::getIntArg(item->id), item->text);
-}
-
-void GuiMenuBar::onSleep()
-{
-   if(mBackground) // a menu is up?
-   {
-      mTextList->setSelectedCell(Point2I(-1, -1));
-      closeMenu();
-   }
-   Parent::onSleep();
-}
-
-void GuiMenuBar::closeMenu()
-{
-   // DAW: First close any open submenu
-    closeSubmenu();
-
-   // Get the selection from the text list:
-   S32 selectionIndex = mTextList->getSelectedCell().y;
-
-   // Pop the background:
-   if( getRoot() )
-      getRoot()->popDialogControl(mBackground);
-   else
-      return;
-   
-   // Kill the popup:
-   mBackground->deleteObject();
-   mBackground = NULL;
-   
-   // Now perform the popup action:
-   if ( selectionIndex != -1 )
-   {
-      MenuItem *list = mouseDownMenu->firstMenuItem;
-
-      while(selectionIndex && list)
-      {
-         list = list->nextMenuItem;
-         selectionIndex--;
-      }
-      if(list)
-         menuItemSelected(mouseDownMenu, list);
-   }
-   mouseDownMenu = NULL;
-}
-
-// DAW: Called when a menu item is highlighted by the mouse
-void GuiMenuBar::highlightedMenuItem(S32 selectionIndex, RectI bounds, Point2I cellSize)
-{
-   S32 selstore = selectionIndex;
-
-   // Now perform the popup action:
-   if ( selectionIndex != -1 )
-   {
-      MenuItem *list = mouseDownMenu->firstMenuItem;
-
-      while(selectionIndex && list)
-      {
-         list = list->nextMenuItem;
-         selectionIndex--;
-      }
-
-      if(list)
-      {
-         // If the highlighted item has changed...
-         if(mouseOverSubmenu != list)
-         {
-            closeSubmenu();
-            mouseOverSubmenu = NULL;
-
-            // Check if this is a submenu.  If so, open the submenu.
-            if(list->isSubmenu)
-            {
-               // If there are submenu items, then open the submenu
-               if(list->firstSubmenuItem)
-               {
-                   mouseOverSubmenu = list;
-                   onSubmenuAction(selstore, bounds, cellSize);
-               }
-            }
-         }
-      }
-   }
-}
-
-//------------------------------------------------------------------------------
-void GuiMenuBar::onAction()
-{
-   if(!mouseDownMenu)
-      return;
-
-   // first, call the script callback for menu selection:
-   Con::executef( this, 4, "onMenuSelect", Con::getIntArg(mouseDownMenu->id), 
-               mouseDownMenu->text);
-
-   MenuItem *visWalk = mouseDownMenu->firstMenuItem;
-   while(visWalk)
-   {
-      if(visWalk->visible)
-         break;
-      visWalk = visWalk->nextMenuItem;
-   }
-   if(!visWalk)
-   {
-      mouseDownMenu = NULL;
-      return;
-   }
-
-   mTextList = new GuiMenuTextListCtrl(this);
-   mTextList->mProfile = mProfile;
-
-   mBackground = new GuiMenuBackgroundCtrl(this, mTextList);
-
-   GuiCanvas *root = getRoot();
-   Point2I windowExt = root->mBounds.extent;
-
-   mBackground->mBounds.point.set(0,0);
-   mBackground->mBounds.extent = root->mBounds.extent;
-
-   S32 textWidth = 0, width = 0;
-   S32 acceleratorWidth = 0;
-
-   GFont *font = mProfile->mFont;
-
-   for(MenuItem *walk = mouseDownMenu->firstMenuItem; walk; walk = walk->nextMenuItem)
-   {
-      if(!walk->visible)
-         continue;
-
-      S32 iTextWidth = font->getStrWidth(walk->text);
-      S32 iAcceleratorWidth = walk->accelerator ? font->getStrWidth(walk->accelerator) : 0;
-
-      if(iTextWidth > textWidth)
-         textWidth = iTextWidth;
-      if(iAcceleratorWidth > acceleratorWidth)
-         acceleratorWidth = iAcceleratorWidth;
-   }
-   width = textWidth + acceleratorWidth + maxBitmapSize.x * 2 + 2 + 4;
-
-   mTextList->setCellSize(Point2I(width, font->getHeight()+2));
-   mTextList->clearColumnOffsets();
-   mTextList->addColumnOffset(-1); // add an empty column in for the bitmap index.
-   mTextList->addColumnOffset(maxBitmapSize.x + 1);
-   mTextList->addColumnOffset(maxBitmapSize.x + 1 + textWidth + 4);
-
-   U32 entryCount = 0;
-
-   for(MenuItem *walk = mouseDownMenu->firstMenuItem; walk; walk = walk->nextMenuItem)
-   {
-      if(!walk->visible)
-         continue;
-
-      char buf[512];
-
-      // DAW: If this menu item is a submenu, then set the isSubmenu to 2 to indicate
-      // an arrow should be drawn.  Otherwise set the isSubmenu normally.
-      char isSubmenu = 1;
-      if(walk->isSubmenu)
-          isSubmenu = 2;
-
-      char bitmapIndex = 1;
-      if(walk->bitmapIndex >= 0 && (walk->bitmapIndex * 3 <= mProfile->mBitmapArrayRects.size()))
-         bitmapIndex = walk->bitmapIndex + 2;
-      dSprintf(buf, sizeof(buf), "%c%c\t%s\t%s", bitmapIndex, isSubmenu, walk->text, walk->accelerator ? walk->accelerator : "");
-      mTextList->addEntry(entryCount, buf);
-
-      if(!walk->enabled)
-         mTextList->setEntryActive(entryCount, false);
-
-      entryCount++;
-   }
-   Point2I menuPoint = localToGlobalCoord(mouseDownMenu->bounds.point);
-   menuPoint.y += mouseDownMenu->bounds.extent.y; // DAW: Used to have this at the end: + 2;
-
-   GuiControl *ctrl = new GuiControl;
-   ctrl->mBounds.point = menuPoint;
-   ctrl->mBounds.extent = mTextList->mBounds.extent + Point2I(6, 6);
-   ctrl->mProfile = mProfile;
-   mTextList->mBounds.point += Point2I(3,3);
-
-   // DAW: Make sure the menu doesn't go beyond the Canvas' bottom edge.
-   if((ctrl->mBounds.point.y+ctrl->mBounds.extent.y) > windowExt.y)
-   {
-      // DAW: Pop the menu above the menu bar
-      Point2I menuBar = localToGlobalCoord(mouseDownMenu->bounds.point);
-      ctrl->mBounds.point.y = menuBar.y - ctrl->mBounds.extent.y;
-   }
-
-   //mTextList->mBounds.point = Point2I(3,3);
-
-   mTextList->registerObject();
-   mBackground->registerObject();
-   ctrl->registerObject();
-
-   mBackground->addObject( ctrl );
-   ctrl->addObject( mTextList );
-
-   root->pushDialogControl(mBackground, mLayer + 1);
-   mTextList->setFirstResponder();
-}
-
-//------------------------------------------------------------------------------
-// DAW: Performs an action when a menu item that is a submenu is selected/highlighted
-void GuiMenuBar::onSubmenuAction(S32 selectionIndex, RectI bounds, Point2I cellSize)
-{
-   if(!mouseOverSubmenu)
-      return;
-
-   // first, call the script callback for menu selection:
-   Con::executef( this, 4, "onSubmenuSelect", Con::getIntArg(mouseOverSubmenu->id), 
-               mouseOverSubmenu->text);
-
-   MenuItem *visWalk = mouseOverSubmenu->firstSubmenuItem;
-   while(visWalk)
-   {
-      if(visWalk->visible)
-         break;
-      visWalk = visWalk->nextMenuItem;
-   }
-   if(!visWalk)
-   {
-      mouseOverSubmenu = NULL;
-      return;
-   }
-
-   mSubmenuTextList = new GuiMenuTextListCtrl(this);
-   mSubmenuTextList->mProfile = mProfile;
-   mSubmenuTextList->isSubMenu = true; // Indicate that this text list is part of a submenu
-
-   mSubmenuBackground = new GuiSubmenuBackgroundCtrl(this, mSubmenuTextList);
-
-   GuiCanvas *root = getRoot();
-   Point2I windowExt = root->mBounds.extent;
-
-   mSubmenuBackground->mBounds.point.set(0,0);
-   mSubmenuBackground->mBounds.extent = root->mBounds.extent;
-
-   S32 textWidth = 0, width = 0;
-   S32 acceleratorWidth = 0;
-
-   GFont *font = mProfile->mFont;
-
-   for(MenuItem *walk = mouseOverSubmenu->firstSubmenuItem; walk; walk = walk->nextMenuItem)
-   {
-      if(!walk->visible)
-         continue;
-
-      S32 iTextWidth = font->getStrWidth(walk->text);
-      S32 iAcceleratorWidth = walk->accelerator ? font->getStrWidth(walk->accelerator) : 0;
-
-      if(iTextWidth > textWidth)
-         textWidth = iTextWidth;
-      if(iAcceleratorWidth > acceleratorWidth)
-         acceleratorWidth = iAcceleratorWidth;
-   }
-   width = textWidth + acceleratorWidth + maxBitmapSize.x * 2 + 2 + 4;
-
-   mSubmenuTextList->setCellSize(Point2I(width, font->getHeight()+3));
-   mSubmenuTextList->clearColumnOffsets();
-   mSubmenuTextList->addColumnOffset(-1); // add an empty column in for the bitmap index.
-   mSubmenuTextList->addColumnOffset(maxBitmapSize.x + 1);
-   mSubmenuTextList->addColumnOffset(maxBitmapSize.x + 1 + textWidth + 4);
-
-   U32 entryCount = 0;
-
-   for(MenuItem *walk = mouseOverSubmenu->firstSubmenuItem; walk; walk = walk->nextMenuItem)
-   {
-      if(!walk->visible)
-         continue;
-
-      char buf[512];
-
-      // DAW: Can't have submenus within submenus.
-      char isSubmenu = 1;
-
-      char bitmapIndex = 1;
-      if(walk->bitmapIndex >= 0 && (walk->bitmapIndex * 3 <= mProfile->mBitmapArrayRects.size()))
-         bitmapIndex = walk->bitmapIndex + 2;
-      dSprintf(buf, sizeof(buf), "%c%c\t%s\t%s", bitmapIndex, isSubmenu, walk->text, walk->accelerator ? walk->accelerator : "");
-      mSubmenuTextList->addEntry(entryCount, buf);
-
-      if(!walk->enabled)
-         mSubmenuTextList->setEntryActive(entryCount, false);
-
-      entryCount++;
-   }
-   Point2I menuPoint = bounds.point; //localToGlobalCoord(bounds.point);
-   menuPoint.x += bounds.extent.x;
-   menuPoint.y += cellSize.y * selectionIndex - 6;
-
-   GuiControl *ctrl = new GuiControl;
-   ctrl->mBounds.point = menuPoint;
-   ctrl->mBounds.extent = mSubmenuTextList->mBounds.extent + Point2I(6, 6);
-   ctrl->mProfile = mProfile;
-   mSubmenuTextList->mBounds.point += Point2I(3,3);
-
-   // DAW: Make sure the menu doesn't go beyond the Canvas' bottom edge.
-   if((ctrl->mBounds.point.y+ctrl->mBounds.extent.y) > windowExt.y)
-   {
-      // DAW: Pop the menu above the menu bar
-      ctrl->mBounds.point.y -= mSubmenuTextList->mBounds.extent.y - cellSize.y - 6 - 3;
-   }
-
-   // DAW: And the same for the right edge
-   if((ctrl->mBounds.point.x+ctrl->mBounds.extent.x) > windowExt.x)
-   {
-      // DAW: Pop the submenu to the left of the menu
-      ctrl->mBounds.point.x -= mSubmenuTextList->mBounds.extent.x + cellSize.x + 6;
-   }
-
-   //mSubmenuTextList->mBounds.point = Point2I(3,3);
-
-   mSubmenuTextList->registerObject();
-   mSubmenuBackground->registerObject();
-   ctrl->registerObject();
-
-   mSubmenuBackground->addObject( ctrl );
-   ctrl->addObject( mSubmenuTextList );
-
-   root->pushDialogControl(mSubmenuBackground, mLayer + 1);
-   mSubmenuTextList->setFirstResponder();
-}
-
-// DAW: Close down the submenu controls
-void GuiMenuBar::closeSubmenu()
-{
-   if(!mSubmenuBackground || !mSubmenuTextList)
-       return;
-
-   // Get the selection from the text list:
-   S32 selectionIndex = mSubmenuTextList->getSelectedCell().y;
-
-   // Pop the background:
-   if( getRoot() )
-      getRoot()->popDialogControl(mSubmenuBackground);
-   
-   // Kill the popup:
-   mSubmenuBackground->deleteObject();
-   mSubmenuBackground = NULL;
-   mSubmenuTextList = NULL;
-   
-   // Now perform the popup action:
-   if ( selectionIndex != -1 )
-   {
-      MenuItem *list = NULL;
-      if(mouseOverSubmenu)
-      {
-         list = mouseOverSubmenu->firstSubmenuItem;
-
-         while(selectionIndex && list)
-         {
-            list = list->nextMenuItem;
-            selectionIndex--;
-         }
-      }
-      if(list)
-         menuItemSelected(list->submenuParentMenu, list);
-   }
-   mouseOverSubmenu = NULL;
-}
-
-// DAW: Find if the mouse pointer is within a menu item
-GuiMenuBar::MenuItem *GuiMenuBar::findHitMenuItem(Point2I mousePoint)
-{
-   //Point2I pos = globalToLocalCoord(mousePoint);
-
-//   for(Menu *walk = menuList; walk; walk = walk->nextMenu)
-//      if(walk->visible && walk->bounds.pointInRect(pos))
-//         return walk;
-   return NULL;
-}
-
-// DAW: Checks if the mouse has been moved to a new menu item
-void GuiMenuBar::checkSubmenuMouseMove(const GuiEvent &event)
-{
-   MenuItem *hit = findHitMenuItem(event.mousePoint);
-   if(hit && hit != mouseOverSubmenu)
-   {
-      // gotta close out the current menu...
-      mSubmenuTextList->setSelectedCell(Point2I(-1, -1));
-//      closeSubmenu();
-      setUpdate();
-   }
-}
-
-// DAW: Process a tick
-void GuiMenuBar::processTick()
-{
-   // If we are to track a tick, then do so.
-   if(mCountMouseOver)
-   {
-      // DAW: If we're at a particular number of ticks, notify the script function
-      if(mMouseOverCounter < mMouseHoverAmount)
-      {
-         ++mMouseOverCounter;
-
-      } else if(mMouseOverCounter == mMouseHoverAmount)
-      {
-         ++mMouseOverCounter;
-         Con::executef( this, 3, "onMouseInMenu", "1"); // Last parameter indicates if we've entered or left the menu
-      }
-   }
-}

+ 0 - 215
engine/source/gui/editor/guiMenuBar.h

@@ -1,215 +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 _GUIMENUBAR_H_
-#define _GUIMENUBAR_H_
-
-#ifndef _GUITEXTLISTCTRL_H_
-#include "gui/guiTextListCtrl.h"
-#endif
-
-class GuiMenuBar;
-class GuiMenuTextListCtrl;
-
-class GuiMenuBackgroundCtrl : public GuiControl
-{
-   typedef GuiControl Parent;
-
-protected:
-   GuiMenuBar *mMenuBarCtrl;
-   GuiMenuTextListCtrl *mTextList; 
-public:
-   GuiMenuBackgroundCtrl(GuiMenuBar *ctrl, GuiMenuTextListCtrl* textList);
-   void onTouchDown(const GuiEvent &event);
-   void onTouchMove(const GuiEvent &event);
-   void onTouchDragged(const GuiEvent &event);
-};
-
-class GuiSubmenuBackgroundCtrl : public GuiMenuBackgroundCtrl
-{
-   typedef GuiMenuBackgroundCtrl Parent;
-
-public:
-   GuiSubmenuBackgroundCtrl(GuiMenuBar *ctrl, GuiMenuTextListCtrl* textList);
-   bool pointInControl(const Point2I & parentCoordPoint);
-   void onTouchDown(const GuiEvent &event);
-};
-
-//------------------------------------------------------------------------------
-
-class GuiMenuTextListCtrl : public GuiTextListCtrl
-{
-   private:
-      typedef GuiTextListCtrl Parent;
-
-   protected:
-      GuiMenuBar *mMenuBarCtrl;
-
-   public:
-      bool isSubMenu; // DAW: Indicates that this text list is in a submenu
-
-      GuiMenuTextListCtrl(); // for inheritance
-      GuiMenuTextListCtrl(GuiMenuBar *ctrl);
-
-      // GuiControl overloads:
-      bool onKeyDown(const GuiEvent &event);
-      void onTouchDown(const GuiEvent &event);
-      void onTouchUp(const GuiEvent &event);
-      void onRenderCell(Point2I offset, Point2I cell, bool selected, bool mouseOver);
-
-      virtual void onCellHighlighted(Point2I cell); // DAW: Added
-};
-
-//------------------------------------------------------------------------------
-
-class GuiMenuBar : public GuiControl
-{
-   typedef GuiControl Parent;
-public:
-
-    struct Menu;
-
-    struct MenuItem   // an individual item in a pull-down menu
-    {
-        char *text;    // the text of the menu item
-        U32 id;        // a script-assigned identifier
-        char *accelerator; // the keyboard accelerator shortcut for the menu item
-      U32 acceleratorIndex; // index of this accelerator
-        bool enabled;        // true if the menu item is selectable
-      bool visible;        // true if the menu item is visible
-      S32 bitmapIndex;     // index of the bitmap in the bitmap array
-      S32 checkGroup;      // the group index of the item visa vi check marks - 
-                           // only one item in the group can be checked.
-        MenuItem *nextMenuItem; // next menu item in the linked list
-
-        bool isSubmenu;				// DAW: This menu item has a submenu that will be displayed
-        MenuItem *firstSubmenuItem;	// DAW: The first menu item in the submenu
-
-        Menu* submenuParentMenu; // DAW: For a submenu, this is the parent menu
-
-    };
-    struct Menu
-    {
-        char *text;
-        U32 id;
-        RectI bounds;
-      bool visible;
-
-        S32 bitmapIndex;		// Index of the bitmap in the bitmap array (-1 = no bitmap)
-        bool drawBitmapOnly;	// Draw only the bitmap and not the text
-        bool drawBorder;		// Should a border be drawn around this menu (usually if we only have a bitmap, we don't want a border)
-
-        Menu *nextMenu;
-        MenuItem *firstMenuItem;
-    };
-    
-    GuiMenuBackgroundCtrl *mBackground;
-    GuiMenuTextListCtrl *mTextList;
-    
-    GuiSubmenuBackgroundCtrl *mSubmenuBackground; // DAW: Background for a submenu
-    GuiMenuTextListCtrl *mSubmenuTextList;     // DAW: Text list for a submenu
-
-    Menu *menuList;
-   Menu *mouseDownMenu;
-   Menu *mouseOverMenu;
-
-   MenuItem* mouseDownSubmenu; // DAW: Stores the menu item that is a submenu that has been selected
-   MenuItem* mouseOverSubmenu; // DAW: Stores the menu item that is a submenu that has been highlighted
-
-   bool menuBarDirty;
-   U32 mCurAcceleratorIndex;
-   Point2I maxBitmapSize;
-
-   S32 mCheckmarkBitmapIndex; // Index in the bitmap array to use for the check mark image
-
-   S32 mPadding;
-   S32 mHorizontalMargin; // Left and right margin around the text of each menu
-   S32 mVerticalMargin;   // Top and bottom margin around the text of each menu
-   S32 mBitmapMargin;     // Margin between a menu's bitmap and text
-
-   // DAW: Used to keep track of the amount of ticks that the mouse is hovering
-   // over a menu.
-   S32 mMouseOverCounter;
-   bool mCountMouseOver;
-   S32 mMouseHoverAmount;
-    
-    GuiMenuBar();
-   bool onWake();
-   void onSleep();
-
-    // internal menu handling functions
-    // these are used by the script manipulation functions to add/remove/change menu items
-
-   void addMenu(const char *menuText, U32 menuId);
-    Menu *findMenu(const char *menu);  // takes either a menu text or a string id
-    MenuItem *findMenuItem(Menu *menu, const char *menuItem); // takes either a menu text or a string id
-    void removeMenu(Menu *menu);
-    void removeMenuItem(Menu *menu, MenuItem *menuItem);
-    void addMenuItem(Menu *menu, const char *text, U32 id, const char *accelerator, S32 checkGroup);
-    void clearMenuItems(Menu *menu);
-   void clearMenus();
-
-   // DAW: Methods to deal with submenus
-   MenuItem* findSubmenuItem(Menu *menu, const char *menuItem, const char *submenuItem);
-   void addSubmenuItem(Menu *menu, MenuItem *submenu, const char *text, U32 id, const char *accelerator, S32 checkGroup);
-   void removeSubmenuItem(MenuItem *menuItem, MenuItem *submenuItem);
-   void clearSubmenuItems(MenuItem *menuitem);
-   void onSubmenuAction(S32 selectionIndex, RectI bounds, Point2I cellSize);
-   void closeSubmenu();
-   void checkSubmenuMouseMove(const GuiEvent &event);
-   MenuItem *findHitMenuItem(Point2I mousePoint);
-
-   void highlightedMenuItem(S32 selectionIndex, RectI bounds, Point2I cellSize); // DAW: Called whenever a menu item is highlighted by the mouse
-
-    // display/mouse functions
-
-    Menu *findHitMenu(Point2I mousePoint);
-
-   // DAW: Called when the GUI theme changes and a bitmap arrary may need updating
-  // void onThemeChange();
-
-   void onPreRender();
-    void onRender(Point2I offset, const RectI &updateRect);
-
-   void checkMenuMouseMove(const GuiEvent &event);
-   void onTouchMove(const GuiEvent &event);
-   void onTouchLeave(const GuiEvent &event);
-   void onTouchDown(const GuiEvent &event);
-   void onTouchDragged(const GuiEvent &event);
-   void onTouchUp(const GuiEvent &event);
-   
-   void onAction();
-   void closeMenu();
-   void buildAcceleratorMap();
-   void acceleratorKeyPress(U32 index);
-
-   void menuItemSelected(Menu *menu, MenuItem *item);
-
-   // DAW: Added to support 'ticks'
-   void processTick();
-
-   static void initPersistFields();
-
-   DECLARE_CONOBJECT(GuiMenuBar);
-};
-
-#endif

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

@@ -0,0 +1,1441 @@
+//-----------------------------------------------------------------------------
+// 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 "console/console.h"
+#include "console/consoleTypes.h"
+#include "graphics/dgl.h"
+#include "gui/guiDefaultControlRender.h"
+#include "gui/guiCanvas.h"
+#include "input/actionMap.h"
+
+#include "gui/editor/guiMenuBarCtrl.h"
+
+#include "gui/editor/guiMenuBarCtrl_ScriptBinding.h"
+
+#pragma region GuiMenuBarCtrl
+IMPLEMENT_CONOBJECT(GuiMenuBarCtrl);
+
+GuiMenuBarCtrl::GuiMenuBarCtrl()
+{
+	mBounds.point.set(0, 0);
+	mBounds.extent.set(400, 26);
+	mActive = true;
+	mUseKeyMode = false;
+	mAcceleratorKey = "alt";
+	setField("profile", "GuiMenuBarProfile");
+
+	mMenuProfile = NULL;
+	setField("MenuProfile", "GuiMenuProfile");
+
+	mMenuContentProfile = NULL;
+	setField("MenuContentProfile", "GuiMenuContentProfile");
+
+	mMenuItemProfile = NULL;
+	setField("MenuItemProfile", "GuiMenuItemProfile");
+
+	mThumbProfile = NULL;
+	setField("ThumbProfile", "GuiScrollThumbProfile");
+
+	mArrowProfile = NULL;
+	setField("ArrowProfile", "GuiSrollArrowProfile");
+
+	mTrackProfile = NULL;
+	setField("TrackProfile", "GuiScrollTrackProfile");
+
+	mHoverTarget = NULL;
+	mOpenMenu = NULL;
+
+	mUseConstantHeightThumb = false;
+	mScrollBarThickness = 12;
+	mShowArrowButtons = false;
+
+	mBackground = new GuiMenuBGCtrl(this);
+	AssertFatal(mBackground, "GuiDropDownCtrl: Failed to initialize GuiMenuBGCtrl!");
+	mBackgroundProfile = mBackground->mProfile;
+	mBackgroundProfile->incRefCount();
+}
+
+void GuiMenuBarCtrl::initPersistFields()
+{
+	Parent::initPersistFields();
+
+	addField("MenuProfile", TypeGuiProfile, Offset(mMenuProfile, GuiMenuBarCtrl));
+	addField("MenuContentProfile", TypeGuiProfile, Offset(mMenuContentProfile, GuiMenuBarCtrl));
+	addField("MenuItemProfile", TypeGuiProfile, Offset(mMenuItemProfile, GuiMenuBarCtrl));
+	addField("backgroundProfile", TypeGuiProfile, Offset(mBackgroundProfile, GuiMenuBarCtrl));
+	addField("constantThumbHeight", TypeBool, Offset(mUseConstantHeightThumb, GuiMenuBarCtrl));
+	addField("scrollBarThickness", TypeS32, Offset(mScrollBarThickness, GuiMenuBarCtrl));
+	addField("showArrowButtons", TypeBool, Offset(mShowArrowButtons, GuiMenuBarCtrl));
+	addField("thumbProfile", TypeGuiProfile, Offset(mThumbProfile, GuiMenuBarCtrl));
+	addField("trackProfile", TypeGuiProfile, Offset(mTrackProfile, GuiMenuBarCtrl));
+	addField("arrowProfile", TypeGuiProfile, Offset(mArrowProfile, GuiMenuBarCtrl));
+}
+
+void GuiMenuBarCtrl::inspectPostApply()
+{
+	ApplyMenuSettings();
+	calculateMenus();
+	Parent::inspectPostApply();
+}
+
+void GuiMenuBarCtrl::childResized(GuiControl *child)
+{
+	calculateMenus();
+}
+
+void GuiMenuBarCtrl::resize(const Point2I &newPosition, const Point2I &newExtent)
+{
+	Parent::resize(Point2I(0, 0), newExtent);
+}
+
+void GuiMenuBarCtrl::onChildAdded(GuiControl *child)
+{
+	GuiMenuItemCtrl *menu = dynamic_cast<GuiMenuItemCtrl*>(child);
+	if (!menu)
+	{
+		Con::warnf("GuiMenuBarCtrl::onChildAdded - Only a GuiMenuItemCtrl can be added to a GuiMenuBarCtrl! Child will not be added.");
+		SimObject *simObj = reinterpret_cast<SimObject*>(child);
+		removeObject(simObj);
+		return;
+	}
+	menu->mMenuBar = this;
+	menu->setControlProfile(mMenuProfile);
+	calculateMenus();
+
+	if (size() > 1)
+	{
+		iterator i = end() - 2;
+		GuiMenuItemCtrl *ctrl = static_cast<GuiMenuItemCtrl *>(*i);
+		menu->mPrevItem = ctrl;
+		ctrl->mNextItem = menu;
+	}
+}
+
+void GuiMenuBarCtrl::onChildRemoved(SimObject *child)
+{
+	calculateMenus();
+}
+
+void GuiMenuBarCtrl::calculateMenus()
+{
+	RectI innerRect = getInnerRect(mBounds.point.Zero, getExtent(), NormalState, mProfile);
+	iterator i;
+	S32 length = 0;
+	for (i = begin(); i != end(); i++)
+	{
+		GuiControl *ctrl = static_cast<GuiControl *>(*i);
+		if (ctrl->isVisible())
+		{
+			S32 width = ctrl->mProfile->mFont->getStrWidth((const UTF8*)ctrl->getText());
+			Point2I outerExtent = getOuterExtent(Point2I(width, 0), NormalState, ctrl->mProfile);
+			ctrl->mBounds.set(Point2I(length, 0), Point2I(outerExtent.x, innerRect.extent.y));
+			length += ctrl->getExtent().x;
+		}
+	}
+}
+
+GuiControl* GuiMenuBarCtrl::findHitControl(const Point2I &pt, S32 initialLayer)
+{
+	return this;
+}
+
+GuiMenuItemCtrl* GuiMenuBarCtrl::findHitMenu(const Point2I &pt)
+{
+	iterator i;
+	for (i = begin(); i != end(); i++)
+	{
+		GuiMenuItemCtrl *ctrl = static_cast<GuiMenuItemCtrl *>(*i);
+		if (ctrl && ctrl->isVisible() && ctrl->isActive())
+		{
+			if (ctrl->mBounds.pointInRect(pt - ctrl->mRenderInsetLT))
+			{
+				return ctrl;
+			}
+		}
+	}
+	return NULL;
+}
+
+void GuiMenuBarCtrl::processHover(const GuiEvent &event)
+{
+	GuiMenuItemCtrl *ctrl = findHitMenu(globalToLocalCoord(event.mousePoint));
+	mUseKeyMode = false;
+	setHoverTarget(ctrl);
+}
+
+void GuiMenuBarCtrl::setHoverTarget(GuiMenuItemCtrl *ctrl)
+{
+	if (mHoverTarget != ctrl) 
+	{
+		if (mHoverTarget != NULL) 
+		{
+			mHoverTarget->mIsHover = false;
+		}
+		if(ctrl != NULL) 
+		{
+			ctrl->mIsHover = true;
+		}
+		mHoverTarget = ctrl;
+	}
+}
+
+void GuiMenuBarCtrl::onTouchMove(const GuiEvent &event)
+{
+	processHover(event);
+}
+
+void GuiMenuBarCtrl::onTouchEnter(const GuiEvent &event)
+{
+	processHover(event);
+}
+
+void GuiMenuBarCtrl::onTouchLeave(const GuiEvent &event)
+{
+	if (mHoverTarget != NULL) {
+		mHoverTarget->mIsHover = false;
+	}
+	mHoverTarget = NULL;
+	clearFirstResponder();
+}
+
+void GuiMenuBarCtrl::onTouchDown(const GuiEvent &event)
+{
+	GuiMenuItemCtrl *ctrl = findHitMenu(globalToLocalCoord(event.mousePoint));
+	if (mOpenMenu != ctrl)
+	{
+		if (mOpenMenu != NULL)
+		{
+			mOpenMenu->closeMenu();
+		}
+		if (ctrl != NULL)
+		{
+			ctrl->mIsOpen = true;
+		}
+		mOpenMenu = ctrl;
+	}
+	openMenu();
+}
+
+void GuiMenuBarCtrl::onRender(Point2I offset, const RectI &updateRect)
+{
+	RectI clipRect = dglGetClipRect();
+	if (clipRect.extent.x != mBounds.extent.x || mBounds.point.x != 0 || mBounds.point.y != 0)
+	{
+		resize(Point2I(0, 0), Point2I(clipRect.extent.x, mBounds.extent.y));
+	}
+	RectI ctrlRect = applyMargins(offset, mBounds.extent, NormalState, mProfile);
+
+	if (!ctrlRect.isValidRect())
+	{
+		return;
+	}
+
+	renderUniversalRect(ctrlRect, mProfile, NormalState);
+
+	RectI fillRect = applyBorders(ctrlRect.point, ctrlRect.extent, NormalState, mProfile);
+	RectI contentRect = applyPadding(fillRect.point, fillRect.extent, NormalState, mProfile);
+
+	if (contentRect.isValidRect())
+	{
+		//Render the childen
+		renderChildControls(offset, contentRect, updateRect);
+	}
+}
+
+void GuiMenuBarCtrl::openMenu()
+{
+	if (mOpenMenu == NULL)
+	{
+		return;
+	}
+
+	GuiCanvas *root = getRoot();
+	AssertFatal(root, "GuiMenuBarCtrl::openMenu: Unable to optain the Canvas!");
+	mBackground->mBounds.extent = root->mBounds.extent;
+	mBackground->setControlProfile(mBackgroundProfile);
+
+	ApplyMenuSettings();
+
+	mBackground->openMenu();
+
+	root->pushDialogControl(mBackground, 99);
+
+	setFirstResponder();
+
+	if (isMethod("onOpen"))
+		Con::executef(this, 1, "onOpen");
+}
+
+void GuiMenuBarCtrl::closeMenu()
+{
+	if (!mOpenMenu)
+		return;
+
+	mOpenMenu->closeMenu();
+
+	mBackground->getRoot()->popDialogControl(mBackground);
+
+	mOpenMenu->mIsOpen = false;
+	mOpenMenu->mIsHover = false;
+	mOpenMenu = NULL;
+
+	if (isMethod("onClose"))
+		Con::executef(this, 1, "onClose");
+}
+
+void GuiMenuBarCtrl::ApplyMenuSettings()
+{
+	iterator i;
+	for (i = begin(); i != end(); i++)
+	{
+		GuiMenuItemCtrl *ctrl = static_cast<GuiMenuItemCtrl *>(*i);
+		if (ctrl->isVisible() && ctrl->isActive() && ctrl->mHasGoodChildren)
+		{
+			ctrl->ApplyMenuSettings();
+		}
+		ctrl->setControlProfile(mMenuProfile);
+	}
+	setUpdate();
+}
+
+void GuiMenuBarCtrl::acceleratorKeyPress(U32 index)
+{
+	if (mUseKeyMode && mOpenMenu != NULL)
+	{
+		mUseKeyMode = true;
+		GuiMenuItemCtrl *ctrl = mOpenMenu;
+		closeMenu();
+		mHoverTarget = ctrl;
+		mHoverTarget->mIsHover = true;
+	}
+	else if (mUseKeyMode)
+	{
+		mUseKeyMode = false;
+		if (mHoverTarget != NULL)
+		{
+			mHoverTarget->mIsHover = false;
+		}
+		mHoverTarget = NULL;
+		clearFirstResponder();
+	}
+	else
+	{
+		mUseKeyMode = true;
+		GuiMenuItemCtrl *newTarget = dynamic_cast<GuiMenuItemCtrl *>(first());
+		setHoverTarget(newTarget);
+		setFirstResponder();
+	}
+}
+
+bool GuiMenuBarCtrl::onKeyDown(const GuiEvent &event)
+{
+	if (!mVisible || !mActive || !mAwake)
+		return false;
+
+	if (mHoverTarget == NULL && mOpenMenu == NULL)
+	{
+		clearFirstResponder();
+		return false;
+	}
+
+	if ((event.keyCode == KEY_ALT || event.keyCode == KEY_LALT || event.keyCode == KEY_RALT) && event.modifier == 0)
+	{
+		acceleratorKeyPress(0);
+		return true;
+	}
+	else if (mOpenMenu != NULL)
+	{
+		mOpenMenu->onKeyDown(event);
+	}
+	else if (event.keyCode == KEY_RIGHT && event.modifier == 0)
+	{
+		mUseKeyMode = true;
+		if (mHoverTarget->mNextItem != NULL)
+		{
+			setHoverTarget(mHoverTarget->mNextItem);
+			if (!mHoverTarget->isVisible() || !mHoverTarget->isActive() || !mHoverTarget->mHasGoodChildren)
+			{
+				onKeyDown(event);
+			}
+		}
+		else
+		{
+			GuiMenuItemCtrl *newTarget = dynamic_cast<GuiMenuItemCtrl *>(first());
+			setHoverTarget(newTarget);
+			if (!mHoverTarget->isVisible() || !mHoverTarget->isActive() || !mHoverTarget->mHasGoodChildren)
+			{
+				onKeyDown(event);
+			}
+		}
+		return true;
+	}
+	else if (event.keyCode == KEY_LEFT && event.modifier == 0)
+	{
+		mUseKeyMode = true;
+		if (mHoverTarget->mPrevItem != NULL)
+		{
+			setHoverTarget(mHoverTarget->mPrevItem);
+			if (!mHoverTarget->isVisible() || !mHoverTarget->isActive() || !mHoverTarget->mHasGoodChildren)
+			{
+				onKeyDown(event);
+			}
+		}
+		else
+		{
+			GuiMenuItemCtrl *newTarget = dynamic_cast<GuiMenuItemCtrl *>(last());
+			setHoverTarget(newTarget);
+			if (!mHoverTarget->isVisible() || !mHoverTarget->isActive() || !mHoverTarget->mHasGoodChildren)
+			{
+				onKeyDown(event);
+			}
+		}
+		return true;
+	}
+	else if (event.keyCode == KEY_DOWN && event.modifier == 0)
+	{
+		mUseKeyMode = true;
+		if (mOpenMenu == NULL && mHoverTarget->mDisplayType == GuiMenuItemCtrl::DisplayType::Menu && mHoverTarget->isVisible() && mHoverTarget->isActive() && mHoverTarget->mHasGoodChildren)
+		{
+			mOpenMenu = mHoverTarget;
+			mOpenMenu->mIsHover = false;
+			mOpenMenu->mIsOpen = true;
+			openMenu();
+			return true;
+		}
+	}
+		
+	return false;
+}
+
+bool GuiMenuBarCtrl::onWake()
+{
+	if (!Parent::onWake())
+		return false;
+
+	if (mBackgroundProfile != NULL)
+		mBackgroundProfile->incRefCount();
+
+	if (mMenuProfile != NULL)
+		mMenuProfile->incRefCount();
+
+	if (mMenuItemProfile != NULL)
+		mMenuItemProfile->incRefCount();
+
+	if (mMenuContentProfile != NULL)
+		mMenuContentProfile->incRefCount();
+
+	if (mBackgroundProfile != NULL)
+		mBackgroundProfile->incRefCount();
+
+	if (mThumbProfile != NULL)
+		mThumbProfile->incRefCount();
+
+	if (mTrackProfile != NULL)
+		mTrackProfile->incRefCount();
+
+	if (mArrowProfile != NULL)
+		mArrowProfile->incRefCount();
+
+	return true;
+}
+
+void GuiMenuBarCtrl::onSleep()
+{
+	Parent::onSleep();
+
+	if (mBackgroundProfile != NULL)
+		mBackgroundProfile->decRefCount();
+
+	if (mMenuProfile != NULL)
+		mMenuProfile->decRefCount();
+
+	if (mMenuItemProfile != NULL)
+		mMenuItemProfile->decRefCount();
+
+	if (mMenuContentProfile != NULL)
+		mMenuContentProfile->decRefCount();
+
+	if (mBackgroundProfile != NULL)
+		mBackgroundProfile->decRefCount();
+
+	if (mThumbProfile != NULL)
+		mThumbProfile->decRefCount();
+
+	if (mTrackProfile != NULL)
+		mTrackProfile->decRefCount();
+
+	if (mArrowProfile != NULL)
+		mArrowProfile->decRefCount();
+}
+
+void GuiMenuBarCtrl::setControlBackgroundProfile(GuiControlProfile* prof)
+{
+	AssertFatal(prof, "GuiMenuBarCtrl::setControlBackgroundProfile: invalid background profile");
+	if (prof == mBackgroundProfile)
+		return;
+	if (mAwake)
+		mBackgroundProfile->decRefCount();
+	mBackgroundProfile = prof;
+	if (mAwake)
+		mBackgroundProfile->incRefCount();
+
+	ApplyMenuSettings();
+}
+
+void GuiMenuBarCtrl::setControlMenuProfile(GuiControlProfile* prof)
+{
+	AssertFatal(prof, "GuiMenuBarCtrl::setControlMenuProfile: invalid profile");
+	if (prof == mMenuProfile)
+		return;
+	if (mAwake)
+		mMenuProfile->decRefCount();
+	mMenuProfile = prof;
+	if (mAwake)
+		mMenuProfile->incRefCount();
+
+	ApplyMenuSettings();
+	setUpdate();
+}
+
+void GuiMenuBarCtrl::setControlMenuItemProfile(GuiControlProfile* prof)
+{
+	AssertFatal(prof, "GuiMenuBarCtrl::setControlMenuItemProfile: invalid profile");
+	if (prof == mMenuItemProfile)
+		return;
+	if (mAwake)
+		mMenuItemProfile->decRefCount();
+	mMenuItemProfile = prof;
+	if (mAwake)
+		mMenuItemProfile->incRefCount();
+
+	ApplyMenuSettings();
+	setUpdate();
+}
+
+void GuiMenuBarCtrl::setControlMenuContentProfile(GuiControlProfile* prof)
+{
+	AssertFatal(prof, "GuiMenuBarCtrl::setControlMenuContentProfile: invalid profile");
+	if (prof == mMenuContentProfile)
+		return;
+	if (mAwake)
+		mMenuContentProfile->decRefCount();
+	mMenuContentProfile = prof;
+	if (mAwake)
+		mMenuContentProfile->incRefCount();
+
+	ApplyMenuSettings();
+}
+
+void GuiMenuBarCtrl::setControlThumbProfile(GuiControlProfile* prof)
+{
+	AssertFatal(prof, "GuiMenuBarCtrl::setControlThumbProfile: invalid thumb profile");
+	if (prof == mThumbProfile)
+		return;
+	if (mAwake)
+		mThumbProfile->decRefCount();
+	mThumbProfile = prof;
+	if (mAwake)
+		mThumbProfile->incRefCount();
+
+	ApplyMenuSettings();
+}
+
+void GuiMenuBarCtrl::setControlTrackProfile(GuiControlProfile* prof)
+{
+	AssertFatal(prof, "GuiMenuBarCtrl::setControlTrackProfile: invalid track profile");
+	if (prof == mTrackProfile)
+		return;
+	if (mAwake)
+		mTrackProfile->decRefCount();
+	mTrackProfile = prof;
+	if (mAwake)
+		mTrackProfile->incRefCount();
+
+	ApplyMenuSettings();
+}
+
+void GuiMenuBarCtrl::setControlArrowProfile(GuiControlProfile* prof)
+{
+	AssertFatal(prof, "GuiMenuBarCtrl::setControlArrowProfile: invalid arrow profile");
+	if (prof == mArrowProfile)
+		return;
+	if (mAwake)
+		mArrowProfile->decRefCount();
+	mArrowProfile = prof;
+	if (mAwake)
+		mArrowProfile->incRefCount();
+
+	ApplyMenuSettings();
+}
+#pragma endregion
+
+#pragma region GuiMenuItemCtrl
+IMPLEMENT_CONOBJECT(GuiMenuItemCtrl);
+
+GuiMenuItemCtrl::GuiMenuItemCtrl()
+{
+	mText = "Menu";
+	mDisplayType = TextCommand;
+	mActive = true;
+	mIsOpen = false;
+	mIsHover = false;
+	mIsOn = false;
+	mToggle = false;
+	mRadio = false;
+	mHasGoodChildren = true;
+
+	mPrevItem = NULL;
+	mNextItem = NULL;
+	mOpenSubMenu = NULL;
+
+	mScroll = NULL;
+	mList = NULL;
+}
+
+void GuiMenuItemCtrl::initPersistFields()
+{
+	SimObject::initPersistFields();
+
+	addGroup("MenuItem");
+	addField("Variable", TypeString, Offset(mConsoleVariable, GuiMenuItemCtrl));
+	addField("Command", TypeString, Offset(mConsoleCommand, GuiMenuItemCtrl));
+	addField("AltCommand", TypeString, Offset(mAltConsoleCommand, GuiMenuItemCtrl));
+	addField("Accelerator", TypeString, Offset(mAcceleratorKey, GuiMenuItemCtrl));
+	addField("Active", TypeBool, Offset(mActive, GuiMenuItemCtrl));
+	addField("Visible", TypeBool, Offset(mVisible, GuiMenuItemCtrl));
+	addProtectedField("IsOn", TypeBool, Offset(mIsOn, GuiMenuItemCtrl), &defaultProtectedSetFn, &defaultProtectedGetFn, &writeIsOn, "");
+	addProtectedField("Toggle", TypeBool, Offset(mToggle, GuiMenuItemCtrl), &setToggle, &defaultProtectedGetFn, &writeToggle, "");
+	addProtectedField("Radio", TypeS32, Offset(mRadio, GuiMenuItemCtrl), &setRadio, &defaultProtectedGetFn, &writeRadio, "");
+	endGroup("MenuItem");
+
+	addGroup("Localization");
+	addField("langTableMod", TypeString, Offset(mLangTableName, GuiMenuItemCtrl));
+	endGroup("Localization");
+
+	addGroup("Text");
+	addProtectedField("text", TypeCaseString, Offset(mText, GuiMenuItemCtrl), setTextProperty, getTextProperty, "");
+	addField("textID", TypeString, Offset(mTextID, GuiMenuItemCtrl));
+	endGroup("Text");
+}
+
+void GuiMenuItemCtrl::onAction()
+{
+	if (!mActive || !mVisible)
+		return;
+
+	if (mDisplayType == TextCommand)
+	{
+		Parent::onAction();
+	}
+	else if (mDisplayType == Toggle || mDisplayType == Radio)
+	{
+		toggleControl();
+	}
+}
+
+void GuiMenuItemCtrl::inspectPostApply()
+{
+	Parent::inspectPostApply();
+
+	if(mDisplayType == Menu)
+	{
+		checkForGoodChildren();
+	}
+
+	GuiMenuItemCtrl *menu = dynamic_cast<GuiMenuItemCtrl *>(getParent());
+	if (menu != NULL)
+	{
+		menu->checkForGoodChildren();
+	}
+}
+
+void GuiMenuItemCtrl::onChildAdded(GuiControl *child)
+{
+	GuiMenuItemCtrl *subMenu = dynamic_cast<GuiMenuItemCtrl*>(child);
+	if (!subMenu)
+	{
+		Con::warnf("GuiMenuItemCtrl::onChildAdded - Only a GuiMenuItemCtrl can be added to a GuiMenuItemCtrl! Child will not be added.");
+		SimObject *simObj = reinterpret_cast<SimObject*>(child);
+		removeObject(simObj);
+		return;
+	}
+	subMenu->mMenuBar = this->mMenuBar;
+	subMenu->setControlProfile(mMenuBar->mMenuItemProfile);
+	if (dStrcmp(subMenu->getText(), "-") == 0)
+	{
+		subMenu->mDisplayType = Spacer;
+		subMenu->setText(StringTable->EmptyString);
+	}
+	else if (subMenu->mToggle)
+	{
+		subMenu->mDisplayType = Toggle;
+	}
+	else if (subMenu->mRadio)
+	{
+		subMenu->mDisplayType = Radio;
+	}
+
+	if (size() > 1)
+	{
+		iterator i = end() - 2;
+		GuiMenuItemCtrl *ctrl = static_cast<GuiMenuItemCtrl *>(*i);
+		subMenu->mPrevItem = ctrl;
+		ctrl->mNextItem = subMenu;
+	}
+
+	if (mDisplayType != Menu)
+	{
+		mDisplayType = Menu;
+		if(mScroll == NULL)
+		{
+			mScroll = new GuiScrollCtrl();
+			AssertFatal(mScroll, "GuiMenuItemCtrl::onChildAdded Failed to initialize GuiScrollCtrl!");
+		}
+
+		if(mList == NULL)
+		{ 
+			mList = new GuiMenuListCtrl(this);
+			AssertFatal(mList, "GuiMenuItemCtrl::onChildAdded Failed to initialize GuiMenuListCtrl!");
+			mScroll->addObject(mList);
+		}
+	}
+
+	if (mDisplayType == Menu)
+	{
+		mList->updateSize();
+	}
+	checkForGoodChildren();
+}
+
+void GuiMenuItemCtrl::onChildRemoved(SimObject *child)
+{
+	if (size() <= 0)
+	{
+		if (mDisplayType == Menu)
+		{
+			mDisplayType = TextCommand;
+			mList->deleteObject();
+			mList = NULL;
+			mScroll->deleteObject();
+			mScroll = NULL;
+		}
+	}
+
+	checkForGoodChildren();
+}
+
+void GuiMenuItemCtrl::checkForGoodChildren()
+{
+	if (mDisplayType != Menu)
+	{
+		mHasGoodChildren = true;
+		return;
+	}
+
+	iterator iter;
+	for (iter = begin(); iter != end(); iter++)
+	{
+		GuiMenuItemCtrl *ctrl = static_cast<GuiMenuItemCtrl *>(*iter);
+		if (ctrl->isVisible() && ctrl->isActive() && ctrl->mDisplayType != Spacer)
+		{
+			mHasGoodChildren = true;
+			return;
+		}
+	}
+	mHasGoodChildren = false;
+}
+
+void GuiMenuItemCtrl::closeMenu()
+{
+	if (mOpenSubMenu != NULL)
+	{
+		mOpenSubMenu->closeMenu();
+	}
+	mOpenSubMenu = NULL;
+	mList->mHoveredItem = NULL;
+	mMenuBar->mBackground->removeObject(mScroll);
+	mIsOpen = false;
+}
+
+void GuiMenuItemCtrl::ApplyMenuSettings()
+{
+	if (mDisplayType == Menu)
+	{
+		mScroll->setControlProfile(mMenuBar->mMenuContentProfile);
+		mScroll->setControlThumbProfile(mMenuBar->mThumbProfile);
+		mScroll->setControlArrowProfile(mMenuBar->mArrowProfile);
+		mScroll->setControlTrackProfile(mMenuBar->mTrackProfile);
+		mScroll->setField("hScrollBar", "AlwaysOff");
+		mScroll->setField("vScrollBar", "Dynamic");
+		mScroll->mUseConstantHeightThumb = mMenuBar->mUseConstantHeightThumb;
+		mScroll->mScrollBarThickness = mMenuBar->mScrollBarThickness;
+		mScroll->mShowArrowButtons = mMenuBar->mShowArrowButtons;
+	}
+
+	iterator i;
+	for (i = begin(); i != end(); i++)
+	{
+		GuiMenuItemCtrl *ctrl = static_cast<GuiMenuItemCtrl *>(*i);
+		if (ctrl->isVisible() && ctrl->isActive() && ctrl->mHasGoodChildren)
+		{
+			ctrl->ApplyMenuSettings();
+		}
+	}
+	setControlProfile(mMenuBar->mMenuItemProfile);
+}
+
+void GuiMenuItemCtrl::onRender(Point2I offset, const RectI& updateRect)
+{
+	GuiControlState currentState = GuiControlState::NormalState;
+	if (!mActive || !mHasGoodChildren)
+		currentState = GuiControlState::DisabledState;
+	else if (mIsOpen)
+		currentState = GuiControlState::SelectedState;
+	else if (mIsHover)
+		currentState = GuiControlState::HighlightState;
+
+	RectI ctrlRect = applyMargins(offset, mBounds.extent, currentState, mProfile);
+
+	renderUniversalRect(ctrlRect, mProfile, currentState);
+
+	//Render Text
+	dglSetBitmapModulation(mProfile->getFontColor(currentState));
+	RectI fillRect = applyBorders(ctrlRect.point, ctrlRect.extent, currentState, mProfile);
+	RectI contentRect = applyPadding(fillRect.point, fillRect.extent, currentState, mProfile);
+	renderText(contentRect.point, contentRect.extent, mText, mProfile);
+}
+
+void GuiMenuItemCtrl::toggleControl()
+{
+	if(mDisplayType == Toggle && !mIsOn)
+	{
+		mIsOn = true;
+		Parent::onAction();
+	}
+	else if (mDisplayType == Toggle && mIsOn)
+	{
+		mIsOn = false;
+		execAltConsoleCallback();
+	}
+	else if(mDisplayType == Radio && !mIsOn)
+	{
+		mIsOn = true;
+		Parent::onAction();
+		//Turn off other radio controls in this block
+		turnOffPrevRadio();
+		turnOffNextRadio();
+	}
+}
+
+void GuiMenuItemCtrl::turnOffPrevRadio()
+{
+	if (mPrevItem != NULL && mPrevItem->mDisplayType == Radio)
+	{
+		if(mPrevItem->mIsOn)
+		{
+			mPrevItem->mIsOn = false;
+			mPrevItem->execAltConsoleCallback();
+		}
+		mPrevItem->turnOffPrevRadio();
+	}
+}
+
+void GuiMenuItemCtrl::turnOffNextRadio()
+{
+	if (mNextItem != NULL && mNextItem->mDisplayType == Radio)
+	{
+		if (mNextItem->mIsOn)
+		{
+			mNextItem->mIsOn = false;
+			mNextItem->execAltConsoleCallback();
+		}
+		mNextItem->turnOffNextRadio();
+	}
+}
+
+const char* GuiMenuItemCtrl::getHotKeyText()
+{
+	if(mAcceleratorKey == StringTable->EmptyString || mDisplayType == Menu)
+		return StringTable->EmptyString;
+
+	char key[128];
+	dSprintf(key, 128, "%s", mAcceleratorKey);
+
+	char buffer[128];
+	buffer[0] = '\0';
+	char *tok;
+	tok = dStrtok((char*)key, " -");
+	while (tok != NULL)
+	{
+		if(buffer[0] != '\0')
+			dStrcat(buffer, "+");
+		dStrcat(buffer, ActionMap::swapCtrlForCmd(tok));
+
+		tok = dStrtok(NULL, " -");
+	}
+
+	return StringTable->insert(buffer);
+}
+
+bool GuiMenuItemCtrl::onKeyDown(const GuiEvent &event)
+{
+	if (mOpenSubMenu != NULL && (mOpenSubMenu->mList->mHoveredItem != NULL || mOpenSubMenu->mOpenSubMenu != NULL))
+	{
+		mOpenSubMenu->onKeyDown(event);
+	}
+	else if (event.keyCode == KEY_DOWN && event.modifier == 0)
+	{
+		mMenuBar->mUseKeyMode = true;
+		if (mList->mHoveredItem == NULL || mList->mHoveredItem->mNextItem == NULL)
+		{
+			mList->setHoveredItem(dynamic_cast<GuiMenuItemCtrl *>(first()));
+			if (!mList->mHoveredItem->isVisible() || !mList->mHoveredItem->isActive() || !mList->mHoveredItem->mHasGoodChildren)
+			{
+				onKeyDown(event);
+			}
+		}
+		else if(mList->mHoveredItem->mNextItem->mDisplayType == DisplayType::Spacer || !mList->mHoveredItem->mNextItem->isVisible() || !mList->mHoveredItem->mNextItem->isActive() || !mList->mHoveredItem->mNextItem->mHasGoodChildren)
+		{
+			//To skip the spacer and still do all the needed checks, we'll move the hovered item to the next item and simulate a second down button push
+			mList->setHoveredItem(mList->mHoveredItem->mNextItem);
+			onKeyDown(event);
+		}
+		else
+		{
+			mList->setHoveredItem(mList->mHoveredItem->mNextItem);
+		}
+		return true;
+	}
+	else if (event.keyCode == KEY_UP && event.modifier == 0)
+	{
+		mMenuBar->mUseKeyMode = true;
+		if (mList->mHoveredItem == NULL || mList->mHoveredItem->mPrevItem == NULL)
+		{
+			mList->setHoveredItem(dynamic_cast<GuiMenuItemCtrl *>(last()));
+			if (!mList->mHoveredItem->isVisible() || !mList->mHoveredItem->isActive() || !mList->mHoveredItem->mHasGoodChildren)
+			{
+				onKeyDown(event);
+			}
+		}
+		else if (mList->mHoveredItem->mPrevItem->mDisplayType == DisplayType::Spacer || !mList->mHoveredItem->mPrevItem->isVisible() || !mList->mHoveredItem->mPrevItem->isActive() || !mList->mHoveredItem->mPrevItem->mHasGoodChildren)
+		{
+			//To skip the spacer and still do all the needed checks, we'll move the hovered item to the prev item and simulate a second up button push
+			mList->setHoveredItem(mList->mHoveredItem->mPrevItem);
+			onKeyDown(event);
+		}
+		else
+		{
+			mList->setHoveredItem(mList->mHoveredItem->mPrevItem);
+		}
+		return true;
+	}
+	else if (event.keyCode == KEY_RIGHT && event.modifier == 0)
+	{
+		mMenuBar->mUseKeyMode = true;
+		if (mList->mHoveredItem == NULL)
+		{
+			//loop to find the first valid menu item
+			GuiMenuItemCtrl *foundCtrl = NULL;
+			iterator iter;
+			for (iter = begin(); iter != end(); iter++)
+			{
+				GuiMenuItemCtrl *ctrl = static_cast<GuiMenuItemCtrl *>(*iter);
+				if (ctrl->isVisible() && ctrl->isActive() && ctrl->mDisplayType != Spacer && ctrl->mHasGoodChildren )
+				{
+					foundCtrl = ctrl;
+					break;
+				}
+			}
+			if (foundCtrl != NULL)
+			{
+				mList->setHoveredItem(foundCtrl);
+			}
+		}
+		else if (mList->mHoveredItem == mOpenSubMenu)
+		{
+			mOpenSubMenu->onKeyDown(event);
+			mList->mHoveredItem = NULL;
+		}
+		else if(mList->mHoveredItem->mDisplayType == DisplayType::Menu && mList->mHoveredItem->isVisible() && mList->mHoveredItem->isActive() && mList->mHoveredItem->mHasGoodChildren)
+		{
+			mList->processMenuItem(mList->mHoveredItem);
+			mOpenSubMenu->onKeyDown(event);
+			mList->mHoveredItem = NULL;
+		}
+		return true;
+	}
+	else if (event.keyCode == KEY_LEFT && event.modifier == 0)
+	{
+		mMenuBar->mUseKeyMode = true;
+
+		//Is this the open sub menu?
+		GuiMenuItemCtrl *menu = dynamic_cast<GuiMenuItemCtrl *>(getParent());
+		if (menu != NULL && menu->mOpenSubMenu == this)
+		{
+			menu->mList->mHoveredItem = menu->mOpenSubMenu;
+			closeMenu();
+			menu->mOpenSubMenu = NULL;
+		}
+		return true;
+	}
+	else if (event.keyCode == KEY_RETURN && event.modifier == 0)
+	{
+		mMenuBar->mUseKeyMode = true;
+		if (mList->mHoveredItem == NULL)
+		{
+			mList->setHoveredItem(dynamic_cast<GuiMenuItemCtrl *>(first()));
+		}
+		else
+		{
+			mList->processMenuItem(mList->mHoveredItem);
+		}
+		return true;
+	}
+}
+#pragma endregion
+
+#pragma region GuiMenuBGCtrl
+GuiMenuBGCtrl::GuiMenuBGCtrl(GuiMenuBarCtrl *ctrl)
+{
+	mMenuBarCtrl = ctrl;
+	mBounds.point.set(0, 0);
+	setField("profile", "GuiDefaultProfile");
+}
+
+void GuiMenuBGCtrl::openMenu()
+{
+	GuiMenuItemCtrl *menu = mMenuBarCtrl->mOpenMenu;
+	if (menu == NULL)
+	{
+		return;
+	}
+
+	positionMenu(menu, Point2I(menu->mBounds.point.x, menu->mBounds.point.y + menu->mBounds.extent.y));
+
+	addObject(menu->mScroll);
+}
+
+void GuiMenuBGCtrl::closeMenu()
+{
+	mMenuBarCtrl->closeMenu();
+}
+
+void GuiMenuBGCtrl::openSubMenu(GuiMenuItemCtrl *subMenu)
+{
+	if (subMenu == NULL)
+	{
+		return;
+	}
+
+	GuiMenuItemCtrl *menu = dynamic_cast<GuiMenuItemCtrl *>(subMenu->getParent());
+	if (subMenu == menu->mOpenSubMenu)
+	{
+		return;
+	}
+
+	if(menu->mOpenSubMenu != NULL)
+	{
+		menu->mOpenSubMenu->closeMenu();
+	}
+	menu->mOpenSubMenu = subMenu;
+	subMenu->mIsOpen = true;
+
+	positionMenu(subMenu, Point2I(subMenu->mBounds.point.x + subMenu->mBounds.extent.x - 4, subMenu->mBounds.point.y - 4));
+
+	addObject(subMenu->mScroll);
+
+	menu->mList->mArmSubMenu = false;
+}
+
+void GuiMenuBGCtrl::onTouchMove(const GuiEvent &event)
+{
+	processHover(event);
+}
+
+void GuiMenuBGCtrl::onTouchDragged(const GuiEvent &event)
+{
+	processHover(event);
+}
+
+void GuiMenuBGCtrl::onTouchDown(const GuiEvent &event)
+{
+	mMenuBarCtrl->closeMenu();
+}
+
+void GuiMenuBGCtrl::processHover(const GuiEvent &event)
+{
+	if (mMenuBarCtrl->pointInControl(event.mousePoint))
+	{
+		GuiMenuItemCtrl *menu = mMenuBarCtrl->findHitMenu(globalToLocalCoord(event.mousePoint));
+		if (menu != NULL && mMenuBarCtrl->mOpenMenu != menu)
+		{
+			mMenuBarCtrl->mOpenMenu->closeMenu();
+			mMenuBarCtrl->mOpenMenu = menu;
+			mMenuBarCtrl->mOpenMenu->mIsOpen = true;
+			openMenu();
+			setUpdate();
+		}
+	}
+	mMenuBarCtrl->mUseKeyMode = false;
+}
+
+void GuiMenuBGCtrl::positionMenu(const GuiMenuItemCtrl *menu, const Point2I &topLeft)
+{
+	menu->mList->updateSize();
+	Point2I menuSize = menu->mList->mBounds.extent;
+	RectI box = RectI(topLeft, menuSize);
+	box.extent = getOuterExtent(box.extent, NormalState, menu->mScroll->mProfile);
+
+	//Is it too tall?
+	if ((box.point.y + box.extent.y) > mBounds.extent.y)
+	{
+		//can we move it up?
+		if ((mMenuBarCtrl->mBounds.point.y + mMenuBarCtrl->mBounds.extent.y) < box.point.y)
+		{
+			box.point.y = getMax(mMenuBarCtrl->mBounds.point.y + mMenuBarCtrl->mBounds.extent.y, mBounds.extent.y - box.extent.y);
+		}
+
+		//Is it still too tall?
+		if ((box.point.y + box.extent.y) > mBounds.extent.y)
+		{
+			box.extent.y = mBounds.extent.y - box.point.y;
+			box.extent.x += menu->mScroll->mScrollBarThickness;
+		}
+	}
+
+	//Is it too far to the right?
+	if ((box.point.x + box.extent.x) > mBounds.extent.x)
+	{
+		box.point.x = mBounds.extent.x - box.extent.x;
+	}
+
+	menu->mScroll->mBounds.extent = box.extent;
+	menu->mScroll->mBounds.point = box.point;
+}
+
+#pragma endregion
+
+#pragma region GuiMenuListCtrl
+GuiMenuListCtrl::GuiMenuListCtrl(GuiMenuItemCtrl *ctrl)
+{
+	mMenu = ctrl;
+	mBounds.point.set(0,0);
+	mHoveredItem = NULL;
+	mEnterItemTime = 0;
+	mSubMenuStallTime = 500;
+}
+
+void GuiMenuListCtrl::onTouchMove(const GuiEvent &event)
+{
+	Parent::onTouchMove(event);
+	mMenu->mMenuBar->mUseKeyMode = false;
+}
+
+GuiMenuItemCtrl* GuiMenuListCtrl::GetHitItem(const Point2I &pt)
+{
+	iterator iter;
+	for (iter = mMenu->begin(); iter != mMenu->end(); iter++)
+	{
+		GuiMenuItemCtrl *ctrl = static_cast<GuiMenuItemCtrl *>(*iter);
+		if (!ctrl->mVisible) continue;
+
+		if (ctrl->pointInControl(pt))
+		{
+			return ctrl;
+		}
+	}
+	return nullptr;
+}
+
+void GuiMenuListCtrl::onPreRender()
+{
+	U32 currentTime = Platform::getVirtualMilliseconds();
+	if (mArmSubMenu && mHoveredItem != NULL && mHoveredItem != mMenu->mOpenSubMenu && (currentTime - mEnterItemTime) > mSubMenuStallTime)
+	{
+		//Close an open sub menu 
+		if (mMenu->mOpenSubMenu != NULL)
+		{
+			mMenu->mOpenSubMenu->closeMenu();
+			mMenu->mOpenSubMenu = NULL;
+		}
+
+		//Open a sub menu
+		if (mHoveredItem->mDisplayType == GuiMenuItemCtrl::DisplayType::Menu)
+		{
+			processMenuItem(mHoveredItem);
+		}
+	}
+}
+
+void GuiMenuListCtrl::onRender(Point2I offset, const RectI &updateRect)
+{
+	bool foundHoveredItem = false;
+	iterator iter;
+	S32 h = 0;
+	for (iter = mMenu->begin(); iter != mMenu->end(); iter++)
+	{
+		GuiMenuItemCtrl *ctrl = static_cast<GuiMenuItemCtrl *>(*iter);
+
+		if (!ctrl->mVisible) continue;
+
+		S32 top = h;
+		S32 bottom = h;
+		if (ctrl->mDisplayType == GuiMenuItemCtrl::DisplayType::Spacer)
+		{
+			 bottom += mSpacerSize.y;
+		}
+		else
+		{
+			bottom += mItemSize.y;
+		}
+
+		// Only render visible items
+		if (bottom + offset.y < updateRect.point.y)
+			continue;
+
+		// Break out once we're no longer in visible item range
+		if (top + offset.y >= updateRect.point.y + updateRect.extent.y)
+			break;
+
+		RectI itemRect;
+		if (ctrl->mDisplayType == GuiMenuItemCtrl::DisplayType::Spacer)
+		{
+			itemRect = RectI(offset.x, offset.y + top, mSpacerSize.x, mSpacerSize.y);
+		}
+		else
+		{
+			itemRect = RectI(offset.x, offset.y + top, mItemSize.x, mItemSize.y);
+		}
+
+		// Render our item
+		foundHoveredItem |= onRenderItem(itemRect, ctrl);
+
+		h = bottom;
+	}
+
+	if (!foundHoveredItem)
+	{
+		mHoveredItem = NULL;
+	}
+}
+
+bool GuiMenuListCtrl::onRenderItem(RectI &itemRect, GuiMenuItemCtrl *item)
+{
+	GuiControlProfile *profile = item->mProfile;
+	if (!profile)
+		return false;
+
+	if (item->mBounds != itemRect)
+	{
+		item->mBounds = itemRect;
+	}
+
+	Point2I cursorPt = Point2I(0, 0);
+	GuiCanvas *root = getRoot();
+	if (root)
+	{
+		cursorPt = root->getCursorPos();
+	}
+
+	//is this item being hovered?
+	bool foundHoveredItem = false;
+	if (mMenu->mMenuBar->mUseKeyMode && mHoveredItem == item)
+	{
+		foundHoveredItem = true;
+	}
+	else if (!mMenu->mMenuBar->mUseKeyMode && itemRect.pointInRect(cursorPt) && (mMenu->mOpenSubMenu == NULL || !mMenu->mOpenSubMenu->mScroll->mBounds.pointInRect(cursorPt)))
+	{
+		if (mHoveredItem != item)
+		{
+			setHoveredItem(item);
+		}
+		foundHoveredItem = true;
+	}
+
+	//Get the current state
+	GuiControlState currentState = GuiControlState::NormalState;
+	if (!item->mActive || !item->mHasGoodChildren)
+		currentState = GuiControlState::DisabledState;
+	else if (item->mDisplayType == GuiMenuItemCtrl::DisplayType::Spacer)
+		currentState = GuiControlState::SelectedState;
+	else if (mHoveredItem == item || 
+		(item->mIsOpen && (mMenu->mMenuBar->mUseKeyMode || !mMenu->mScroll->mBounds.pointInRect(cursorPt) || mMenu->mOpenSubMenu->mScroll->mBounds.pointInRect(cursorPt))))
+		currentState = GuiControlState::HighlightState;
+	RectI ctrlRect = applyMargins(itemRect.point, itemRect.extent, currentState, profile);
+
+	if (!ctrlRect.isValidRect())
+	{
+		return foundHoveredItem;
+	}
+
+	renderUniversalRect(ctrlRect, profile, currentState);
+
+	//Render Text
+	dglSetBitmapModulation(profile->getFontColor(currentState));
+	RectI fillRect = applyBorders(ctrlRect.point, ctrlRect.extent, currentState, profile);
+	RectI contentRect = applyPadding(fillRect.point, fillRect.extent, currentState, profile);
+
+	if(contentRect.isValidRect())
+	{
+		//Left Icon
+		RectI leftIconRect = RectI(itemRect.point, Point2I(itemRect.extent.y, itemRect.extent.y));
+		if(item->mDisplayType == GuiMenuItemCtrl::DisplayType::Toggle)
+		{
+			ColorI itemColor = item->mIsOn ? profile->getFillColor(HighlightState) : profile->getFillColor(NormalState);
+			S32 size = profile->mFont->getHeight();
+			renderColorBullet(leftIconRect, itemColor, getMin(size, 16));
+		}
+		else if (item->mDisplayType == GuiMenuItemCtrl::DisplayType::Radio)
+		{
+			ColorI itemColor = item->mIsOn ? profile->getFillColor(HighlightState) : profile->getFillColor(NormalState);
+			S32 size = profile->mFont->getHeight();
+			renderColorBullet(leftIconRect, itemColor, getMin(size, 16), true);
+		}
+
+		//Right Icon
+		RectI rightIconRect = RectI(Point2I(itemRect.point.x + itemRect.extent.x - itemRect.extent.y, itemRect.point.y), leftIconRect.extent);
+		if (item->mDisplayType == GuiMenuItemCtrl::DisplayType::Menu)
+		{
+			S32 size = (profile->mFont->getHeight() / 2);
+			rightIconRect.inset(2, 0);
+			renderTriangleIcon(rightIconRect, ColorI(profile->getFontColor(currentState)), GuiDirection::Right, size);
+		}
+
+		//Text Space
+		RectI textRect = RectI(itemRect.point.x + itemRect.extent.y, itemRect.point.y, itemRect.extent.x - (2 * itemRect.extent.y), itemRect.extent.y);
+
+		//Command Description
+		profile->mAlignment = GuiControlProfile::AlignmentType::LeftAlign;
+		renderText(textRect.point, textRect.extent, item->getText(), profile);
+
+		//Hot Keys!!
+		profile->mAlignment = GuiControlProfile::AlignmentType::RightAlign;
+		renderText(textRect.point, textRect.extent, item->getHotKeyText(), profile);
+	}
+
+	return foundHoveredItem;
+}
+
+void GuiMenuListCtrl::updateSize()
+{
+	if(mMenu->size() == 0)
+	{
+		resize(mBounds.extent, Point2I(100, 20));
+		return;
+	}
+
+	GuiMenuItemCtrl *child = dynamic_cast<GuiMenuItemCtrl *>(mMenu->first());
+	if (!child)
+		return;
+
+	GuiControlProfile *profile = child->mProfile;
+	if (!profile)
+		return;
+
+	GFont *font = profile->mFont;
+	Point2I contentSize = Point2I(10, font->getHeight() + 2);
+	Point2I spacerSize = Point2I(10, 0);
+
+	// Find the maximum width cell:
+	mItemCount = 0;
+	mSpacerCount = 0;
+	S32 maxWidth = 1;
+	iterator i;
+	for (i = mMenu->begin(); i != mMenu->end(); i++)
+	{
+		GuiMenuItemCtrl *ctrl = static_cast<GuiMenuItemCtrl *>(*i);
+
+		if(!ctrl->mVisible) continue;
+
+		S32 width = font->getStrWidth(ctrl->getText());
+		if(ctrl->mDisplayType != GuiMenuItemCtrl::DisplayType::Menu && ctrl->mDisplayType != GuiMenuItemCtrl::DisplayType::Spacer)
+		{
+			StringTableEntry hotKey = ctrl->getHotKeyText();
+			if(hotKey != StringTable->EmptyString)
+			{
+				width += font->getStrWidth(hotKey) + 30;
+			}
+		}
+		
+		if (width > maxWidth)
+			maxWidth = width;
+
+		if (ctrl->mDisplayType == GuiMenuItemCtrl::DisplayType::Spacer)
+		{
+			mSpacerCount++;
+		}
+		else
+		{
+			mItemCount++;
+		}
+	}
+	contentSize.x = maxWidth;
+	spacerSize.x = contentSize.x;
+
+	mItemSize = this->getOuterExtent(contentSize, NormalState, profile);
+	mSpacerSize = this->getOuterExtent(spacerSize, SelectedState, profile);
+	
+	//Add a square of space at both ends for icons
+	mItemSize.x += (2 * mItemSize.y);
+	mSpacerSize.x += (2 * mItemSize.y);
+
+	Point2I newExtent = Point2I(mItemSize.x, (mItemSize.y * mItemCount) + (mSpacerSize.y * mSpacerCount));
+
+	resize(mBounds.point, newExtent);
+}
+
+void GuiMenuListCtrl::onTouchUp(const GuiEvent &event)
+{
+	GuiMenuItemCtrl *ctrl = GetHitItem(event.mousePoint);
+	if (ctrl != nullptr )
+	{
+		processMenuItem(ctrl);
+	}
+}
+
+void GuiMenuListCtrl::processMenuItem(GuiMenuItemCtrl *ctrl)
+{
+	if(!ctrl->mActive || ctrl->mDisplayType == GuiMenuItemCtrl::DisplayType::Spacer || !ctrl->mHasGoodChildren)
+		return;
+
+	ctrl->onAction();
+
+	GuiScrollCtrl* parent = dynamic_cast<GuiScrollCtrl *>(getParent());
+	if (parent)
+	{
+		GuiMenuBGCtrl* grandParent = dynamic_cast<GuiMenuBGCtrl *>(parent->getParent());
+		if (grandParent)
+		{
+			if (ctrl->mDisplayType != GuiMenuItemCtrl::DisplayType::Menu)
+			{
+				grandParent->closeMenu();
+			}
+			else
+			{
+				grandParent->openSubMenu(ctrl);
+
+			}
+		}
+	}
+}
+
+#pragma endregion

+ 223 - 0
engine/source/gui/editor/guiMenuBarCtrl.h

@@ -0,0 +1,223 @@
+//-----------------------------------------------------------------------------
+// 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 _GUIMENUBARCTRL_H_
+#define _GUIMENUBARCTRL_H_
+
+#ifndef _SIMBASE_H_
+#include "sim/simBase.h"
+#endif
+#ifndef _GUITYPES_H_
+#include "gui/guiTypes.h"
+#endif
+#ifndef _GUICONTROL_H_
+#include "gui/guiControl.h"
+#endif
+#ifndef _GUISCROLLCTRL_H_
+#include "gui/containers/guiScrollCtrl.h"
+#endif
+
+class GuiMenuItemCtrl;
+class GuiMenuBGCtrl;
+class GuiMenuListCtrl;
+
+class GuiMenuBarCtrl : public GuiControl
+{
+private:
+   typedef GuiControl Parent;
+
+public:
+   //creation methods
+   DECLARE_CONOBJECT(GuiMenuBarCtrl);
+   GuiMenuBarCtrl();
+   static void initPersistFields();
+
+   virtual void childResized(GuiControl *child);
+   virtual void resize(const Point2I &newPosition, const Point2I &newExtent);
+   virtual void inspectPostApply();
+   virtual void onChildAdded(GuiControl *child);
+   virtual void onChildRemoved(SimObject *child);
+   virtual void calculateMenus();
+   virtual GuiControl* findHitControl(const Point2I &pt, S32 initialLayer);
+   virtual GuiMenuItemCtrl* findHitMenu(const Point2I &pt);
+   virtual void onRender(Point2I offset, const RectI &updateRect);
+
+   virtual void processHover(const GuiEvent &event);
+   virtual void setHoverTarget(GuiMenuItemCtrl *ctrl);
+   virtual void onTouchMove(const GuiEvent &event);
+   virtual void onTouchEnter(const GuiEvent &event);
+   virtual void onTouchLeave(const GuiEvent &event);
+   virtual void onTouchDown(const GuiEvent &event);
+
+   void openMenu();
+   void closeMenu();
+   void ApplyMenuSettings();
+
+   bool mUseKeyMode;
+   virtual void acceleratorKeyPress(U32 index);
+   virtual bool onKeyDown(const GuiEvent &event);
+
+   GuiControlProfile *mMenuProfile;
+   GuiControlProfile *mMenuContentProfile;
+   GuiControlProfile *mMenuItemProfile;
+   GuiControlProfile *mBackgroundProfile;
+   GuiControlProfile *mThumbProfile;
+   GuiControlProfile *mArrowProfile;
+   GuiControlProfile *mTrackProfile;
+
+   bool onWake();
+   void onSleep();
+   void setControlBackgroundProfile(GuiControlProfile* prof);
+   void setControlMenuProfile(GuiControlProfile* prof);
+   void setControlMenuItemProfile(GuiControlProfile* prof);
+   void setControlMenuContentProfile(GuiControlProfile* prof);
+   void setControlThumbProfile(GuiControlProfile* prof);
+   void setControlArrowProfile(GuiControlProfile* prof);
+   void setControlTrackProfile(GuiControlProfile* prof);
+
+   S32 mScrollBarThickness;
+   bool mShowArrowButtons;
+   bool mUseConstantHeightThumb;
+
+   GuiMenuItemCtrl *mHoverTarget;
+   GuiMenuItemCtrl *mOpenMenu;
+   GuiMenuBGCtrl *mBackground;
+};
+
+class GuiMenuItemCtrl : public GuiControl
+{
+private:
+	typedef GuiControl Parent;
+
+public:
+	//creation methods
+	DECLARE_CONOBJECT(GuiMenuItemCtrl);
+	GuiMenuItemCtrl();
+	static void initPersistFields();
+
+	enum DisplayType
+	{
+		TextCommand = 0,
+		Toggle,
+		Radio,
+		Spacer,
+		Menu
+	};
+
+	DisplayType			mDisplayType;
+	bool				mIsOpen;
+	bool				mIsHover;
+	bool				mIsOn;
+	bool				mToggle;
+	bool				mRadio;
+	bool				mHasGoodChildren;
+
+	static bool setToggle(void *obj, const char *data) 
+	{ 
+		GuiMenuItemCtrl* pCastObject = static_cast<GuiMenuItemCtrl *>(obj);
+		pCastObject->mToggle = dAtob(data);
+		pCastObject->mDisplayType = pCastObject->mToggle ? Toggle : TextCommand; 
+		return false; 
+	}
+	static bool writeToggle(void* obj, StringTableEntry pFieldName) { return static_cast<GuiMenuItemCtrl*>(obj)->mToggle; }
+
+	static bool setRadio(void *obj, const char *data)
+	{
+		GuiMenuItemCtrl* pCastObject = static_cast<GuiMenuItemCtrl *>(obj);
+		pCastObject->mRadio = dAtob(data);
+		pCastObject->mDisplayType = pCastObject->mRadio ? Radio : TextCommand;
+		return false;
+	}
+	static bool writeRadio(void* obj, StringTableEntry pFieldName) { return static_cast<GuiMenuItemCtrl*>(obj)->mRadio; }
+	static bool writeIsOn(void* obj, StringTableEntry pFieldName) { GuiMenuItemCtrl* pCastObject = static_cast<GuiMenuItemCtrl *>(obj); return pCastObject->mToggle || pCastObject->mRadio; }
+
+	GuiMenuBarCtrl *mMenuBar;
+	GuiScrollCtrl *mScroll;
+	GuiMenuListCtrl *mList;
+
+	GuiMenuItemCtrl *mPrevItem;
+	GuiMenuItemCtrl *mNextItem;
+	GuiMenuItemCtrl *mOpenSubMenu;
+
+	virtual void onAction();
+	virtual void inspectPostApply();
+	virtual void onChildAdded(GuiControl *child);
+	virtual void onChildRemoved(SimObject *child);
+	void checkForGoodChildren();
+	virtual void closeMenu();
+	void ApplyMenuSettings();
+	virtual void onRender(Point2I offset, const RectI &updateRect);
+	virtual const char* getHotKeyText();
+	virtual void toggleControl();
+	virtual void turnOffPrevRadio();
+	virtual void turnOffNextRadio();
+	virtual bool onKeyDown(const GuiEvent &event);
+};
+
+class GuiMenuBGCtrl : public GuiControl
+{
+protected:
+	typedef GuiControl Parent;
+	GuiMenuBarCtrl *mMenuBarCtrl;
+public:
+	GuiMenuBGCtrl(GuiMenuBarCtrl *ctrl);
+	void openMenu();
+	void closeMenu();
+	void openSubMenu(GuiMenuItemCtrl *subMenu);
+	virtual void onTouchMove(const GuiEvent &event);
+	virtual void onTouchDragged(const GuiEvent &event);
+	virtual void processHover(const GuiEvent &event);
+	virtual void onTouchDown(const GuiEvent &event);
+private:
+	void positionMenu(const GuiMenuItemCtrl *menu, const Point2I &topLeft);
+};
+
+class GuiMenuListCtrl : public GuiControl
+{
+protected:
+	typedef GuiControl Parent;
+	GuiMenuItemCtrl *mMenu;
+public:
+	GuiMenuListCtrl(GuiMenuItemCtrl *ctrl);
+	virtual void onTouchMove(const GuiEvent &event);
+	GuiMenuItemCtrl* GetHitItem(const Point2I &pt);
+	virtual void onPreRender();
+	void onRender(Point2I offset, const RectI &updateRect);
+	bool onRenderItem(RectI &itemRect, GuiMenuItemCtrl *item);
+	void updateSize();
+
+	Point2I mItemSize;
+	Point2I	mSpacerSize;
+	S32 mItemCount;
+	S32 mSpacerCount;
+	U32 mEnterItemTime;
+	U32 mSubMenuStallTime;
+	GuiMenuItemCtrl *mHoveredItem;
+	bool mArmSubMenu;
+
+	inline void setHoveredItem(GuiMenuItemCtrl *item) { mEnterItemTime = Platform::getVirtualMilliseconds(); mHoveredItem = item; mArmSubMenu = true; }
+
+	virtual void onTouchUp(const GuiEvent &event);
+	void processMenuItem(GuiMenuItemCtrl *ctrl);
+};
+
+#endif

+ 109 - 0
engine/source/gui/editor/guiMenuBarCtrl_ScriptBinding.h

@@ -0,0 +1,109 @@
+//-----------------------------------------------------------------------------
+// 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(GuiMenuBarCtrl, GuiControl)
+
+/*! Sets the currently used BackgroundProfile for the GuiControl
+	@param p The BackgroundProfile applies to the the entire screen behind the open menu.
+	@return No return value
+*/
+ConsoleMethodWithDocs(GuiMenuBarCtrl, setBackgroundProfile, ConsoleVoid, 3, 3, (GuiControlProfile p))
+{
+	GuiControlProfile* profile;
+
+	if (Sim::findObject(argv[2], profile))
+		object->setControlBackgroundProfile(profile);
+}
+
+/*! Sets the currently used MenuProfile for the GuiControl
+	@param p The MenuProfile is applied to each top level menu item.
+	@return No return value
+*/
+ConsoleMethodWithDocs(GuiMenuBarCtrl, setMenuProfile, ConsoleVoid, 3, 3, (GuiControlProfile p))
+{
+	GuiControlProfile* profile;
+
+	if (Sim::findObject(argv[2], profile))
+		object->setControlMenuProfile(profile);
+}
+
+/*! Sets the currently used MenuItemProfile for the GuiControl
+	@param p The MenuItemProfile is applied to each menu item.
+	@return No return value
+*/
+ConsoleMethodWithDocs(GuiMenuBarCtrl, setMenuItemProfile, ConsoleVoid, 3, 3, (GuiControlProfile p))
+{
+	GuiControlProfile* profile;
+
+	if (Sim::findObject(argv[2], profile))
+		object->setControlMenuItemProfile(profile);
+}
+
+/*! Sets the currently used MenuContentProfile for the GuiControl
+	@param p The MenuContentProfile is applied the menu box that opens.
+	@return No return value
+*/
+ConsoleMethodWithDocs(GuiMenuBarCtrl, setMenuContentProfile, ConsoleVoid, 3, 3, (GuiControlProfile p))
+{
+	GuiControlProfile* profile;
+
+	if (Sim::findObject(argv[2], profile))
+		object->setControlMenuContentProfile(profile);
+}
+
+/*! Sets the currently used ThumbProfile for the GuiControl
+	@param p The ThumbProfile is applied to the thumb of the scrollbar.
+	@return No return value
+*/
+ConsoleMethodWithDocs(GuiMenuBarCtrl, setThumbProfile, ConsoleVoid, 3, 3, (GuiControlProfile p))
+{
+	GuiControlProfile* profile;
+
+	if (Sim::findObject(argv[2], profile))
+		object->setControlThumbProfile(profile);
+}
+
+/*! Sets the currently used TrackProfile for the GuiControl
+	@param p The TrackProfile is applied to the track area used by the scroll thumb.
+	@return No return value
+*/
+ConsoleMethodWithDocs(GuiMenuBarCtrl, setTrackProfile, ConsoleVoid, 3, 3, (GuiControlProfile p))
+{
+	GuiControlProfile* profile;
+
+	if (Sim::findObject(argv[2], profile))
+		object->setControlTrackProfile(profile);
+}
+
+/*! Sets the currently used ArrowProfile for the GuiControl
+	@param p The ArrowProfile is applied to the arrow buttons of the scrollbar if you turn them on.
+	@return No return value
+*/
+ConsoleMethodWithDocs(GuiMenuBarCtrl, setArrowProfile, ConsoleVoid, 3, 3, (GuiControlProfile p))
+{
+	GuiControlProfile* profile;
+
+	if (Sim::findObject(argv[2], profile))
+		object->setControlArrowProfile(profile);
+}
+
+ConsoleMethodGroupEndWithDocs(GuiMenuBarCtrl)

+ 1 - 1
engine/source/gui/guiCanvas.cc

@@ -371,7 +371,7 @@ bool GuiCanvas::processInputEvent(const InputEvent *event)
          //if not handled, search for an accelerator
          //if not handled, search for an accelerator
          for (U32 i = 0; i < (U32)mAcceleratorMap.size(); i++)
          for (U32 i = 0; i < (U32)mAcceleratorMap.size(); i++)
          {
          {
-            if ((U32)mAcceleratorMap[i].keyCode == (U32)event->objInst && (U32)mAcceleratorMap[i].modifier == eventModifier)
+            if ((U32)mAcceleratorMap[i].IsKeyCodeEqual(event->objInst) && (U32)mAcceleratorMap[i].modifier == eventModifier)
             {
             {
                mAcceleratorMap[i].ctrl->acceleratorKeyPress(mAcceleratorMap[i].index);
                mAcceleratorMap[i].ctrl->acceleratorKeyPress(mAcceleratorMap[i].index);
                return true;
                return true;

+ 9 - 0
engine/source/gui/guiCanvas.h

@@ -160,6 +160,15 @@ protected:
       U32 index;
       U32 index;
       U32 keyCode;
       U32 keyCode;
       U32 modifier;
       U32 modifier;
+
+	  inline bool IsKeyCodeEqual(U32 testCode)
+	  {
+		  return (testCode == keyCode ||
+			  (keyCode == KEY_ALT && (testCode == KEY_RALT || testCode == KEY_LALT)) ||
+			  (keyCode == KEY_SHIFT && (testCode == KEY_RSHIFT || testCode == KEY_LSHIFT)) || 
+			  (keyCode == KEY_CONTROL && (testCode == KEY_RCONTROL || testCode == KEY_LCONTROL)) || 
+			  (keyCode == KEY_MAC_OPT && (testCode == KEY_MAC_ROPT || testCode == KEY_MAC_LOPT)));
+	  }
    };
    };
    Vector <AccKeyMap> mAcceleratorMap;
    Vector <AccKeyMap> mAcceleratorMap;
 
 

+ 0 - 1
engine/source/gui/guiControl.cc

@@ -151,7 +151,6 @@ void GuiControl::initPersistFields()
 {
 {
    Parent::initPersistFields();
    Parent::initPersistFields();
 
 
-
    // Things relevant only to the editor.
    // Things relevant only to the editor.
    addGroup("Gui Editing");
    addGroup("Gui Editing");
    addField("isContainer",       TypeBool,      Offset(mIsContainer, GuiControl));
    addField("isContainer",       TypeBool,      Offset(mIsContainer, GuiControl));

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

@@ -729,8 +729,8 @@ public:
 	/// Returns the extent of the outer rect given the extent of the inner rect.
 	/// Returns the extent of the outer rect given the extent of the inner rect.
 	Point2I getOuterExtent(Point2I innerExtent, GuiControlState currentState, GuiControlProfile *profile);
 	Point2I getOuterExtent(Point2I innerExtent, GuiControlState currentState, GuiControlProfile *profile);
 
 
-    void inspectPostApply();
-    void inspectPreApply();
+    virtual void inspectPostApply();
+    virtual void inspectPreApply();
 
 
 protected:
 protected:
 	virtual void interpolateTick(F32 delta) {};
 	virtual void interpolateTick(F32 delta) {};

+ 38 - 9
engine/source/gui/guiDefaultControlRender.cc

@@ -356,7 +356,7 @@ void renderStretchedImageAsset(RectI &bounds, U8 frame, GuiControlProfile *profi
 //Renders a color bullet at or one pixel smaller than maxSize.
 //Renders a color bullet at or one pixel smaller than maxSize.
 //It shrinks the given box until it is less than or equal to the 
 //It shrinks the given box until it is less than or equal to the 
 //maxSize in the x direction.
 //maxSize in the x direction.
-void renderColorBullet(RectI &bounds, ColorI &color, S32 maxSize)
+void renderColorBullet(RectI &bounds, ColorI &color, S32 maxSize, bool useCircle)
 {
 {
 	if (bounds.extent.x > maxSize)
 	if (bounds.extent.x > maxSize)
 	{
 	{
@@ -367,16 +367,27 @@ void renderColorBullet(RectI &bounds, ColorI &color, S32 maxSize)
 	{
 	{
 		return;
 		return;
 	}
 	}
-	dglDrawRectFill(bounds, ColorI(0, 0, 0, 100));
-	bounds.inset(1, 1);
-	if (!bounds.isValidRect())
+
+	if(!useCircle)
 	{
 	{
-		return;
+		dglDrawRectFill(bounds, ColorI(0, 0, 0, 100));
+		bounds.inset(1, 1);
+		if (!bounds.isValidRect())
+		{
+			return;
+		}
+		dglDrawRectFill(bounds, color);
+	}
+	else
+	{
+		Point2I center = Point2I(bounds.point.x + (bounds.extent.x / 2), bounds.point.y + (bounds.extent.y / 2));
+		F32 radius = (F32)(bounds.extent.x / 2);
+		dglDrawCircleFill(center, radius, ColorI(0, 0, 0, 100));
+		dglDrawCircleFill(center, radius-1, color);
 	}
 	}
-	dglDrawRectFill(bounds, color);
 }
 }
 
 
-void renderTriangleIcon(RectI &bounds, ColorI &color, bool pointsUp, S32 maxSize)
+void renderTriangleIcon(RectI &bounds, ColorI &color, GuiDirection pointsToward, S32 maxSize)
 {
 {
 	if (bounds.extent.x > maxSize)
 	if (bounds.extent.x > maxSize)
 	{
 	{
@@ -388,7 +399,7 @@ void renderTriangleIcon(RectI &bounds, ColorI &color, bool pointsUp, S32 maxSize
 		return;
 		return;
 	}
 	}
 
 
-	if (pointsUp)
+	if (pointsToward == GuiDirection::Up)
 	{
 	{
 		dglDrawTriangleFill(
 		dglDrawTriangleFill(
 			Point2I(bounds.point.x, bounds.point.y + bounds.extent.y),
 			Point2I(bounds.point.x, bounds.point.y + bounds.extent.y),
@@ -397,7 +408,7 @@ void renderTriangleIcon(RectI &bounds, ColorI &color, bool pointsUp, S32 maxSize
 			color
 			color
 		);
 		);
 	}
 	}
-	else
+	else if (pointsToward == GuiDirection::Down)
 	{
 	{
 		dglDrawTriangleFill(
 		dglDrawTriangleFill(
 			bounds.point,
 			bounds.point,
@@ -406,4 +417,22 @@ void renderTriangleIcon(RectI &bounds, ColorI &color, bool pointsUp, S32 maxSize
 			color
 			color
 		);
 		);
 	}
 	}
+	else if (pointsToward == GuiDirection::Right)
+	{
+		dglDrawTriangleFill(
+			bounds.point,
+			Point2I(bounds.point.x, bounds.point.y + bounds.extent.y),
+			Point2I(bounds.point.x + bounds.extent.x, bounds.point.y + (bounds.extent.y / 2)),
+			color
+		);
+	}
+	else if (pointsToward == GuiDirection::Left)
+	{
+		dglDrawTriangleFill(
+			Point2I(bounds.point.x + bounds.extent.x, bounds.point.y),
+			Point2I(bounds.point.x, bounds.point.y + (bounds.extent.y / 2)),
+			Point2I(bounds.point.x + bounds.extent.x, bounds.point.y + bounds.extent.y),
+			color
+		);
+	}
 }
 }

+ 2 - 2
engine/source/gui/guiDefaultControlRender.h

@@ -39,7 +39,7 @@ void renderSizableBorderedTexture(RectI &bounds, TextureHandle &texture, RectI &
 void renderFixedBitmapBordersFilled(RectI &bounds, S32 baseMultiplier, GuiControlProfile *profile);
 void renderFixedBitmapBordersFilled(RectI &bounds, S32 baseMultiplier, GuiControlProfile *profile);
 void renderStretchedBitmap(RectI &bounds, U8 frame, GuiControlProfile *profile);
 void renderStretchedBitmap(RectI &bounds, U8 frame, GuiControlProfile *profile);
 void renderStretchedImageAsset(RectI &bounds, U8 frame, GuiControlProfile *profile);
 void renderStretchedImageAsset(RectI &bounds, U8 frame, GuiControlProfile *profile);
-void renderColorBullet(RectI &bounds, ColorI &color, S32 maxSize);
-void renderTriangleIcon(RectI &bounds, ColorI &color, bool pointsUp, S32 maxSize);
+void renderColorBullet(RectI &bounds, ColorI &color, S32 maxSize, bool useCircle = false);
+void renderTriangleIcon(RectI &bounds, ColorI &color, GuiDirection pointsToward, S32 maxSize);
 
 
 #endif
 #endif

+ 1 - 2
engine/source/gui/guiListBoxCtrl.cc

@@ -69,6 +69,7 @@ bool GuiListBoxCtrl::onWake()
 void GuiListBoxCtrl::addObject(SimObject *obj)
 void GuiListBoxCtrl::addObject(SimObject *obj)
 {
 {
 	AssertWarn(0, "GuiListBoxCtrl::addObject: cannot add children to the GuiListBoxCtrl. It is not a container. Child was not added.");
 	AssertWarn(0, "GuiListBoxCtrl::addObject: cannot add children to the GuiListBoxCtrl. It is not a container. Child was not added.");
+	removeObject(obj);
 }
 }
 
 
 #pragma region ItemAccessors
 #pragma region ItemAccessors
@@ -627,8 +628,6 @@ void GuiListBoxCtrl::onRender( Point2I offset, const RectI &updateRect )
 
 
 	for ( S32 i = 0; i < mItems.size(); i++)
 	for ( S32 i = 0; i < mItems.size(); i++)
 	{
 	{
-		S32 colorBoxSize = 0;
-		ColorI boxColor = ColorI(0, 0, 0);
 		// Only render visible items
 		// Only render visible items
 		if ((i + 1) * mItemSize.y + offset.y < updateRect.point.y)
 		if ((i + 1) * mItemSize.y + offset.y < updateRect.point.y)
 		continue;
 		continue;

+ 0 - 5
engine/source/gui/guiProgressCtrl.h

@@ -27,11 +27,6 @@
 #include "gui/guiControl.h"
 #include "gui/guiControl.h"
 #endif
 #endif
 
 
-#ifndef _GUITEXTCTRL_H_
-#include "gui/guiTextCtrl.h"
-#endif
-
-
 class GuiProgressCtrl : public GuiControl, public Fluid
 class GuiProgressCtrl : public GuiControl, public Fluid
 {
 {
 private:
 private:

+ 10 - 2
engine/source/input/actionMap.cc

@@ -314,7 +314,7 @@ bool ActionMap::createEventDescriptor(const char* pEventString, EventDescriptor*
             pDescriptor->flags |= SI_LSHIFT;
             pDescriptor->flags |= SI_LSHIFT;
          } else if (dStricmp(pModifier, "rshift") == 0) {
          } else if (dStricmp(pModifier, "rshift") == 0) {
             pDescriptor->flags |= SI_RSHIFT;
             pDescriptor->flags |= SI_RSHIFT;
-         } else if (dStricmp(pModifier, "ctrl") == 0) {
+         } else if (dStricmp(swapCtrlForCmd(pModifier), "ctrl") == 0) {
             pDescriptor->flags |= SI_CTRL;
             pDescriptor->flags |= SI_CTRL;
          } else if (dStricmp(pModifier, "lctrl") == 0) {
          } else if (dStricmp(pModifier, "lctrl") == 0) {
             pDescriptor->flags |= SI_LCTRL;
             pDescriptor->flags |= SI_LCTRL;
@@ -326,7 +326,7 @@ bool ActionMap::createEventDescriptor(const char* pEventString, EventDescriptor*
             pDescriptor->flags |= SI_LALT;
             pDescriptor->flags |= SI_LALT;
          } else if (dStricmp(pModifier, "ralt") == 0) {
          } else if (dStricmp(pModifier, "ralt") == 0) {
             pDescriptor->flags |= SI_RALT;
             pDescriptor->flags |= SI_RALT;
-         } else if (dStricmp(pModifier, "cmd") == 0) {
+         } else if (dStricmp(swapCtrlForCmd(pModifier), "cmd") == 0) {
             pDescriptor->flags |= SI_ALT;
             pDescriptor->flags |= SI_ALT;
          } else if (dStricmp(pModifier, "opt") == 0) {
          } else if (dStricmp(pModifier, "opt") == 0) {
             pDescriptor->flags |= SI_MAC_OPT;
             pDescriptor->flags |= SI_MAC_OPT;
@@ -414,6 +414,14 @@ bool ActionMap::createEventDescriptor(const char* pEventString, EventDescriptor*
    return false;
    return false;
 }
 }
 
 
+const char* ActionMap::swapCtrlForCmd(const char* input)
+{
+#ifdef TORQUE_OS_OSX
+	return dStrcmp(input, "Ctrl") == 0 ? "Cmd" : input;
+#endif
+	return input;
+}
+
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 ActionMap::Node* ActionMap::getNode(const U32 inDeviceType, const U32 inDeviceInst,
 ActionMap::Node* ActionMap::getNode(const U32 inDeviceType, const U32 inDeviceInst,
                    const U32 inModifiers,  const U32 inAction,SimObject* object /*= NULL*/)
                    const U32 inModifiers,  const U32 inAction,SimObject* object /*= NULL*/)

+ 1 - 0
engine/source/input/actionMap.h

@@ -146,6 +146,7 @@ class ActionMap : public SimObject
    void dumpActionMap(const char* fileName, const bool append) const;
    void dumpActionMap(const char* fileName, const bool append) const;
 
 
    static bool createEventDescriptor(const char* pEventString, EventDescriptor* pDescriptor);
    static bool createEventDescriptor(const char* pEventString, EventDescriptor* pDescriptor);
+   static const char* swapCtrlForCmd(const char* input); ///< A simple helper function that takes Ctrl and turns it to Cmd on Mac
 
 
    bool processBind(const U32 argc, const char** argv, SimObject* object = NULL);
    bool processBind(const U32 argc, const char** argv, SimObject* object = NULL);
    bool processBindCmd(const char *device, const char *action, const char *makeCmd, const char *breakCmd);
    bool processBindCmd(const char *device, const char *action, const char *makeCmd, const char *breakCmd);

+ 193 - 0
toybox/GuiEditorToy/1/assets/gui/guiEditorCtrl.gui

@@ -75,6 +75,199 @@
 		canSave = "1";
 		canSave = "1";
 		Visible = "1";
 		Visible = "1";
 		hovertime = "1000";
 		hovertime = "1000";
+
+		new GuiMenuBarCtrl(GuiEditorMenuBar) {
+			new GuiMenuItemCtrl() {
+				Text = "File";
+
+				new GuiMenuItemCtrl() {
+					Text = "New Gui...";
+					Command = "GuiEditorStartCreate();";
+					Accelerator = "Ctrl N";
+				};
+				new GuiMenuItemCtrl() {
+					Text = "Open Gui...";
+					Command = "GuiEditorOpenGui();";
+					Accelerator = "Ctrl O";
+				};
+				new GuiMenuItemCtrl() { Text = "-"; };
+				new GuiMenuItemCtrl() {
+					Text = "Save Gui...";
+					Command = "GuiEditorToy.save();";
+					Accelerator = "Ctrl S";
+				};
+			};
+			new GuiMenuItemCtrl() {
+				Text = "Edit";
+
+				new GuiMenuItemCtrl() {
+					Text = "Undo";
+					Command = "GuiEditor.Undo();";
+					Accelerator = "Ctrl Z";
+				};
+				new GuiMenuItemCtrl() {
+					Text = "Redo";
+					Command = "GuiEditor.Redo();";
+					Accelerator = "Ctrl-Shift Z";
+				};
+				new GuiMenuItemCtrl() { Text = "-"; };
+				new GuiMenuItemCtrl() {
+					Text = "Cut";
+					Command = "GuiEditor.Cut();";
+					Accelerator = "Ctrl X";
+				};
+				new GuiMenuItemCtrl() {
+					Text = "Copy";
+					Command = "GuiEditor.Copy();";
+					Accelerator = "Ctrl C";
+				};
+				new GuiMenuItemCtrl() {
+					Text = "Paste";
+					Command = "GuiEditor.Paste();";
+					Accelerator = "Ctrl V";
+				};
+			};
+			new GuiMenuItemCtrl() {
+				Text = "Layout";
+
+				new GuiMenuItemCtrl() {
+					Text = "Align Left";
+					Command = "GuiEditor.Justify(0);";
+					Accelerator = "Ctrl L";
+				};
+				new GuiMenuItemCtrl() {
+					Text = "Align Right";
+					Command = "GuiEditor.Justify(2);";
+					Accelerator = "Ctrl R";
+				};
+				new GuiMenuItemCtrl() {
+					Text = "Align Top";
+					Command = "GuiEditor.Justify(3);";
+					Accelerator = "Ctrl T";
+				};
+				new GuiMenuItemCtrl() {
+					Text = "Align Bottom";
+					Command = "GuiEditor.Justify(4);";
+					Accelerator = "Ctrl B";
+				};
+				new GuiMenuItemCtrl() { Text = "-"; };
+				new GuiMenuItemCtrl() {
+					Text = "Center Horizontally";
+					Command = "GuiEditor.Justify(1);";
+				};
+				new GuiMenuItemCtrl() {
+					Text = "Space Vertically";
+					Command = "GuiEditor.Justify(5);";
+				};
+				new GuiMenuItemCtrl() {
+					Text = "Space Horizontally";
+					Command = "GuiEditor.Justify(6);";
+				};
+				new GuiMenuItemCtrl() { Text = "-"; };
+				new GuiMenuItemCtrl() {
+					Text = "Bring to Front";
+					Command = "GuiEditor.BringToFront();";
+					Accelerator = "Ctrl-Shift Up";
+				};
+				new GuiMenuItemCtrl() {
+					Text = "Push to Back";
+					Command = "GuiEditor.PushToBack();";
+					Accelerator = "Ctrl-Shift Down";
+				};
+				new GuiMenuItemCtrl() { Text = "-"; };
+				new GuiMenuItemCtrl() {
+					Text = "Snap to Grid";
+					Toggle = "1";
+					IsOn = "1";
+					Command = "echo(\"Snap to Grid On!\");";
+					AltCommand = "echo(\"Snap to Grid Off!\");";
+					Accelerator = "Ctrl G";
+				};
+				new GuiMenuItemCtrl() { Text = "-"; };
+				new GuiMenuItemCtrl() {
+					Text = "Radio Test 1";
+					Radio = "1";
+					IsOn = "1";
+					Command = "echo(\"Radio 1 On!\");";
+					AltCommand = "echo(\"Radio 1 Off!\");";
+					Accelerator = "Ctrl 1";
+				};
+				new GuiMenuItemCtrl() {
+					Text = "Radio Test 2";
+					Radio = "1";
+					IsOn = "0";
+					Command = "echo(\"Radio 2 On!\");";
+					AltCommand = "echo(\"Radio 2 Off!\");";
+					Accelerator = "Ctrl 2";
+				};
+				new GuiMenuItemCtrl() {
+					Text = "Radio Test 3";
+					Radio = "1";
+					IsOn = "0";
+					Command = "echo(\"Radio 3 On!\");";
+					AltCommand = "echo(\"Radio 3 Off!\");";
+					Accelerator = "Ctrl 3";
+				};
+				new GuiMenuItemCtrl() { Text = "-"; };
+				new GuiMenuItemCtrl() {
+					Text = "Example Sub Menu 1";
+					new GuiMenuItemCtrl() {
+						Text = "Example Menu Item 1";
+						Command = "echo(\"Example Menu Item 1!\");";
+						Accelerator = "Ctrl K";
+					};
+					new GuiMenuItemCtrl() {
+						Text = "Example Menu Item 2";
+						Command = "echo(\"Example Menu Item 2!\");";
+						Accelerator = "Ctrl-Alt K";
+					};
+				};
+				new GuiMenuItemCtrl() {
+					Text = "Example Sub Menu 2";
+					new GuiMenuItemCtrl() {
+						Text = "Example Menu Item 3";
+						Command = "echo(\"Example Menu Item 3!\");";
+						Accelerator = "Ctrl W";
+					};
+					new GuiMenuItemCtrl() {
+						Text = "Example Menu Item 4";
+						Command = "echo(\"Example Menu Item 4!\");";
+					};
+					new GuiMenuItemCtrl() { Text = "-"; };
+					new GuiMenuItemCtrl() {
+						Text = "Example Menu Item 5";
+						new GuiMenuItemCtrl() {
+							Text = "Example Menu Item 6";
+							Command = "echo(\"Example Menu Item 6!\");";
+						};
+					};
+				};
+			};
+			new GuiMenuItemCtrl() {
+				Text = "Move";
+
+				new GuiMenuItemCtrl() {
+					Text = "Nudge Up";
+					Command = "GuiEditor.moveSelection(0,-1);";
+					Accelerator = "Up";
+				};
+				new GuiMenuItemCtrl() {
+					Text = "Nudge Down";
+					Command = "GuiEditor.moveSelection(0,1);";
+					Accelerator = "Down";
+				};
+				new GuiMenuItemCtrl() {
+					Text = "Nudge Left";
+					Command = "GuiEditor.moveSelection(-1,0);";
+					Accelerator = "Left";
+				};
+				new GuiMenuItemCtrl() {
+					Text = "Nudge Right";
+					Command = "GuiEditor.moveSelection(1,0);";
+					Accelerator = "Right";
+				};
+			};
+		};
 	};
 	};
 };
 };
 //--- OBJECT WRITE END ---
 //--- OBJECT WRITE END ---

+ 0 - 69
toybox/GuiEditorToy/1/main.cs

@@ -36,77 +36,8 @@ function GuiEditorToy::create( %this )
     //SandboxWindow.delete();
     //SandboxWindow.delete();
 	GuiEditor.blankGui = new GuiControl();
 	GuiEditor.blankGui = new GuiControl();
 
 
-	// Init menu
-	GuiEditorToy.initMenus();
-
     // Reset the toy initially.
     // Reset the toy initially.
     GuiEditorToy.reset();
     GuiEditorToy.reset();
-
-}
-
-function GuiEditorToy::initMenus( %this )
-{
-   if( isObject( %this.menuGroup ) )
-      %this.menuGroup.delete();
-
-   %this.menuGroup = new SimGroup();
-
-   //set up %cmdctrl variable so that it matches OS standards
-   %cmdCtrl = $platform $= "macos" ? "Cmd" : "Ctrl";
-
-   %filemenu = new PopupMenu()
-   {
-      superClass = "MenuBuilder";
-      barPosition = 0;
-      barName = "File";
-
-      item[0] = "New Gui..." TAB %cmdCtrl SPC "N" TAB "GuiEditorStartCreate();";
-      item[1] = "Open Gui..." TAB %cmdCtrl SPC "O" TAB "GuiEditorOpenGui();";
-      item[2] = "-";
-      item[3] = "Save Gui..." TAB %cmdCtrl SPC "S" TAB "GuiEditorToy.save();";
-   };
-
-   %layoutmenu = new PopupMenu()
-   {
-      superClass = "MenuBuilder";
-      barPosition = 1;
-      barName = "Layout";
-
-      item[0] = "Align Left" TAB %cmdCtrl SPC "L" TAB "GuiEditor.Justify(0);";
-      item[1] = "Align Right" TAB %cmdCtrl SPC "R" TAB "GuiEditor.Justify(2);";
-      item[2] = "Align Top" TAB %cmdCtrl SPC "T" TAB "GuiEditor.Justify(3);";
-      item[3] = "Align Bottom" TAB %cmdCtrl SPC "B" TAB "GuiEditor.Justify(4);";
-      item[4] = "-";
-      item[5] = "Center Horizontally" TAB "" TAB "GuiEditor.Justify(1);";
-      item[6] = "Space Vertically" TAB "" TAB "GuiEditor.Justify(5);";
-      item[7] = "Space Horizontally" TAB "" TAB "GuiEditor.Justify(6);";
-      item[8] = "-";
-      item[9] = "Bring to Front" TAB "" TAB "GuiEditor.BringToFront();";
-      item[10] = "Send to Back" TAB "" TAB "GuiEditor.PushToBack();";
-      item[11] = "Lock Selection" TAB "" TAB "GuiEditorTreeView.lockSelection(true);";
-      item[12] = "Unlock Selection" TAB "" TAB "GuiEditorTreeView.lockSelection(false);";
-   };
-
-   %movemenu = new PopupMenu()
-   {
-      superClass = "MenuBuilder";
-      barPosition = 2;
-      barName = "Move";
-
-      item[0] = "Nudge Up" TAB "Up" TAB "GuiEditor.moveSelection(0,-1);";
-      item[1] = "Nudge Down" TAB "Down" TAB "GuiEditor.moveSelection(0,1);";
-	  item[2] = "Nudge Right" TAB "Right" TAB "GuiEditor.moveSelection(1,0);";
-	  item[3] = "Nudge Left" TAB "Left" TAB "GuiEditor.moveSelection(-1,0);";
-   };
-
-   // add menus to a group
-   %this.menuGroup.add(%fileMenu);
-   %this.menuGroup.add(%layoutmenu);
-   %this.menuGroup.add(%movemenu);
-
-   for( %i = 0; %i < %this.menuGroup.getCount(); %i++ )
-     %this.menuGroup.getObject( %i ).attachToMenuBar();
-
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------

+ 134 - 0
toybox/Sandbox/1/gui/guiProfiles.cs

@@ -806,3 +806,137 @@ if(!isObject(GuiDropDownProfile)) new GuiControlProfile (GuiDropDownProfile : Gu
 	borderBottom = GuiDropDownDarkBorderProfile;
 	borderBottom = GuiDropDownDarkBorderProfile;
 	category = "dropDown";
 	category = "dropDown";
 };
 };
+
+if (!isObject(GuiMenuBarBorderProfile)) new GuiBorderProfile (GuiMenuBarBorderProfile : GuiDefaultBorderProfile)
+{
+	padding = 2;
+};
+
+if(!isObject(GuiMenuBarProfile)) new GuiControlProfile (GuiMenuBarProfile : GuiDefaultProfile)
+{
+	fillColor = AdjustColorValue($color1, -7);
+	canKeyFocus = true;
+	borderDefault = GuiMenuBarBorderProfile;
+	category = "defaultMenuBar";
+};
+
+if (!isObject(GuiMenuBorderProfile)) new GuiBorderProfile (GuiMenuBorderProfile : GuiDefaultBorderProfile)
+{
+	margin = 2;
+	marginHL = 0;
+	marginSL = 0;
+	marginNA = 2;
+
+	border = 0;
+	borderHL = 2;
+	borderSL = 2;
+	borderNA = 0;
+
+	borderColorHL = "255 255 255 30";
+	borderColorSL = $color4;
+};
+
+if (!isObject(GuiMenuBottomBorderProfile)) new GuiBorderProfile (GuiMenuBottomBorderProfile : GuiMenuBorderProfile)
+{
+	paddingSL = 2;
+	marginSL = 0;
+	borderSL = 0;
+};
+
+if (!isObject(GuiMenuSideBorderProfile)) new GuiBorderProfile (GuiMenuSideBorderProfile : GuiDefaultBorderProfile)
+{
+	border = 0;
+	borderHL = 2;
+	borderSL = 2;
+	borderNA = 0;
+
+	padding = 10;
+	paddingHL = 8;
+	paddingSL = 8;
+	paddingNA = 10;
+
+	borderColorHL = "255 255 255 30";
+	borderColorSL = $color4;
+};
+
+if(!isObject(GuiMenuProfile)) new GuiControlProfile (GuiMenuProfile : GuiDefaultProfile)
+{
+	fillColor = "0 0 0 0";
+	fillColorHL = "255 255 255 10";
+	fillColorSL = AdjustColorValue($color4, -15);
+	fillColorNA = "0 0 0 0";
+
+	borderDefault = GuiMenuBorderProfile;
+	borderLeft = GuiMenuSideBorderProfile;
+	borderRight = GuiMenuSideBorderProfile;
+	borderBottom = GuiMenuBottomBorderProfile;
+	category = "defaultMenuBar";
+
+	fontColor = $color3;
+	fontColorHL = AdjustColorValue($color3, 10);
+	fontColorSL = $color3;
+	fontColorNA = SetColorAlpha($color3, 100);
+};
+
+if (!isObject(GuiMenuContentVertBorderProfile)) new GuiBorderProfile (GuiMenuContentVertBorderProfile : GuiDefaultBorderProfile)
+{
+	border = 2;
+	padding = 4;
+	borderColor = $color4;
+};
+
+if (!isObject(GuiMenuContentSideBorderProfile)) new GuiBorderProfile (GuiMenuContentSideBorderProfile : GuiDefaultBorderProfile)
+{
+	border = 2;
+	padding = 0;
+	borderColor = $color4;
+};
+
+if(!isObject(GuiMenuContentProfile)) new GuiControlProfile (GuiMenuContentProfile : GuiDefaultBorderProfile)
+{
+	fillColor = AdjustColorValue($color1, -5);
+
+	borderDefault = GuiMenuContentSideBorderProfile;
+	borderTop = GuiMenuContentVertBorderProfile;
+	borderBottom = GuiMenuContentVertBorderProfile;
+};
+
+if (!isObject(GuiMenuItemBorderTopProfile)) new GuiBorderProfile (GuiMenuItemBorderTopProfile : GuiDefaultBorderProfile)
+{
+	padding = 6;
+	paddingHL = 6;
+	paddingSL = 0;
+	paddingNA = 6;
+
+	marginSL = 4;
+	borderSL = 1;
+	borderColorSL = "0 0 0 50";
+};
+
+if (!isObject(GuiMenuItemBorderBottomProfile)) new GuiBorderProfile (GuiMenuItemBorderBottomProfile : GuiMenuItemBorderTopProfile)
+{
+	borderColorSL = "255 255 255 50";
+};
+
+if (!isObject(GuiMenuItemBorderSideProfile)) new GuiBorderProfile (GuiMenuItemBorderSideProfile : GuiMenuItemBorderTopProfile)
+{
+	marginSL = 0;
+	borderSL = 0;
+	paddingSL = 6;
+};
+
+if(!isObject(GuiMenuItemProfile)) new GuiControlProfile (GuiMenuItemProfile : GuiDefaultProfile)
+{
+	fillColor = AdjustColorValue($color1, -5);
+	fillColorHL = AdjustColorValue($color4, -15);
+	fillColorNA = $color1;
+	align = left;
+
+	fontColor = $color3;
+	fontColorHL = AdjustColorValue($color3, 10);
+	fontColorNA = SetColorAlpha($color3, 150);
+
+	borderDefault = GuiMenuItemBorderSideProfile;
+	borderTop = GuiMenuItemBorderTopProfile;
+	borderBottom = GuiMenuItemBorderBottomProfile;
+};