Browse Source

SceneWindow Event Pass Through

This code allows sceneWindows to optionally let events that they don't consume pass through them to controls behind them. Like all events, sceneWindow events like onTouchDown can return true if they have consumed the event. Previously returning false would allow the parent of the sceneWindow to also respond to the event as it bubbles up the chain to the canvas. This bubbling will still happen, but afterwards the event, if still unconsumed, is passed to controls behind the sceneWindow. Practically, this allows two scene windows to be stacked so that the top window can be used for UI elements made from sprites and the bottom window can consist of a game world.
Peter Robinson 1 year ago
parent
commit
e329e35773

+ 34 - 23
engine/source/2d/gui/SceneWindow.cc

@@ -1163,27 +1163,32 @@ void SceneWindow::sceneToWindowPoint( const Vector2& srcPoint, Vector2& dstPoint
 
 //-----------------------------------------------------------------------------
 
-void SceneWindow::dispatchInputEvent( StringTableEntry name, const GuiEvent& event )
+bool SceneWindow::dispatchInputEvent( StringTableEntry name, const GuiEvent& event )
 {
     // Debug Profiling.
     PROFILE_SCOPE(SceneWindow_DispatchInputEvent);
 
     // Dispatch input event to window if appropriate.
+	bool windowConsumedEvent = false;
     if ( getUseWindowInputEvents() )
-        sendWindowInputEvent( name, event );
+		windowConsumedEvent = sendWindowInputEvent( name, event );
 
     // Dispatch input event to scene objects if appropriate.
+	bool objectConsumedEvent = false;
     if ( getUseObjectInputEvents() )
-        sendObjectInputEvent( name, event );
+		objectConsumedEvent = sendObjectInputEvent( name, event );
+
+	return !(windowConsumedEvent || objectConsumedEvent);
 }
 
 //-----------------------------------------------------------------------------
 
-void SceneWindow::sendWindowInputEvent( StringTableEntry name, const GuiEvent& event )
+bool SceneWindow::sendWindowInputEvent( StringTableEntry name, const GuiEvent& event )
 {       
     // Debug Profiling.
     PROFILE_SCOPE(SceneWindow_SendWindowInputEvent);
 
+	bool consumed = false;
     Vector2   worldMousePoint;
 
     // Calculate Current Camera View.
@@ -1218,7 +1223,7 @@ void SceneWindow::sendWindowInputEvent( StringTableEntry name, const GuiEvent& e
     dSprintf(argBuffer[2], 64, "%d", event.mouseClickCount);
 
     // Call Scripts.
-    Con::executef(this, 4, name, argBuffer[0], argBuffer[1], argBuffer[2]);
+    consumed = Con::executef(this, 4, name, argBuffer[0], argBuffer[1], argBuffer[2]);
 
     // Iterate listeners.
     for( SimSet::iterator listenerItr = mInputListeners.begin(); listenerItr != mInputListeners.end(); ++listenerItr )
@@ -1226,24 +1231,28 @@ void SceneWindow::sendWindowInputEvent( StringTableEntry name, const GuiEvent& e
         // Call scripts on listener.
         Con::executef( *listenerItr, 4, name, argBuffer[0], argBuffer[1], argBuffer[2] );
     }
+
+	return consumed;
 }
 
 //-----------------------------------------------------------------------------
 
-void SceneWindow::sendObjectInputEvent( StringTableEntry name, const GuiEvent& event )
+bool SceneWindow::sendObjectInputEvent( StringTableEntry name, const GuiEvent& event )
 {
     // Debug Profiling.
     PROFILE_SCOPE(SceneWindow_SendObjectInputEvent);
 
+	bool consumed = false;
+
     // Finish if we're not bound to a scene?
-    if ( !getScene() ) return;
+    if ( !getScene() ) return consumed;
 
     // Only process appropriate input events.
     if ( !( name == inputEventDownName ||
             name == inputEventUpName ||
             name == inputEventMovedName ||
             name == inputEventDraggedName ) )
-        return;
+        return consumed;
 
     // Convert Event-Position into scene coordinates.
     Vector2 worldMousePoint;
@@ -1264,7 +1273,7 @@ void SceneWindow::sendObjectInputEvent( StringTableEntry name, const GuiEvent& e
 
     // Early-out if nothing to do.
     if ( newPickCount == 0 && oldPickCount == 0 )
-        return;
+        return consumed;
 
     // Fetch results.
     mInputEventQuery = pWorldQuery->getQueryResults();
@@ -1338,7 +1347,7 @@ void SceneWindow::sendObjectInputEvent( StringTableEntry name, const GuiEvent& e
             continue;
 
         // Emit event.
-        pSceneObject->onInputEvent( name, event, worldMousePoint );
+		consumed = pSceneObject->onInputEvent( name, event, worldMousePoint );
     }
 
     // Process "leave" events.
@@ -1365,7 +1374,7 @@ void SceneWindow::sendObjectInputEvent( StringTableEntry name, const GuiEvent& e
 
         // Process "moved" or "dragged" events.
         if ( name == inputEventMovedName || name == inputEventDraggedName )
-            pSceneObject->onInputEvent( name, event, worldMousePoint );
+			consumed = pSceneObject->onInputEvent( name, event, worldMousePoint );
 
         // Add scene object.
         mInputEventWatching.addObject( pSceneObject );
@@ -1375,6 +1384,8 @@ void SceneWindow::sendObjectInputEvent( StringTableEntry name, const GuiEvent& e
     mInputEventQuery.clear();
     mInputEventEntering.clear();
     mInputEventLeaving.clear();
+
+	return consumed;
 }
 
 //-----------------------------------------------------------------------------
@@ -1418,7 +1429,7 @@ void SceneWindow::onTouchDown( const GuiEvent& event )
         mouseLock();
 
     // Dispatch input event.
-    dispatchInputEvent( inputEventDownName, event);
+    mPassEventThru = dispatchInputEvent( inputEventDownName, event);
 }
 
 //-----------------------------------------------------------------------------
@@ -1430,7 +1441,7 @@ void SceneWindow::onTouchUp( const GuiEvent& event )
         mouseUnlock();
 
     // Dispatch input event.
-    dispatchInputEvent(inputEventUpName, event);
+	mPassEventThru = dispatchInputEvent(inputEventUpName, event);
 }
 
 //-----------------------------------------------------------------------------
@@ -1443,7 +1454,7 @@ void SceneWindow::onTouchMove( const GuiEvent& event )
 	}
 
     // Dispatch input event.
-    dispatchInputEvent(inputEventMovedName, event);
+	mPassEventThru = dispatchInputEvent(inputEventMovedName, event);
 }
 
 //-----------------------------------------------------------------------------
@@ -1451,7 +1462,7 @@ void SceneWindow::onTouchMove( const GuiEvent& event )
 void SceneWindow::onTouchDragged( const GuiEvent& event )
 {
     // Dispatch input event.
-    dispatchInputEvent(inputEventDraggedName, event);
+	mPassEventThru = dispatchInputEvent(inputEventDraggedName, event);
 }
 
 //-----------------------------------------------------------------------------
@@ -1463,7 +1474,7 @@ void SceneWindow::onMiddleMouseDown( const GuiEvent& event )
         mouseLock();
 
     // Dispatch input event.
-    dispatchInputEvent(mouseEventMiddleMouseDownName, event);
+	mPassEventThru = dispatchInputEvent(mouseEventMiddleMouseDownName, event);
 }
 
 //-----------------------------------------------------------------------------
