VGUI: Redo the way input is handled, address focus changes between Windows etc.

This commit is contained in:
Marco Cawthorne 2023-10-01 01:13:26 -07:00
parent 5c5eedb665
commit c1d6324153
Signed by: eukara
GPG key ID: CE2032F0A2882A22
2 changed files with 137 additions and 22 deletions

View file

@ -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

View file

@ -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);
}