Browse Source

Merge pull request #319 from chaigler/attach_gui_revamp

AttachGui Revamp
Peter Robinson 9 years ago
parent
commit
72f62cd78e

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

@@ -183,11 +183,6 @@ SceneObject::SceneObject() :
     /// Camera mounting.
     /// Camera mounting.
     mpAttachedCamera(NULL),
     mpAttachedCamera(NULL),
 
 
-    /// GUI attachment.
-    mAttachedGuiSizeControl(false),
-    mpAttachedGui(NULL),
-    mpAttachedGuiSceneWindow(NULL),
-
     /// Safe deletion.
     /// Safe deletion.
     mBeingSafeDeleted(false),
     mBeingSafeDeleted(false),
     mSafeDeleteReady(true),
     mSafeDeleteReady(true),
@@ -206,6 +201,7 @@ SceneObject::SceneObject() :
     VECTOR_SET_ASSOCIATION( mDestroyNotifyList );
     VECTOR_SET_ASSOCIATION( mDestroyNotifyList );
     VECTOR_SET_ASSOCIATION( mCollisionFixtureDefs );
     VECTOR_SET_ASSOCIATION( mCollisionFixtureDefs );
     VECTOR_SET_ASSOCIATION( mCollisionFixtures );
     VECTOR_SET_ASSOCIATION( mCollisionFixtures );
+    VECTOR_SET_ASSOCIATION( mAttachedCtrls );
 
 
     // Assign scene-object index.
     // Assign scene-object index.
     mSerialId = ++sSceneObjectMasterSerialId;
     mSerialId = ++sSceneObjectMasterSerialId;
@@ -368,8 +364,8 @@ bool SceneObject::onAdd()
 
 
 void SceneObject::onRemove()
 void SceneObject::onRemove()
 {
 {
-    // Detach Any GUI Control.
-    detachGui();
+    // Detach all GUI Control.
+    detachAllGuiControls();
 
 
     // Remove from Scene.
     // Remove from Scene.
     if ( getScene() )
     if ( getScene() )
@@ -627,7 +623,7 @@ void SceneObject::integrateObject( const F32 totalTime, const F32 elapsedTime, D
     }
     }
 
 
     // Update Any Attached GUI.
     // Update Any Attached GUI.
-    if ( mpAttachedGui && mpAttachedGuiSceneWindow )
+    if ( mAttachedCtrls.size() )
     {
     {
         updateAttachedGui();
         updateAttachedGui();
     }
     }
@@ -761,7 +757,7 @@ void SceneObject::interpolateObject( const F32 timeDelta )
     }
     }
 
 
     // Update Any Attached GUI.
     // Update Any Attached GUI.
-    if ( mpAttachedGui && mpAttachedGuiSceneWindow )
+    if ( mAttachedCtrls.size() )
     {
     {
         updateAttachedGui();
         updateAttachedGui();
     }
     }