@@ -1475,7 +1486,7 @@ void SceneWindow::onMiddleMouseUp( const GuiEvent& event )
         mouseUnlock();
 
     // Dispatch input event.
-    dispatchInputEvent(mouseEventMiddleMouseUpName, event);
+	mPassEventThru = dispatchInputEvent(mouseEventMiddleMouseUpName, event);
 }
 
 //-----------------------------------------------------------------------------
@@ -1483,7 +1494,7 @@ void SceneWindow::onMiddleMouseUp( const GuiEvent& event )
 void SceneWindow::onMiddleMouseDragged( const GuiEvent& event )
 {
     // Dispatch input event.
-    dispatchInputEvent(mouseEventMiddleMouseDraggedName, event);
+	mPassEventThru = dispatchInputEvent(mouseEventMiddleMouseDraggedName, event);
 }
 
 //-----------------------------------------------------------------------------
@@ -1495,7 +1506,7 @@ void SceneWindow::onRightMouseDown( const GuiEvent& event )
         mouseLock();
 
     // Dispatch input event.
-    dispatchInputEvent(mouseEventRightMouseDownName, event);
+	mPassEventThru = dispatchInputEvent(mouseEventRightMouseDownName, event);
 }
 
 //-----------------------------------------------------------------------------
@@ -1507,7 +1518,7 @@ void SceneWindow::onRightMouseUp( const GuiEvent& event )
         mouseUnlock();
 
     // Dispatch input event.
