nuclide/src/vgui/ui.qc

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