481 lines
10 KiB
Plaintext
481 lines
10 KiB
Plaintext
/*
|
|
* Copyright (c) 2016-2022 Vera Visions LLC.
|
|
*
|
|
* Permission to use, copy, modify, and distribute this software for any
|
|
* purpose with or without fee is hereby granted, provided that the above
|
|
* copyright notice and this permission notice appear in all copies.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
|
|
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
|
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
*/
|
|
|
|
/* compatibility wrappers */
|
|
#define CUI3DView VGUI3DView
|
|
#define CUIButton VGUIButton
|
|
#define CUICheckbox VGUICheckbox
|
|
#define CUILabel VGUILabel
|
|
#define CUIList VGUIList
|
|
#define CUIListBox VGUIListBox
|
|
#define CUIMenuButton VGUIMenuButton
|
|
#define CUIPic VGUIPic
|
|
#define CUIRadio VGUIRadio
|
|
#define CUIScrollbar VGUIScrollbar
|
|
#define CUISlider VGUISlider
|
|
#define CUITabView VGUITabView
|
|
#define CUITextBox VGUITextBox
|
|
#define CUIWidget VGUIWidget
|
|
#define CUIWindow VGUIWindow
|
|
|
|
font_s g_fntDefault;
|
|
var int g_vguiWidgetCount;
|
|
|
|
/** Return whether a VGUI panel is active on the 2D overlay level. */
|
|
bool
|
|
VGUI_Active(void)
|
|
{
|
|
return (g_vguiWidgetCount > 0i) ? (true) : (false);
|
|
}
|
|
|
|
/** Returns whether our mouse cursor is in a specific region of the screen. */
|
|
bool
|
|
Util_MouseAbove(vector vecMousePos, vector vecPos, vector vecSize)
|
|
{
|
|
if (vecMousePos[0] >= vecPos[0] && vecMousePos[0] <= vecPos[0] + vecSize[0]) {
|
|
if (vecMousePos[1] >= vecPos[1] && vecMousePos[1] <= vecPos[1] + vecSize[1]) {
|
|
return (true);
|
|
}
|
|
}
|
|
return (false);
|
|
}
|
|
|
|
.bool isVGUI;
|
|
/** @brief The base VGUI widget class.
|
|
|
|
Every VGUI widget is based off of this. */
|
|
class VGUIWidget
|
|
{
|
|
public:
|
|
void VGUIWidget(void);
|
|
|
|
/** Adds a widget into this one. */
|
|
virtual void Add(VGUIWidget);
|
|
/** Add a flag to the widget. */
|
|
nonvirtual void FlagAdd(int);
|
|
/** Remove a flag from the widget. */
|
|
nonvirtual void FlagRemove(int);
|
|
/** Check if the VGUIWidget has a flag attached. */
|
|
nonvirtual bool HasFlag(int);
|
|
|
|
/** Set the position within its context. */
|
|
nonvirtual void SetPos(vector);
|
|
/** Return the position of the widget within its context. */
|
|
nonvirtual vector GetPos(void);
|
|
/** Returns the X coordinate of the widget position within its context. */
|
|
nonvirtual int GetPosWidth(void);
|
|
/** Returns the Y coordinate of the widget position within its context. */
|
|
nonvirtual int GetPosHeight(void);
|
|
|
|
/** Set the size of the widget to a new one. */
|
|
nonvirtual void SetSize(vector);
|
|
/** Returns the size of the widget, in pixels. */
|
|
nonvirtual vector GetSize(void);
|
|
|
|
/** Returns the width of the widget, in pixels. */
|
|
nonvirtual int GetSizeWidth(void);
|
|
/** Returns the height of the widget, in pixels. */
|
|
nonvirtual int GetSizeHeight(void);
|
|
|
|
/** Sets the minimum size of the widget. */
|
|
nonvirtual void SetMinSize(vector);
|
|
/** Returns the minimum size of the widget. */
|
|
nonvirtual vector GetMinSize(void);
|
|
|
|
/** Sets the maximum size of the widget. */
|
|
nonvirtual void SetMaxSize(vector);
|
|
/** Returns the maximum size of the widget. */
|
|
nonvirtual vector GetMaxSize(void);
|
|
|
|
/** Returns true/false depending on if the widget is visible. */
|
|
nonvirtual bool Visible(void);
|
|
/** Show the widget. */
|
|
nonvirtual void Show(void);
|
|
/** Hide the widget. */
|
|
nonvirtual void Hide(void);
|
|
|
|
/** Sets the VGUITheme to use on this widget (and any children it may have) */
|
|
nonvirtual void SetTheme(VGUITheme);
|
|
/** Returns the VGUI that will be used on this widget. */
|
|
nonvirtual VGUITheme GetTheme(void);
|
|
|
|
/** Called when the position of the widget was changed in any capacity. */
|
|
virtual void PositionChanged(vector, vector);
|
|
/** 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. */
|
|
virtual void Reposition(void);
|
|
/** Called whenever an input event gets directed to the widget. */
|
|
virtual bool Input(float, float, float, float);
|
|
/** Called when the widget has fully initialized.
|
|
When you override this, you may call `super::Spawned();` to ensure
|
|
the parent classes get to finish initializing also. */
|
|
virtual void Spawned(void);
|
|
|
|
private:
|
|
vector m_vecOrigin;
|
|
vector m_vecSize;
|
|
vector m_vecMinSize;
|
|
vector m_vecMaxSize;
|
|
VGUIWidget m_next;
|
|
VGUIWidget m_parent;
|
|
VGUIWidget m_children;
|
|
int m_iFlags;
|
|
bool m_bVisible;
|
|
VGUITheme m_theme;
|
|
};
|
|
|
|
void
|
|
VGUIWidget::VGUIWidget(void)
|
|
{
|
|
m_vecOrigin = [0.0f, 0.0f];
|
|
m_vecSize = [0.0f, 0.0f];
|
|
m_vecMinSize = [0.0f, 0.0f];
|
|
m_vecMaxSize = [9999.0f, 9999.0f];
|
|
m_next = __NULL__;
|
|
m_parent = __NULL__;
|
|
m_iFlags = 0i;
|
|
m_bVisible = true;
|
|
isVGUI = true;
|
|
|
|
Spawned();
|
|
}
|
|
|
|
void
|
|
VGUIWidget::SetTheme(VGUITheme theme)
|
|
{
|
|
m_theme = theme;
|
|
}
|
|
|
|
VGUITheme
|
|
VGUIWidget::GetTheme(void)
|
|
{
|
|
/* if no theme set, but we have a parent... inherit the parents' theme recursively */
|
|
if (!m_theme && m_parent)
|
|
return m_parent.GetTheme();
|
|
|
|
/* we have nothing, use the default one. */
|
|
if (!m_theme)
|
|
m_theme = spawn(VGUITheme);
|
|
|
|
return m_theme;
|
|
}
|
|
|
|
bool
|
|
VGUIWidget::Visible(void)
|
|
{
|
|
return m_bVisible;
|
|
}
|
|
|
|
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
|
|
VGUIWidget::PositionChanged(vector vecOld, vector vecNew)
|
|
{
|
|
|
|
}
|
|
|
|
void
|
|
VGUIWidget::SizeChanged(vector vecOld, vector vecNew)
|
|
{
|
|
|
|
}
|
|
|
|
void
|
|
VGUIWidget::SetPos(vector vecNewPos)
|
|
{
|
|
m_vecOrigin[0] = bound(0, vecNewPos[0], 9999.0);
|
|
m_vecOrigin[1] = bound(0, vecNewPos[1], 9999.0);
|
|
}
|
|
|
|
vector
|
|
VGUIWidget::GetPos(void)
|
|
{
|
|
return m_vecOrigin;
|
|
}
|
|
|
|
int
|
|
VGUIWidget::GetPosWidth(void)
|
|
{
|
|
return m_vecOrigin[0];
|
|
}
|
|
|
|
int
|
|
VGUIWidget::GetPosHeight(void)
|
|
{
|
|
return m_vecOrigin[1];
|
|
}
|
|
|
|
void
|
|
VGUIWidget::SetSize(vector vecNewSize)
|
|
{
|
|
vector vecOld = m_vecSize;
|
|
m_vecSize = vecNewSize;
|
|
m_vecSize[0] = bound(m_vecMinSize[0], vecNewSize[0], m_vecMaxSize[0]);
|
|
m_vecSize[1] = bound(m_vecMinSize[1], vecNewSize[1], m_vecMaxSize[1]);
|
|
|
|
SizeChanged(vecOld, m_vecSize);
|
|
}
|
|
|
|
vector
|
|
VGUIWidget::GetSize(void)
|
|
{
|
|
return m_vecSize;
|
|
}
|
|
|
|
int
|
|
VGUIWidget::GetSizeWidth(void)
|
|
{
|
|
return m_vecSize[0];
|
|
}
|
|
|
|
int
|
|
VGUIWidget::GetSizeHeight(void)
|
|
{
|
|
return m_vecSize[1];
|
|
}
|
|
|
|
void
|
|
VGUIWidget::SetMinSize (vector vecNewSize)
|
|
{
|
|
m_vecMinSize = vecNewSize;
|
|
}
|
|
|
|
vector
|
|
VGUIWidget::GetMinSize(void)
|
|
{
|
|
return m_vecMinSize;
|
|
}
|
|
|
|
void
|
|
VGUIWidget::SetMaxSize (vector vecNewSize)
|
|
{
|
|
m_vecMaxSize = vecNewSize;
|
|
}
|
|
|
|
vector
|
|
VGUIWidget::GetMaxSize(void)
|
|
{
|
|
return m_vecMaxSize;
|
|
}
|
|
|
|
void
|
|
VGUIWidget::FlagAdd(int iFlag)
|
|
{
|
|
m_iFlags |= iFlag;
|
|
}
|
|
|
|
void
|
|
VGUIWidget::FlagRemove(int iFlag)
|
|
{
|
|
m_iFlags -= (m_iFlags & iFlag);
|
|
}
|
|
|
|
bool
|
|
VGUIWidget::HasFlag(int flag)
|
|
{
|
|
return (m_iFlags & flag) ? true : false;
|
|
}
|
|
|
|
void
|
|
VGUIWidget::Reposition(void)
|
|
{
|
|
|
|
}
|
|
|
|
void
|
|
VGUIWidget::Add(VGUIWidget wNew)
|
|
{
|
|
VGUIWidget wNext = this;
|
|
VGUIWidget wParent;
|
|
do {
|
|
wParent = wNext;
|
|
wNext = wNext.m_next;
|
|
} while (wNext);
|
|
wParent.m_next = wNew;
|
|
wNew.m_parent = this;
|
|
}
|
|
|
|
.string classname;
|
|
void
|
|
VGUIWidget::Draw(void)
|
|
{
|
|
VGUIWidget wNext = this;
|
|
g_vguiWidgetCount = 0;
|
|
do {
|
|
wNext = wNext.m_next;
|
|
if (wNext && wNext.Visible() && wNext.m_parent.Visible()) {
|
|
g_vguiWidgetCount++;
|
|
wNext.Draw();
|
|
}
|
|
} while (wNext);
|
|
}
|
|
|
|
typedef struct
|
|
{
|
|
VGUIWidget member;
|
|
} vgui_input_scene_t;
|
|
|
|
bool
|
|
VGUIWidget::Input(float flEVType, float flKey, float flChar, float flDevID)
|
|
{
|
|
VGUIWidget wNext = this;
|
|
VGUIWidget wLast = __NULL__;
|
|
VGUIWidget wLastBefore = __NULL__;
|
|
|
|
/* figure out the last window in the chain... */
|
|
do {
|
|
wLastBefore = wNext;
|
|
wNext = wNext.m_next;
|
|
|
|
if (wNext) {
|
|
wLast = wNext;
|
|
}
|
|
} while (wNext);
|
|
|
|
//print(sprintf("Last widget: %S\n", wLast.classname));
|
|
|
|
/* we've found a window, let's test inputs backwards. */
|
|
while (wLast.classname) {
|
|
bool test = false;
|
|
|
|
if (wLast.Visible())
|
|
test = wLast.Input(flEVType, flKey, flChar, flDevID);
|
|
|
|
//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;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void
|
|
VGUIWidget::Spawned(void)
|
|
{
|
|
}
|
|
|
|
void
|
|
UISystem_Init(void)
|
|
{
|
|
/* we support fancier stuff in non-classic mode */
|
|
#ifndef CLASSIC_VGUI
|
|
string strTemp;
|
|
string strUIFile = "scripts/ui_style.txt";
|
|
filestream fileUI = fopen(strUIFile, FILE_READ);
|
|
|
|
UI_MAINCOLOR = [68,68,68] / 255;
|
|
UI_MAINALPHA = 1.0f;
|
|
|
|
if (fileUI >= 0) {
|
|
while ((strTemp = fgets(fileUI))) {
|
|
if (tokenizebyseparator(strTemp, "=") == 2) {
|
|
switch (argv(0)) {
|
|
case "COLOR":
|
|
UI_MAINCOLOR = stov(argv(1)) / 255;
|
|
break;
|
|
case "ALPHA":
|
|
UI_MAINALPHA = stof(argv(1)) / 255;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
fclose(fileUI);
|
|
} else {
|
|
error(sprintf("[MENU] Cannot load UI file %s!", strUIFile));
|
|
}
|
|
#endif
|
|
|
|
Font_Load("fonts/ui.font", g_fntDefault);
|
|
precache_pic("textures/ui/steam/icon_radiosel");
|
|
precache_pic("textures/ui/steam/icon_radiounsel");
|
|
precache_pic("textures/ui/steam/icon_checked");
|
|
precache_pic("textures/ui/steam/icon_emptybox");
|
|
precache_pic("textures/ui/steam/icon_down");
|
|
precache_pic("textures/ui/steam/icon_up");
|
|
precache_pic("textures/ui/steam/icon_close");
|
|
}
|
|
|
|
#ifdef CLIENT
|
|
VGUIWidget
|
|
UIClass_Spawn(string cname)
|
|
{
|
|
string func = strcat("spawnfunc_", cname);
|
|
|
|
if (isfunction(func)) {
|
|
entity oldself = self;
|
|
void(void) vFunc;
|
|
vFunc = externvalue(-2, func);
|
|
VGUIWidget new_uiclass = spawn(VGUIWidget);
|
|
self = new_uiclass;
|
|
vFunc();
|
|
self = oldself;
|
|
return (new_uiclass);
|
|
} else {
|
|
error("UIClass_Spawn: failed loading designated UI class\n");
|
|
}
|
|
|
|
return __NULL__;
|
|
}
|
|
#endif
|