-    dispatchInputEvent(mouseEventRightMouseUpName, event);
+	mPassEventThru = dispatchInputEvent(mouseEventRightMouseUpName, event);
 }
 
 //-----------------------------------------------------------------------------
@@ -1515,7 +1526,7 @@ void SceneWindow::onRightMouseUp( const GuiEvent& event )
 void SceneWindow::onRightMouseDragged( const GuiEvent& event )
 {
     // Dispatch input event.
-    dispatchInputEvent(mouseEventRightMouseDraggedName, event);
+	mPassEventThru = dispatchInputEvent(mouseEventRightMouseDraggedName, event);
 }
 
 //-----------------------------------------------------------------------------
@@ -1532,7 +1543,7 @@ void SceneWindow::onMouseWheelUp( const GuiEvent& event )
    Parent::onMouseWheelUp( event );
 
    // Dispatch input event.
-   dispatchInputEvent(mouseEventWheelUpName, event);
+   mPassEventThru = dispatchInputEvent(mouseEventWheelUpName, event);
 }
 
 //-----------------------------------------------------------------------------
@@ -1549,7 +1560,7 @@ void SceneWindow::onMouseWheelDown( const GuiEvent& event )
    Parent::onMouseWheelDown( event );
 
    // Dispatch input event.
-   dispatchInputEvent(mouseEventWheelDownName, event);
+   mPassEventThru = dispatchInputEvent(mouseEventWheelDownName, event);
 }
 
 //-----------------------------------------------------------------------------

+ 3 - 3
engine/source/2d/gui/SceneWindow.h

@@ -158,9 +158,9 @@ private:
     char                mDebugText[256];
 
     /// Handling Input Events.
-    void dispatchInputEvent( StringTableEntry name, const GuiEvent& event );
-    void sendWindowInputEvent( StringTableEntry name, const GuiEvent& event );
-    void sendObjectInputEvent( StringTableEntry, const GuiEvent& event );
+    bool dispatchInputEvent( StringTableEntry name, const GuiEvent& event );
+    bool sendWindowInputEvent( StringTableEntry name, const GuiEvent& event );
+    bool sendObjectInputEvent( StringTableEntry, const GuiEvent& event );
 
     void calculateCameraView( CameraView* pCameraView );
 

+ 9 - 0
engine/source/2d/gui/SceneWindow_ScriptBinding.h