@@ -2776,119 +2772,162 @@ void SceneObject::onInputEvent( StringTableEntry name, const GuiEvent& event, co
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
-void SceneObject::attachGui( GuiControl* pGuiControl, SceneWindow* pSceneWindow, const bool sizeControl )
+void SceneObject::attachGui(GuiControl* pGuiControl, SceneWindow* pSceneWindow, const bool sizeControl, const Vector2 offset)
 {
 {
-    // Attach Gui Control.
-    mpAttachedGui = pGuiControl;
-
-    // Attach SceneWindow.
-    mpAttachedGuiSceneWindow = pSceneWindow;
-
-    // Set Size Gui Flag.
-    mAttachedGuiSizeControl = sizeControl;
+    // Attach GUI control.
+    SceneObjectAttachedGUI attachedGui;
+    attachedGui.mpAttachedCtrl = pGuiControl;
+    attachedGui.mpAttachedSceneWindow = pSceneWindow;
+    attachedGui.mAutoSize = sizeControl;
+    attachedGui.mAttachedOffset = offset;
 
 
-    // Register Gui Control/Window References.
-    mpAttachedGui->registerReference( (SimObject**)&mpAttachedGui );
-    mpAttachedGuiSceneWindow->registerReference( (SimObject**)&mpAttachedGuiSceneWindow );
+    // Register GUI control & window references.
+    attachedGui.mpAttachedCtrl->registerReference((SimObject**)&attachedGui.mpAttachedCtrl);
+    attachedGui.mpAttachedSceneWindow->registerReference((SimObject**)&attachedGui.mpAttachedSceneWindow);
 
 
-    // Check/Adjust Parentage.
-    if ( mpAttachedGui->getParent() != mpAttachedGuiSceneWindow )
+    // Check & adjust GUI parentage.
+    if (attachedGui.mpAttachedCtrl->getParent() != attachedGui.mpAttachedSceneWindow)
     {
     {
-        // Warn.
-        // Remove GuiControl from existing parent (if it has one).
-        if ( mpAttachedGui->getParent() )
+        // Warn user & remove the GuiControl from the existing parent (if it has one).
+        if (attachedGui.mpAttachedCtrl->getParent())
         {
         {
-            mpAttachedGui->getParent()->removeObject( mpAttachedGui );
+            Con::warnf("Warning: SceneObject::attachGui - GuiControl already has a parent GuiWindow!");
+            attachedGui.mpAttachedCtrl->getParent()->removeObject(attachedGui.mpAttachedCtrl);
         }
         }
 
 
-        // Add it to the scene-window.
-        mpAttachedGuiSceneWindow->addObject( mpAttachedGui );
+        // Add the GuiControl to the scene window.
+        attachedGui.mpAttachedSceneWindow->addObject(attachedGui.mpAttachedCtrl);
     }
     }
-    
-}
 
 
+    mAttachedCtrls.push_back(attachedGui);
+}
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
-void SceneObject::detachGui( void )
+void SceneObject::detachGui(void)
 {
 {
-    // Unregister Gui Control Reference.
-    if ( mpAttachedGui )
+    // Remove the last attached GUI.
+    if (mAttachedCtrls.size() > 0)
     {
     {
-       // [neo, 5/7/2007 - #2997]
-       // Changed to UNregisterReference was registerReference which would crash later
-       mpAttachedGui->unregisterReference( (SimObject**)&mpAttachedGui );
-        mpAttachedGui = NULL;
+        mAttachedCtrls.last().mpAttachedCtrl->unregisterReference((SimObject**)&mAttachedCtrls.last().mpAttachedCtrl);
+        mAttachedCtrls.last().mpAttachedSceneWindow->unregisterReference((SimObject**)&mAttachedCtrls.last().mpAttachedSceneWindow);
+
+        mAttachedCtrls.pop_back();
     }
     }
+}
 
 
-    // Unregister Gui Control Reference.
-    if ( mpAttachedGuiSceneWindow )
+void SceneObject::detachGui(GuiControl* pGuiControl)
+{
+    Vector<SceneObjectAttachedGUI>::iterator i;
+    for (i = mAttachedCtrls.begin(); i != mAttachedCtrls.end(); i++)
     {
     {
-        mpAttachedGuiSceneWindow->registerReference( (SimObject**)&mpAttachedGuiSceneWindow );
-        mpAttachedGuiSceneWindow = NULL;
+        if (i->mpAttachedCtrl == pGuiControl)
+        {
+            // Remove the attached GuiControl.
+            i->mpAttachedCtrl->unregisterReference((SimObject**)&i->mpAttachedCtrl);
+            i->mpAttachedSceneWindow->unregisterReference((SimObject**)&i->mpAttachedSceneWindow);
+
+            mAttachedCtrls.pop_back();
+
+            return;
+        }
     }
     }
+
+    // Warn user that no GuiControls were found.
+    Con::warnf("Warning: SceneObject::detachGui() - The GuiControl was not found!");
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
-void SceneObject::updateAttachedGui( void )
+void SceneObject::detachAllGuiControls(void)
+{
+    Vector<SceneObjectAttachedGUI>::iterator i;
+    for (i = mAttachedCtrls.begin(); i != mAttachedCtrls.end(); i++)
+    {
+        // Remove the attached GuiControl.
+        i->mpAttachedCtrl->unregisterReference((SimObject**)&i->mpAttachedCtrl);
+        i->mpAttachedSceneWindow->unregisterReference((SimObject**)&i->mpAttachedSceneWindow);
+    }
+
+    // Clear all references to the attached GuiControls.
+    mAttachedCtrls.clear();
+}
+
+//-----------------------------------------------------------------------------
+void SceneObject::updateAttachedGui(void)
 {
 {
     // Debug Profiling.
     // Debug Profiling.
     PROFILE_SCOPE(SceneObject_updateAttachedGui);
     PROFILE_SCOPE(SceneObject_updateAttachedGui);
 
 
-    // Finish if either Gui Control or Window is invalid.
-    if ( !mpAttachedGui || !mpAttachedGuiSceneWindow )
+    // Early-out if no GUIs are attached.
+    if (mAttachedCtrls.size() == 0)
         return;
         return;
 
 
-    // Ignore if we're not in the scene that the scene-window is attached to.
-    if ( getScene() != mpAttachedGuiSceneWindow->getScene() )
+    Vector<SceneObjectAttachedGUI>::iterator i;
+    for (i = mAttachedCtrls.begin(); i != mAttachedCtrls.end(); i++)
     {
     {
-        // Warn.
-        Con::warnf("SceneObject::updateAttachedGui() - SceneWindow is not attached to my Scene!");
-        // Detach from GUI Control.
-        detachGui();
-        // Finish Here.
-        return;
-    }
+        // Ignore if we're not in the scene that the GUI is attached to.
+        if (getScene() != i->mpAttachedSceneWindow->getScene())
+        {
+            // Warn.
+            Con::warnf("Warning: SceneObject::updateAttachedGui() - SceneWindow is not attached to the Scene!");
 
 
-    // Calculate the GUI Controls' dimensions.
-    Point2I topLeftI, extentI;
+            // Detach the control.
+            detachGui(i->mpAttachedCtrl);
 
 
-    // Size Control?
-    if ( mAttachedGuiSizeControl )
-    {
-        // Yes, so fetch Clip Rectangle; this forms the area we want to fix the Gui-Control to.
-        const RectF objAABB = getAABBRectangle();
-        // Fetch Top-Left.
-        Vector2 upperLeft = Vector2( objAABB.point.x, objAABB.point.y + objAABB.extent.y );
-        Vector2 lowerRight = Vector2( objAABB.point.x + objAABB.extent.x, objAABB.point.y );
+            return;
+        }
 
 
-        // Convert Scene to Window Coordinates.
-        mpAttachedGuiSceneWindow->sceneToWindowPoint( upperLeft, upperLeft );
-        mpAttachedGuiSceneWindow->sceneToWindowPoint( lowerRight, lowerRight );
-        // Convert Control Dimensions.
-        topLeftI.set( S32(upperLeft.x), S32(upperLeft.y) );
-        extentI.set( S32(lowerRight.x-upperLeft.x), S32(lowerRight.y-upperLeft.y) );
-    }
-    else
-    {
-        // No, so center GUI-Control on objects position but don't resize it.
+        // Calculate the GUI Controls' dimensions.
+        Point2I topLeftI, extentI;
 
 
-        // Calculate Position from World Clip.
-        const RectF clipRectangle = getAABBRectangle();
-        // Calculate center position.
-        const Vector2 centerPosition = clipRectangle.point + Vector2(clipRectangle.len_x()*0.5f, clipRectangle.len_y()*0.5f);
+        // Size Control?
+        if (i->mAutoSize)
+        {
+            // Yes, so fetch Clip Rectangle; this forms the area we want to fix the Gui-Control to.
+            const RectF objAABB = getAABBRectangle();
+            // Fetch Top-Left.
+            Vector2 upperLeft = Vector2(objAABB.point.x, objAABB.point.y + objAABB.extent.y);
+            Vector2 lowerRight = Vector2(objAABB.point.x + objAABB.extent.x, objAABB.point.y);
+
+            // Convert Scene to Window Coordinates.
+            i->mpAttachedSceneWindow->sceneToWindowPoint(upperLeft, upperLeft);
+            i->mpAttachedSceneWindow->sceneToWindowPoint(lowerRight, lowerRight);
+
+            // Convert Control Dimensions.
+            topLeftI.set(S32(upperLeft.x), S32(upperLeft.y));
+            extentI.set(S32(lowerRight.x - upperLeft.x), S32(lowerRight.y - upperLeft.y));
+
+            // Add offset
+            topLeftI.x += static_cast<S32>(i->mAttachedOffset.x);
+            topLeftI.y += static_cast<S32>(i->mAttachedOffset.y);
+        }
+        else
+        {
+            // No, so center GUI-Control on objects position but don't resize it.
 
 
-        // Convert Scene to Window Coordinates.
-        Vector2 positionI;
-        mpAttachedGuiSceneWindow->sceneToWindowPoint( centerPosition, positionI );
-        // Fetch Control Extents (which don't change here).
-        extentI = mpAttachedGui->getExtent();
-        // Calculate new top-left.
-        topLeftI.set( S32(positionI.x-extentI.x/2), S32(positionI.y-extentI.y/2) );
-    }
+            // Calculate Position from World Clip.
+            const RectF clipRectangle = getAABBRectangle();
+            // Calculate center position.
+            const Vector2 centerPosition = clipRectangle.point + Vector2(clipRectangle.len_x()*0.5f, clipRectangle.len_y()*0.5f);
+
+            // Convert Scene to Window Coordinates.
+            Vector2 positionI;
+            i->mpAttachedSceneWindow->sceneToWindowPoint(centerPosition, positionI);
 
 
-    // Set Control Dimensions.
-    mpAttachedGui->resize( topLeftI, extentI );
+            // Fetch Control Extents (which don't change here).
+            extentI = i->mpAttachedCtrl->getExtent();
+
+            // Calculate new top-left.
+            topLeftI.set(S32(positionI.x - extentI.x / 2), S32(positionI.y - extentI.y / 2));
+
+            // Add offset
+            topLeftI.x += static_cast<S32>(i->mAttachedOffset.x);
+            topLeftI.y += static_cast<S32>(i->mAttachedOffset.y);
+        }
+
+        // Set Control Dimensions.
+        i->mpAttachedCtrl->resize(topLeftI, extentI);
+    }
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------

+ 14 - 6
engine/source/2d/sceneobject/SceneObject.h

@@ -94,6 +94,14 @@ extern EnumTable dstBlendFactorTable;
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
+struct SceneObjectAttachedGUI
+{
+    bool mAutoSize;
+    GuiControl* mpAttachedCtrl;
+    SceneWindow* mpAttachedSceneWindow;
+    Vector2 mAttachedOffset;
+};
+
 class SceneObject :
 class SceneObject :
     public BehaviorComponent,
     public BehaviorComponent,
     public SceneRenderObject,
     public SceneRenderObject,
@@ -219,9 +227,7 @@ protected:
     SceneWindow*            mpAttachedCamera;
     SceneWindow*            mpAttachedCamera;
 
 
     /// GUI attachment.
     /// GUI attachment.
-    bool                    mAttachedGuiSizeControl;
-    GuiControl*             mpAttachedGui;
-    SceneWindow*            mpAttachedGuiSceneWindow;
+    Vector<SceneObjectAttachedGUI> mAttachedCtrls;
 
 
     /// Safe deletion.
     /// Safe deletion.
     bool                    mBeingSafeDeleted;
     bool                    mBeingSafeDeleted;
@@ -562,9 +568,11 @@ public:
     inline void             dismountCamera( void )                      { if ( mpAttachedCamera ) mpAttachedCamera->dismountMe( this ); }
     inline void             dismountCamera( void )                      { if ( mpAttachedCamera ) mpAttachedCamera->dismountMe( this ); }
 
 
     // GUI attachment.
     // GUI attachment.
-    void                    attachGui( GuiControl* pGuiControl, SceneWindow* pSceneWindow, const bool sizeControl );
-    void                    detachGui( void );
-    inline void             updateAttachedGui( void );
+    void attachGui(GuiControl* pGuiControl, SceneWindow* pSceneWindow, const bool sizeControl, const Vector2 offset);
+    void detachGui(void);
+    void detachGui(GuiControl* pGuiControl);
+    void detachAllGuiControls(void);
+    inline void updateAttachedGui(void);
 
 
     // Picking.
     // Picking.
     inline void             setPickingAllowed( const bool pickingAllowed ) { mPickingAllowed = pickingAllowed; }
     inline void             setPickingAllowed( const bool pickingAllowed ) { mPickingAllowed = pickingAllowed; }

+ 56 - 12
engine/source/2d/sceneobject/SceneObject_ScriptBinding.h

@@ -4315,18 +4315,19 @@ ConsoleMethodWithDocs(SceneObject, setDebugOff, ConsoleVoid, 3, 2 + DEBUG_MODE_C
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
 /*! Attach a GUI Control to the object.
 /*! Attach a GUI Control to the object.
-    @param guiObject The GuiControl to attach.
-    @param window The SceneWindow to bind the GuiControl to.
-    @param sizeControl Whether or not to size the GuiControl to the size of this object.
-    @return No return Value.
+@param guiObject The GuiControl to attach.
+@param window The SceneWindow to bind the GuiControl to.
+@param sizeControl Whether or not to size the GuiControl to the size of this object.
+@param offset The position offset to apply to the GuiControl.
+@return No return Value.
 */
 */
-ConsoleMethodWithDocs(SceneObject, attachGui, ConsoleVoid, 4, 5, (guiControl guiObject, SceneWindow window, [sizeControl? = false]))
+ConsoleMethodWithDocs(SceneObject, attachGui, ConsoleVoid, 4, 7, (guiControl guiObject, SceneWindow window, [sizeControl ? = false], [offset ? = Vector2(0, 0)]))
 {
 {
     // Find GuiControl Object.
     // Find GuiControl Object.
     GuiControl* pGuiControl = dynamic_cast<GuiControl*>(Sim::findObject(argv[2]));
     GuiControl* pGuiControl = dynamic_cast<GuiControl*>(Sim::findObject(argv[2]));
 
 
     // Check for invalid Gui Control.
     // Check for invalid Gui Control.
-    if ( !pGuiControl )
+    if (!pGuiControl)
     {
     {
         Con::warnf("SceneObject::attachGui() - Couldn't find GuiControl %s!", argv[2]);
         Con::warnf("SceneObject::attachGui() - Couldn't find GuiControl %s!", argv[2]);
         return;
         return;
@@ -4336,28 +4337,71 @@ ConsoleMethodWithDocs(SceneObject, attachGui, ConsoleVoid, 4, 5, (guiControl gui
     SceneWindow* pSceneWindow = dynamic_cast<SceneWindow*>(Sim::findObject(argv[3]));
     SceneWindow* pSceneWindow = dynamic_cast<SceneWindow*>(Sim::findObject(argv[3]));
 
 
     // Check for invalid SceneWindow Object.
     // Check for invalid SceneWindow Object.
-    if ( !pSceneWindow )
+    if (!pSceneWindow)
     {
     {
         Con::warnf("SceneObject::attachGui() - Couldn't find SceneWindow %s!", argv[3]);
         Con::warnf("SceneObject::attachGui() - Couldn't find SceneWindow %s!", argv[3]);
         return;
         return;
     }
     }
 
 
-    // Calculate Send to Mount.
+    // Auto-size control?.
     const bool sizeControl = argc >= 5 ? dAtob(argv[4]) : false;
     const bool sizeControl = argc >= 5 ? dAtob(argv[4]) : false;
 
 
+    // GuiControl position offset.
+    Vector2 offset(0, 0);
+
+    // Elements in the first argument.
+    U32 elementCount = Utility::mGetStringElementCount(argv[5]);
+
+    // ("x y")
+    if ((elementCount == 2) && (argc == 6))
+        offset = Utility::mGetStringElementVector(argv[5]);
+
+    // (x, y)
+    else if ((elementCount == 1) && (argc == 7))
+        offset = Vector2(dAtof(argv[5]), dAtof(argv[6]));
+
     // Attach GUI Control.
     // Attach GUI Control.
-    object->attachGui( pGuiControl, pSceneWindow, sizeControl );
+    object->attachGui(pGuiControl, pSceneWindow, sizeControl, offset);
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
 /*! Detach any GUI Control.
 /*! Detach any GUI Control.
+@param ctrl The SimObjectId of the GuiControl to detach.
     @return No return Value.
     @return No return Value.
 */
 */
-ConsoleMethodWithDocs(SceneObject, detachGui, ConsoleVoid, 2, 2, ())
+ConsoleMethodWithDocs(SceneObject, detachGui, ConsoleVoid, 2, 3, ())
+{
+    if (argc >= 3)
+    {
+        GuiControl* pGuiControl = dynamic_cast<GuiControl*>(Sim::findObject(argv[3]));
+
+        if (!pGuiControl)
+        {
+            // Detach the last attached control.
+            object->detachGui();
+        }
+        else
+        {
+            // Detach the attached control.
+            object->detachGui(pGuiControl);
+        }
+    }
+    else
+    {
+        // Detach the last attached control.
+        object->detachGui();
+    }
+}
+
+//-----------------------------------------------------------------------------
+
+/*! Detach all GUI Controls.
+    @return No return value.
+*/
+ConsoleMethodWithDocs(SceneObject, detachAllGuiControls, ConsoleVoid, 2, 2, ())
 {
 {
-    // Detach GUI Control.
-    object->detachGui();
+    object->detachAllGuiControls();
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------