diff --git a/src/vgui/ui.qc b/src/vgui/ui.qc index 3d4d7f1a..13a44772 100644 --- a/src/vgui/ui.qc +++ b/src/vgui/ui.qc @@ -53,6 +53,7 @@ Util_MouseAbove(vector vecMousePos, vector vecPos, vector vecSize) return (0); } +.bool isVGUI; /** @brief The base VGUI widget class. Every VGUI widget is based off of this. */ @@ -62,7 +63,7 @@ public: void VGUIWidget(void); /** Adds a widget into this one. */ - nonvirtual void Add(VGUIWidget); + virtual void Add(VGUIWidget); /** Add a flag to the widget. */ nonvirtual void FlagAdd(int); /** Remove a flag from the widget. */ @@ -116,6 +117,9 @@ public: /** Called when the size of the widget has changed in any capacity. */ virtual void SizeChanged(vector, vector); + virtual void NowVisible(void); + virtual void NowHidden(void); + /** Called in order to draw the widget. */ virtual void Draw(void); /** Called whenever the physical properties of the display change. */ @@ -134,6 +138,7 @@ private: vector m_vecMaxSize; VGUIWidget m_next; VGUIWidget m_parent; + VGUIWidget m_children; int m_iFlags; bool m_bVisible; VGUITheme m_theme; @@ -150,6 +155,7 @@ VGUIWidget::VGUIWidget(void) m_parent = __NULL__; m_iFlags = 0i; m_bVisible = true; + isVGUI = true; Spawned(); } @@ -184,12 +190,26 @@ void VGUIWidget::Hide(void) { m_bVisible = false; + NowHidden(); } +void +VGUIWidget::NowHidden(void) +{ +} + + +void +VGUIWidget::NowVisible(void) +{ +} + + void VGUIWidget::Show(void) { m_bVisible = true; + NowVisible(); } void @@ -343,38 +363,51 @@ bool VGUIWidget::Input(float flEVType, float flKey, float flChar, float flDevID) { VGUIWidget wNext = this; + VGUIWidget wLast = __NULL__; + VGUIWidget wLastBefore = __NULL__; - /* this is garbage, but it'll work */ - int c = 0; + /* figure out the last window in the chain... */ do { + wLastBefore = wNext; wNext = wNext.m_next; - c++; + + if (wNext) { + wLast = wNext; + } } while (wNext); - /* we got the count of valid items */ - vgui_input_scene_t *tree = memalloc(sizeof(vgui_input_scene_t) * c); + //print(sprintf("Last widget: %S\n", wLast.classname)); - int i = 0; - wNext = this; - do { - wNext = wNext.m_next; - tree[i].member = wNext; - i++; - } while (wNext); + /* we've found a window, let's test inputs backwards. */ + while (wLast.classname) { + bool test = false; - /* traverse the list in reverse */ - for (int x = c-1; x >= 0; x--) { - wNext = tree[x].member; + if (wLast.Visible()) + test = wLast.Input(flEVType, flKey, flChar, flDevID); - if (wNext && wNext.Visible() && wNext.m_parent.Visible()) - if (wNext.Input(flEVType, flKey, flChar, flDevID) == true) { - memfree(tree); - return (true); + //print(sprintf("Testing input for... widget: %S %d\n", wLast.classname, test)); + + /* input successful */ + if (test == true) { + return true; + } + + /* select the former input */ + for (VGUIWidget a = this; a != __NULL__; a = a.m_next) { + /* we've reached the end, take one from before */ + if (a == wLast) { + wLast = wLastBefore; + break; } + wLastBefore = a; + } + + /* the end of the world. */ + if (wLast == this) + return false; } - memfree(tree); - return (false); + return false; } void diff --git a/src/vgui/ui_window.qc b/src/vgui/ui_window.qc index a2a95717..c9878f60 100644 --- a/src/vgui/ui_window.qc +++ b/src/vgui/ui_window.qc @@ -64,6 +64,9 @@ public: /** Called when the window has been repositioned by the user. */ nonvirtual void CallOnMove(void(void) vFunc); + /** Will focus the window when called. */ + nonvirtual bool Focus(void); + /** Called when the VGUIWindow got moved successfully. */ virtual void WindowDidMove(vector, vector); /** Called when the VGUIWindow got resized successfully. */ @@ -72,10 +75,12 @@ public: virtual void WindowDidClose(void); /* overrides */ + virtual void Add(VGUIWidget); virtual void Draw(void); virtual void SizeChanged(vector, vector); virtual bool Input(float, float, float, float); virtual void Spawned(void); + virtual void NowVisible(); private: vector m_vecColor; @@ -96,6 +101,57 @@ VGUIWindow::VGUIWindow(void) m_styleMask = VGUIWindowStyleDefault; } +void +VGUIWindow::NowVisible(void) +{ + Focus(); +} + +void +VGUIWindow::Add(VGUIWidget wNew) +{ + VGUIWidget wNext = this; + VGUIWidget wParent; + do { + wParent = wNext; + wNext = wNext.m_children; + } while (wNext); + wParent.m_children = wNew; + wNew.m_parent = this; +} + +bool +VGUIWindow::Focus(void) +{ + VGUIWidget wLast = this; + VGUIWidget wEdit = m_parent; /* start at parent */ +// error("Focusing!!!\n"); + + /* iterate through the main windows, we start at the parent of all windows... */ + do { + //print(sprintf("At %S\n", wEdit.classname)); + wLast = wEdit; + wEdit = wEdit.m_next; /* next window of parent */ + + /* skip over ourselves. */ + if (wEdit == this) { + wEdit = this.m_next; + wLast.m_next = this.m_next; + // print("Skipping over ourselves...\n"); + //print(sprintf("At %S\n", wEdit.classname)); + } + + /* if empty... mark ourselves as the last window */ + if (wEdit == __NULL__) { + //print("Last window is us...\n"); + wLast.m_next = this; + this.m_next = __NULL__; + } + } while (wEdit); + + return true; +} + void VGUIWindow::SetStyleMask(vguiWindowStyle_t val) { @@ -247,6 +303,16 @@ void VGUIWindow::Draw(void) } #endif + VGUIWidget wNext = this; + g_vguiWidgetCount = 0; + do { + wNext = wNext.m_children; + if (wNext && wNext.Visible() && wNext.m_parent.Visible()) { + g_vguiWidgetCount++; + wNext.Draw(); + } + } while (wNext); + #ifdef UI_DEVELOPER if (m_iFlags & WINDOW_DRAGGING) { Font_DrawText([8, video_res[1] - 18], sprintf("Window Position: %d, %d\n", m_vecOrigin[0], m_vecOrigin[1]), g_fntDefault); @@ -265,9 +331,11 @@ bool VGUIWindow::Input (float flEVType, float flKey, float flChar, float flDevID if (flKey == K_MOUSE1) { if (m_styleMask & VGUIWindowResizeable && Util_MouseAbove(g_vecMousePos, m_vecOrigin + (m_vecSize - [16,16]), [16,16])) { m_iFlags |= WINDOW_RESIZING; + return Focus(); } else if (m_styleMask & VGUIWindowMovable && Util_MouseAbove(g_vecMousePos, m_vecOrigin, [m_vecSize[0] - 32, 16])) { m_iFlags |= WINDOW_DRAGGING; m_vecDragOffset = m_vecOrigin - g_vecMousePos; + return Focus(); } } } else if (flEVType == IE_KEYUP) { @@ -300,5 +368,19 @@ bool VGUIWindow::Input (float flEVType, float flKey, float flChar, float flDevID } ret = true; } + + if (ret == false) { + VGUIWidget wNext = this; + do { + wNext = wNext.m_children; + if (wNext && wNext.Visible() && wNext.m_parent.Visible()) { + ret = wNext.Input(flEVType, flKey, flChar, flDevID); + } + + if (ret == true) + return true; + } while (wNext); + } + return (ret); }