@@ -1602,4 +1602,13 @@ ConsoleMethodWithDocs(SceneWindow, setArrowProfile, ConsoleVoid, 3, 3, (GuiContr
 		object->setControlArrowProfile(profile);
 }
 
+/*! Sets if events (touch down, up and move) should be allowed to pass through the control. When true, event callbacks will return true if they consume an event and false if they don't. Unconsumed events will be passed to controls behind the scene window.
+	@param isPassThru True to allow touch down, up and move to pass through the scene window when they are not consumed.
+	@return No return value
+*/
+ConsoleMethodWithDocs(GuiControl, setAllowEventPassThru, ConsoleVoid, 3, 3, (isPassThru))
+{
+	object->mAllowEventPassThru = (dAtob(argv[2]));
+}
+
 ConsoleMethodGroupEndWithDocs(SceneWindow)

+ 2 - 2
engine/source/2d/sceneobject/SceneObject.cc

@@ -2793,7 +2793,7 @@ void SceneObject::resetBlendOptions( void )
 
 //---------------------------------------------------------------------------------------------
 
-void SceneObject::onInputEvent( StringTableEntry name, const GuiEvent& event, const Vector2& worldMousePosition )
+bool SceneObject::onInputEvent( StringTableEntry name, const GuiEvent& event, const Vector2& worldMousePosition )
 {
     // Debug Profiling.
     PROFILE_SCOPE(SceneObject_OnInputEvent);
@@ -2811,7 +2811,7 @@ void SceneObject::onInputEvent( StringTableEntry name, const GuiEvent& event, co
     dSprintf(argBuffer[2], 32, "%d", event.mouseClickCount);
 
     // Call Scripts.
-    Con::executef(this, 4, name, argBuffer[0], argBuffer[1], argBuffer[2]);
+    return dAtob(Con::executef(this, 4, name, argBuffer[0], argBuffer[1], argBuffer[2]));
 }
 
 //-----------------------------------------------------------------------------

+ 1 - 1
engine/source/2d/sceneobject/SceneObject.h

@@ -550,7 +550,7 @@ public:
     /// Input events.
     inline void             setUseInputEvents( bool mouseStatus )       { mUseInputEvents = mouseStatus; }
     inline bool             getUseInputEvents( void ) const             { return mUseInputEvents; }
-    virtual void            onInputEvent( StringTableEntry name, const GuiEvent& event, const Vector2& worldMousePoint );
+    virtual bool            onInputEvent( StringTableEntry name, const GuiEvent& event, const Vector2& worldMousePoint );
 
     // Script callbacks.
     inline void             setUpdateCallback( bool status )            { mUpdateCallback = status; }

+ 0 - 10
engine/source/console/metaScripting_ScriptBinding.cc

@@ -433,16 +433,6 @@ ConsoleFunctionWithDocs(exec, ConsoleBool, 2, 4, ( fileName, [nocalls]?, [journa
          rScr->getFileTimes(NULL, &scrModifyTime);
    }
 
-   // Let's do a sanity check to complain about DSOs in the future.
-   //
-   // MM:	This doesn't seem to be working correctly for now so let's just not issue
-   //		the warning until someone knows how to resolve it.
-   //
-   //if(compiled && rCom && rScr && Platform::compareFileTimes(comModifyTime, scrModifyTime) < 0)
-   //{
-   //Con::warnf("exec: Warning! Found a DSO from the future! (%s)", nameBuffer);
-   //}
-
     // If we had a DSO, let's check to see if we should be reading from it.
     if((compiled && rCom) && (!rScr || Platform::compareFileTimes(comModifyTime, scrModifyTime) >= 0))
     {

+ 38 - 53
engine/source/gui/guiCanvas.cc

@@ -618,26 +618,7 @@ void GuiCanvas::rootMouseDown(const GuiEvent &event)
    //else pass it to whoever is underneath the cursor
    else
    {
-      iterator i;
-      i = end();
-      while (i != begin())
-      {
-         i--;
-         GuiControl *ctrl = static_cast<GuiControl *>(*i);
-         if (ctrl->mUseInput)
-         {
-             GuiControl* controlHit = ctrl->findHitControl(event.mousePoint);
-
-             //Regardless of what the control does, it has the user's focus.
-             controlHit->onFocus(false);
-
-             if (controlHit->mUseInput)
-             {
-                 controlHit->onTouchDown(event);
-                 break;
-             }
-         }
-      }
+      handleTouchDown(event, event.mousePoint);
    }
    if (bool(mMouseControl))
       mMouseControlClicked = true;
@@ -715,33 +696,37 @@ void GuiCanvas::rootScreenTouchDown(const GuiEvent &event)
     mPrevMouseTime = Platform::getVirtualMilliseconds();  
     mMouseButtonDown = true;  
   
-        iterator i;  
-        i = end();  
-        while (i != begin())  
-        {  
-            i--;  
-            GuiControl *ctrl = static_cast<GuiControl *>(*i);  
-            if (ctrl->mUseInput)
+    iterator i;  
+    i = end();  
+    while (i != begin())  
+    {  
+        i--;  
+        GuiControl *ctrl = static_cast<GuiControl *>(*i);  
+        if (ctrl->mUseInput)
+        {
+            GuiControl* controlHit = ctrl->findHitControl(event.mousePoint);
+
+            //If the control we hit is not the same one that is locked,  
+            // then unlock the existing control.  
+            if (bool(mMouseCapturedControl) && mMouseCapturedControl->isMouseLocked() && mMouseCapturedControl != controlHit)
             {
-                GuiControl* controlHit = ctrl->findHitControl(event.mousePoint);
-
-                //If the control we hit is not the same one that is locked,  
-                // then unlock the existing control.  
-                if (bool(mMouseCapturedControl) && mMouseCapturedControl->isMouseLocked() && mMouseCapturedControl != controlHit)
-                {
-                    mMouseCapturedControl->onTouchLeave(event);
-                }
-
-                //Regardless of what the control does, it has the user's focus.
-                controlHit->onFocus(false);
-
-                if (controlHit->mUseInput)
-                {
-                    controlHit->onTouchDown(event);
-                    break;
-                }
+                mMouseCapturedControl->onTouchLeave(event);
             }
-        }  
+
+            //Regardless of what the control does, it has the user's focus.
+            controlHit->onFocus(false);
+
+            if (controlHit->mUseInput)
+            {
+				controlHit->mPassEventThru = false;//If true after the call then pass the event to the next control below it.
+				controlHit->onTouchDown(event);
+				if (!controlHit->mPassEventThru)
+				{
+					break;
+				}
+            }
+        }
+    }
       
     if (bool(mMouseControl))  
         mMouseControlClicked = true;  
@@ -764,8 +749,12 @@ void GuiCanvas::rootScreenTouchUp(const GuiEvent &event)
 
             if (controlHit->mActive && controlHit->mUseInput)
             {
-                controlHit->onTouchUp(event);
-                break;
+				controlHit->mPassEventThru = false;//If true after the call then pass the event to the next control below it.
+				controlHit->onTouchUp(event);
+				if (!controlHit->mPassEventThru)
+				{
+					break;
+				}
             }
         }
     }
@@ -807,9 +796,7 @@ void GuiCanvas::rootMouseUp(const GuiEvent &event)
       mMouseCapturedControl->onTouchUp(event);
    else
    {
-      findMouseControl(event);
-      if(bool(mMouseControl))
-         mMouseControl->onTouchUp(event);
+      handleTouchUp(event, event.mousePoint);
    }
 }
 
@@ -863,9 +850,7 @@ void GuiCanvas::rootMouseMove(const GuiEvent &event)
    }
    else
    {
-      findMouseControl(event);
-      if(bool(mMouseControl))
-         mMouseControl->onTouchMove(event);
+	   handleTouchMove(event, event.mousePoint);
    }
 }
 

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

@@ -123,6 +123,7 @@ GuiControl::GuiControl()
    mTipHoverTime        = 1000;
    mTooltipWidth		= 250;
    mIsContainer         = true;
+   mAllowEventPassThru  = false;
    mTextWrap			= false;
    mTextExtend          = false;
    mUseInput            = true;
@@ -1451,7 +1452,101 @@ GuiControl* GuiControl::findHitControl(const Point2I &pt, S32 initialLayer, cons
    return this;
 }
 
-// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- //
+bool GuiControl::handleTouchDown(const GuiEvent& event, const Point2I& pt, S32 initialLayer)
+{
+	bool keepGoing = true;
+	iterator i = end(); // find in z order (last to first)
+	while (i != begin())
+	{
+		i--;
+		GuiControl* ctrl = static_cast<GuiControl*>(*i);
+		if (initialLayer >= 0 && ctrl->mLayer > initialLayer)
+		{
+			continue;
+		}
+		else if (ctrl->pointInControl(pt - ctrl->mRenderInsetLT) && ctrl->mVisible && ctrl->mUseInput)
+		{
+			Point2I ptemp = pt - (ctrl->mBounds.point + ctrl->mRenderInsetLT);
+			keepGoing = ctrl->handleTouchDown(event, ptemp) && ctrl->mAllowEventPassThru;
+		}
+
+		if (!keepGoing)
+		{
+			break;
+		}
+	}
+	if (keepGoing)
+	{
+		mPassEventThru = false;
+		onTouchDown(event);
+		keepGoing = mPassEventThru;
+	}
+	return keepGoing;
+}
+
+bool GuiControl::handleTouchUp(const GuiEvent& event, const Point2I& pt, S32 initialLayer)
+{
+	bool keepGoing = true;
+	iterator i = end(); // find in z order (last to first)
+	while (i != begin())
+	{
+		i--;
+		GuiControl* ctrl = static_cast<GuiControl*>(*i);
+		if (initialLayer >= 0 && ctrl->mLayer > initialLayer)
+		{
+			continue;
+		}
+		else if (ctrl->pointInControl(pt - ctrl->mRenderInsetLT) && ctrl->mVisible && ctrl->mUseInput)
+		{
+			Point2I ptemp = pt - (ctrl->mBounds.point + ctrl->mRenderInsetLT);
+			keepGoing = ctrl->handleTouchUp(event, ptemp) && ctrl->mAllowEventPassThru;
+		}
+
+		if (!keepGoing)
+		{
+			break;
+		}
+	}
+	if (keepGoing)
+	{
+		mPassEventThru = false;
+		onTouchUp(event);
+		keepGoing = mPassEventThru;
+	}
+	return keepGoing;
+}
+
+bool GuiControl::handleTouchMove(const GuiEvent& event, const Point2I& pt, S32 initialLayer)
+{
+	bool keepGoing = true;
+	iterator i = end(); // find in z order (last to first)
+	while (i != begin())
+	{
+		i--;
+		GuiControl* ctrl = static_cast<GuiControl*>(*i);
+		if (initialLayer >= 0 && ctrl->mLayer > initialLayer)
+		{
+			continue;
+		}
+		else if (ctrl->pointInControl(pt - ctrl->mRenderInsetLT) && ctrl->mVisible && ctrl->mUseInput)
+		{
+			Point2I ptemp = pt - (ctrl->mBounds.point + ctrl->mRenderInsetLT);
+			keepGoing = ctrl->handleTouchMove(event, ptemp) && ctrl->mAllowEventPassThru;
+		}
+
+		if (!keepGoing)
+		{
+			break;
+		}
+	}
+	if (keepGoing)
+	{
+		mPassEventThru = false;
+		onTouchMove(event);
+		keepGoing = mPassEventThru;
+	}
+	return keepGoing;
+}
 
 bool GuiControl::isMouseLocked()
 {

+ 7 - 0
engine/source/gui/guiControl.h

@@ -194,6 +194,8 @@ public:
 		tRotateRight
 	};
 
+	bool mPassEventThru = false;
+
 protected:
     /// @name Control State
     /// @{
@@ -577,6 +579,11 @@ public:
     virtual bool isMouseLocked();
     /// @}
 
+	bool mAllowEventPassThru;
+	bool handleTouchDown(const GuiEvent& event, const Point2I& pt, S32 initialLayer = -1);
+	bool handleTouchUp(const GuiEvent& event, const Point2I& pt, S32 initialLayer = -1);
+	bool handleTouchMove(const GuiEvent& event, const Point2I& pt, S32 initialLayer = -1);
+
     //Sends a script event with modifier and mouse position if the script method exists. Returns true if the event is consumed.
     bool sendScriptMouseEvent(const char* name, const GuiEvent& event);
     bool sendScriptKeyEvent(const char* name, const InputEvent& event);

+ 60 - 0
space/BlankGame/gui/passthrutest.gui.taml

@@ -0,0 +1,60 @@
+<GuiControl
+    canSaveDynamicFields="false"
+    isContainer="true"
+    Profile="GuiWindowProfile"
+    HorizSizing="fill"
+    VertSizing="fill"
+    Position="0 0"
+    Extent="1227 943"
+    canSave="true"
+    Visible="true"
+    useInput="true"
+    Active="false"
+    tooltipWidth="250"
+    hovertime="1000"
+    fontSizeAdjust="1"
+    overrideFontColor="false"
+    fontColor="Black">
+    <SceneWindow
+        Name="GameWindow"
+        canSaveDynamicFields="false"
+        isContainer="true"
+        Profile="GuiDefaultProfile"
+        HorizSizing="fill"
+        VertSizing="fill"
+        Position="0 0"
+        Extent="1227 943"
+        canSave="true"
+        Visible="true"
+        useInput="true"
+        Active="false"
+        tooltipWidth="250"
+        hovertime="1000"
+        fontSizeAdjust="1"
+        overrideFontColor="false"
+        fontColor="Black"
+        lockMouse="false"
+        UseWindowInputEvents="true"
+        UseObjectInputEvents="true" />
+    <SceneWindow
+        Name="StatusWindow"
+        canSaveDynamicFields="false"
+        isContainer="true"
+        Profile="GuiDefaultProfile"
+        HorizSizing="fill"
+        VertSizing="fill"
+        Position="0 0"
+        Extent="1227 943"
+        canSave="true"
+        Visible="true"
+        useInput="true"
+        Active="false"
+        tooltipWidth="250"
+        hovertime="1000"
+        fontSizeAdjust="1"
+        overrideFontColor="false"
+        fontColor="Black"
+        lockMouse="false"
+        UseWindowInputEvents="true"
+        UseObjectInputEvents="false" />
+</GuiControl>