Moved modified HL SDK to trunk

This commit is contained in:
Scott Ehlert
2006-08-27 02:22:59 +00:00
parent 28c4ea4fec
commit 30235e05e5
900 changed files with 344676 additions and 0 deletions

181
hlsdk/game_shared/bitvec.h Normal file
View File

@ -0,0 +1,181 @@
//========= Copyright <20> 1996-2002, Valve LLC, All rights reserved. ============
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#ifndef BITVEC_H
#define BITVEC_H
#ifdef _WIN32
#ifndef __MINGW32__
#pragma once
#endif /* not __MINGW32__ */
#endif
#include <assert.h>
class CBitVecAccessor
{
public:
CBitVecAccessor(unsigned long *pDWords, int iBit);
void operator=(int val);
operator unsigned long();
private:
unsigned long *m_pDWords;
int m_iBit;
};
// CBitVec allows you to store a list of bits and do operations on them like they were
// an atomic type.
template<int NUM_BITS>
class CBitVec
{
public:
CBitVec();
// Set all values to the specified value (0 or 1..)
void Init(int val = 0);
// Access the bits like an array.
CBitVecAccessor operator[](int i);
// Operations on other bit vectors.
CBitVec& operator=(CBitVec<NUM_BITS> const &other);
bool operator==(CBitVec<NUM_BITS> const &other);
bool operator!=(CBitVec<NUM_BITS> const &other);
// Get underlying dword representations of the bits.
int GetNumDWords();
unsigned long GetDWord(int i);
void SetDWord(int i, unsigned long val);
int GetNumBits();
private:
enum {NUM_DWORDS = NUM_BITS/32 + !!(NUM_BITS & 31)};
unsigned long m_DWords[NUM_DWORDS];
};
// ------------------------------------------------------------------------ //
// CBitVecAccessor inlines.
// ------------------------------------------------------------------------ //
inline CBitVecAccessor::CBitVecAccessor(unsigned long *pDWords, int iBit)
{
m_pDWords = pDWords;
m_iBit = iBit;
}
inline void CBitVecAccessor::operator=(int val)
{
if(val)
m_pDWords[m_iBit >> 5] |= (1 << (m_iBit & 31));
else
m_pDWords[m_iBit >> 5] &= ~(unsigned long)(1 << (m_iBit & 31));
}
inline CBitVecAccessor::operator unsigned long()
{
return m_pDWords[m_iBit >> 5] & (1 << (m_iBit & 31));
}
// ------------------------------------------------------------------------ //
// CBitVec inlines.
// ------------------------------------------------------------------------ //
template<int NUM_BITS>
inline int CBitVec<NUM_BITS>::GetNumBits()
{
return NUM_BITS;
}
template<int NUM_BITS>
inline CBitVec<NUM_BITS>::CBitVec()
{
for(int i=0; i < NUM_DWORDS; i++)
m_DWords[i] = 0;
}
template<int NUM_BITS>
inline void CBitVec<NUM_BITS>::Init(int val)
{
for(int i=0; i < GetNumBits(); i++)
{
(*this)[i] = val;
}
}
template<int NUM_BITS>
inline CBitVec<NUM_BITS>& CBitVec<NUM_BITS>::operator=(CBitVec<NUM_BITS> const &other)
{
memcpy(m_DWords, other.m_DWords, sizeof(m_DWords));
return *this;
}
template<int NUM_BITS>
inline CBitVecAccessor CBitVec<NUM_BITS>::operator[](int i)
{
assert(i >= 0 && i < GetNumBits());
return CBitVecAccessor(m_DWords, i);
}
template<int NUM_BITS>
inline bool CBitVec<NUM_BITS>::operator==(CBitVec<NUM_BITS> const &other)
{
for(int i=0; i < NUM_DWORDS; i++)
if(m_DWords[i] != other.m_DWords[i])
return false;
return true;
}
template<int NUM_BITS>
inline bool CBitVec<NUM_BITS>::operator!=(CBitVec<NUM_BITS> const &other)
{
return !(*this == other);
}
template<int NUM_BITS>
inline int CBitVec<NUM_BITS>::GetNumDWords()
{
return NUM_DWORDS;
}
template<int NUM_BITS>
inline unsigned long CBitVec<NUM_BITS>::GetDWord(int i)
{
assert(i >= 0 && i < NUM_DWORDS);
return m_DWords[i];
}
template<int NUM_BITS>
inline void CBitVec<NUM_BITS>::SetDWord(int i, unsigned long val)
{
assert(i >= 0 && i < NUM_DWORDS);
m_DWords[i] = val;
}
#endif // BITVEC_H

View File

@ -0,0 +1,197 @@
//========= Copyright <20> 1996-2002, Valve LLC, All rights reserved. ============
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#include <stdarg.h>
#include <stdio.h>
#include "vgui_checkbutton2.h"
#include "vgui_loadtga.h"
#define EXTRA_X 5
using namespace vgui;
CCheckButton2::CCheckButton2() :
m_Label(""),
m_pChecked(NULL),
m_pUnchecked(NULL),
m_pHandler(NULL),
m_CheckboxPanel(NULL)
{
m_bOwnImages = false;
m_bChecked = false;
m_pChecked = m_pUnchecked = NULL;
m_bCheckboxLeft = true;
m_Label.setParent(this);
m_Label.setFgColor(255,255,255,0);
m_Label.setBgColor(0,0,0,255); // background is not drawn and foreground is white
m_Label.addInputSignal(this);
m_CheckboxPanel.setParent(this);
m_CheckboxPanel.addInputSignal(this);
setPaintBackgroundEnabled(false);
}
CCheckButton2::~CCheckButton2()
{
DeleteImages();
}
void CCheckButton2::SetImages(char const *pChecked, char const *pUnchecked)
{
DeleteImages();
m_pChecked = vgui_LoadTGA(pChecked);
m_pUnchecked = vgui_LoadTGA(pUnchecked);
m_bOwnImages = true;
SetupControls();
}
void CCheckButton2::SetImages(Image *pChecked, Image *pUnchecked)
{
DeleteImages();
m_pChecked = pChecked;
m_pUnchecked = pUnchecked;
m_bOwnImages = false;
SetupControls();
}
void CCheckButton2::DeleteImages()
{
if(m_bOwnImages)
{
delete m_pChecked;
delete m_pUnchecked;
}
m_pChecked = NULL;
m_pUnchecked = NULL;
m_bOwnImages = false;
SetupControls();
}
void CCheckButton2::SetCheckboxLeft(bool bLeftAlign)
{
m_bCheckboxLeft = bLeftAlign;
SetupControls();
}
bool CCheckButton2::GetCheckboxLeft()
{
return m_bCheckboxLeft;
}
void CCheckButton2::SetText(char const *pText, ...)
{
char str[512];
va_list marker;
va_start(marker, pText);
_vsnprintf(str, sizeof(str), pText, marker);
va_end(marker);
m_Label.setText(str);
SetupControls();
}
void CCheckButton2::SetTextColor(int r, int g, int b, int a)
{
m_Label.setFgColor(r, g, b, a);
repaint();
}
void CCheckButton2::SetHandler(ICheckButton2Handler *pHandler)
{
m_pHandler = pHandler;
}
bool CCheckButton2::IsChecked()
{
return m_bChecked;
}
void CCheckButton2::SetChecked(bool bChecked)
{
m_bChecked = bChecked;
SetupControls();
}
void CCheckButton2::internalMousePressed(MouseCode code)
{
m_bChecked = !m_bChecked;
if(m_pHandler)
m_pHandler->StateChanged(this);
SetupControls();
}
void CCheckButton2::SetupControls()
{
// Initialize the checkbutton bitmap.
Image *pBitmap = m_bChecked ? m_pChecked : m_pUnchecked;
Panel *controls[2] = {&m_CheckboxPanel, &m_Label};
int controlSizes[2][2];
controlSizes[0][0] = controlSizes[0][1] = 0;
if(pBitmap)
pBitmap->getSize(controlSizes[0][0], controlSizes[0][1]);
m_CheckboxPanel.setImage(pBitmap);
m_CheckboxPanel.setSize(controlSizes[0][0], controlSizes[0][1]);
// Get the label's size.
m_Label.getSize(controlSizes[1][0], controlSizes[1][1]);
m_Label.setContentAlignment(Label::a_west);
// Position the controls.
int iLeftControl = !m_bCheckboxLeft;
int iBiggestY = controlSizes[0][1] > controlSizes[1][0] ? 0 : 1;
controls[iLeftControl]->setPos(0, (controlSizes[iBiggestY][1] - controlSizes[iLeftControl][1]) / 2);
controls[!iLeftControl]->setPos(controlSizes[iLeftControl][0] + EXTRA_X, (controlSizes[iBiggestY][1] - controlSizes[!iLeftControl][1]) / 2);
// Fit this control to the sizes of the subcontrols.
setSize(controlSizes[0][0] + controlSizes[1][0] + EXTRA_X, (controlSizes[0][1] > controlSizes[1][1]) ? controlSizes[0][1] : controlSizes[1][1]);
repaint();
}
void CCheckButton2::mousePressed(MouseCode code, Panel *panel)
{
internalMousePressed(code);
}

View File

@ -0,0 +1,103 @@
//========= Copyright <20> 1996-2002, Valve LLC, All rights reserved. ============
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#ifndef VGUI_CHECKBUTTON2_H
#define VGUI_CHECKBUTTON2_H
#ifdef _WIN32
#ifndef __MINGW32__
#pragma once
#endif /* not __MINGW32__ */
#endif
#include "vgui_label.h"
#include "vgui_imagepanel.h"
#include "vgui_defaultinputsignal.h"
namespace vgui
{
class CCheckButton2;
class ICheckButton2Handler
{
public:
virtual void StateChanged(CCheckButton2 *pButton) = 0;
};
// VGUI checkbox class.
// - Provides access to the checkbox images.
// - Provides an easy callback mechanism for state changes.
// - Default background is invisible, and default text color is white.
class CCheckButton2 : public Panel, public CDefaultInputSignal
{
public:
CCheckButton2();
~CCheckButton2();
// Initialize the button with these.
void SetImages(char const *pChecked, char const *pUnchecked);
void SetImages(Image *pChecked, Image *pUnchecked); // If you use this, the button will never delete the images.
void DeleteImages();
// The checkbox can be to the left or the right of the text (default is left).
void SetCheckboxLeft(bool bLeftAlign);
bool GetCheckboxLeft();
// Set the label text.
void SetText(char const *pText, ...);
void SetTextColor(int r, int g, int b, int a);
// You can register for change notification here.
void SetHandler(ICheckButton2Handler *pHandler);
// Get/set the check state.
bool IsChecked();
void SetChecked(bool bChecked);
// Panel overrides.
public:
virtual void internalMousePressed(MouseCode code);
protected:
void SetupControls();
// InputSignal overrides.
protected:
virtual void mousePressed(MouseCode code,Panel* panel);
public:
ICheckButton2Handler *m_pHandler;
bool m_bCheckboxLeft;
Label m_Label;
ImagePanel m_CheckboxPanel;
Image *m_pChecked;
Image *m_pUnchecked;
bool m_bOwnImages;
bool m_bChecked;
};
}
#endif // VGUI_CHECKBUTTON2_H

View File

@ -0,0 +1,41 @@
//========= Copyright <20> 1996-2002, Valve LLC, All rights reserved. ============
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#ifndef VGUI_DEFAULTINPUTSIGNAL_H
#define VGUI_DEFAULTINPUTSIGNAL_H
#ifdef _WIN32
#ifndef __MINGW32__
#pragma once
#endif /* not __MINGW32__ */
#endif
#include "vgui_inputsignal.h"
namespace vgui
{
// This class derives from vgui::InputSignal and implements empty defaults for all of its functions.
class CDefaultInputSignal : public vgui::InputSignal
{
public:
virtual void cursorMoved(int x,int y,Panel* panel) {}
virtual void cursorEntered(Panel* panel) {}
virtual void cursorExited(Panel* panel) {}
virtual void mousePressed(MouseCode code,Panel* panel) {}
virtual void mouseDoublePressed(MouseCode code,Panel* panel) {}
virtual void mouseReleased(MouseCode code,Panel* panel) {}
virtual void mouseWheeled(int delta,Panel* panel) {}
virtual void keyPressed(KeyCode code,Panel* panel) {}
virtual void keyTyped(KeyCode code,Panel* panel) {}
virtual void keyReleased(KeyCode code,Panel* panel) {}
virtual void keyFocusTicked(Panel* panel) {}
};
}
#endif // VGUI_DEFAULTINPUTSIGNAL_H

View File

@ -0,0 +1,398 @@
//========= Copyright <20> 1996-2002, Valve LLC, All rights reserved. ============
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#include <assert.h>
#include "vgui_grid.h"
using namespace vgui;
#define AssertCheck(expr, msg) \
if(!(expr))\
{\
assert(!msg);\
return 0;\
}
// ------------------------------------------------------------------------------ //
// CGrid::CGridEntry.
// ------------------------------------------------------------------------------ //
CGrid::CGridEntry::CGridEntry()
{
m_pPanel = NULL;
m_bUnderline = false;
}
CGrid::CGridEntry::~CGridEntry()
{
}
// ------------------------------------------------------------------------------ //
// CGrid.
// ------------------------------------------------------------------------------ //
CGrid::CGrid()
{
Clear();
}
CGrid::~CGrid()
{
Term();
}
bool CGrid::SetDimensions(int xCols, int yRows)
{
Term();
m_GridEntries = new CGridEntry[xCols * yRows];
m_Widths = new int[xCols*2 + yRows*2];
m_Heights = m_Widths + xCols;
m_ColOffsets = m_Heights + yRows;
m_RowOffsets = m_ColOffsets + xCols;
if(!m_GridEntries || !m_Widths)
{
Term();
return false;
}
memset(m_Widths, 0, sizeof(int) * (xCols*2 + yRows*2));
m_xCols = xCols;
m_yRows = yRows;
return true;
}
void CGrid::Term()
{
delete [] m_GridEntries;
delete [] m_Widths;
Clear();
}
Panel* CGrid::GetEntry(int x, int y)
{
return GridEntry(x, y)->m_pPanel;
}
bool CGrid::SetEntry(int x, int y, Panel *pPanel)
{
CGridEntry *pEntry = GridEntry(x, y);
if(!pEntry)
return false;
if(pEntry->m_pPanel)
pEntry->m_pPanel->setParent(NULL);
pEntry->m_pPanel = pPanel;
if(pPanel)
pPanel->setParent(this);
m_bDirty = true;
return true;
}
int CGrid::GetXSpacing()
{
return m_xSpacing;
}
int CGrid::GetYSpacing()
{
return m_ySpacing;
}
void CGrid::SetSpacing(int xSpacing, int ySpacing)
{
if(xSpacing != m_xSpacing)
{
m_xSpacing = xSpacing;
CalcColOffsets(0);
m_bDirty = true;
}
if(ySpacing != m_ySpacing)
{
m_ySpacing = ySpacing;
CalcRowOffsets(0);
m_bDirty = true;
}
}
bool CGrid::SetColumnWidth(int iColumn, int width)
{
AssertCheck(iColumn >= 0 && iColumn < m_xCols, "CGrid::SetColumnWidth : invalid location specified");
m_Widths[iColumn] = width;
CalcColOffsets(iColumn+1);
m_bDirty = true;
return true;
}
bool CGrid::SetRowHeight(int iRow, int height)
{
AssertCheck(iRow >= 0 && iRow < m_yRows, "CGrid::SetColumnWidth : invalid location specified");
m_Heights[iRow] = height;
CalcRowOffsets(iRow+1);
m_bDirty = true;
return true;
}
int CGrid::GetColumnWidth(int iColumn)
{
AssertCheck(iColumn >= 0 && iColumn < m_xCols, "CGrid::GetColumnWidth: invalid location specified");
return m_Widths[iColumn];
}
int CGrid::GetRowHeight(int iRow)
{
AssertCheck(iRow >= 0 && iRow < m_yRows, "CGrid::GetRowHeight: invalid location specified");
return m_Heights[iRow];
}
int CGrid::CalcFitColumnWidth(int iColumn)
{
AssertCheck(iColumn >= 0 && iColumn < m_xCols, "CGrid::CalcFitColumnWidth: invalid location specified");
int maxSize = 0;
for(int i=0; i < m_yRows; i++)
{
Panel *pPanel = GridEntry(iColumn, i)->m_pPanel;
if(!pPanel)
continue;
int w, h;
pPanel->getSize(w,h);
if(w > maxSize)
maxSize = w;
}
return maxSize;
}
int CGrid::CalcFitRowHeight(int iRow)
{
AssertCheck(iRow >= 0 && iRow < m_yRows, "CGrid::CalcFitRowHeight: invalid location specified");
int maxSize = 0;
for(int i=0; i < m_xCols; i++)
{
Panel *pPanel = GridEntry(i, iRow)->m_pPanel;
if(!pPanel)
continue;
int w, h;
pPanel->getSize(w,h);
if(h > maxSize)
maxSize = h;
}
return maxSize;
}
void CGrid::AutoSetRowHeights()
{
for(int i=0; i < m_yRows; i++)
SetRowHeight(i, CalcFitRowHeight(i));
}
bool CGrid::GetEntryBox(
int col, int row, int &x, int &y, int &w, int &h)
{
AssertCheck(col >= 0 && col < m_xCols && row >= 0 && row < m_yRows, "CGrid::GetEntryBox: invalid location specified");
x = m_ColOffsets[col];
w = m_Widths[col];
y = m_RowOffsets[row];
h = m_Heights[row];
return true;
}
bool CGrid::CopyColumnWidths(CGrid *pOther)
{
if(!pOther || pOther->m_xCols != m_xCols)
return false;
for(int i=0; i < m_xCols; i++)
m_Widths[i] = pOther->m_Widths[i];
CalcColOffsets(0);
m_bDirty = true;
return true;
}
void CGrid::RepositionContents()
{
for(int x=0; x < m_xCols; x++)
{
for(int y=0; y < m_yRows; y++)
{
Panel *pPanel = GridEntry(x,y)->m_pPanel;
if(!pPanel)
continue;
pPanel->setBounds(
m_ColOffsets[x],
m_RowOffsets[y],
m_Widths[x],
m_Heights[y]);
}
}
m_bDirty = false;
}
int CGrid::CalcDrawHeight()
{
if(m_yRows > 0)
{
return m_RowOffsets[m_yRows-1] + m_Heights[m_yRows - 1] + m_ySpacing;
}
else
{
return 0;
}
}
void CGrid::paint()
{
if(m_bDirty)
RepositionContents();
Panel::paint();
// walk the grid looking for underlined rows
int x = 0, y = 0;
for (int row = 0; row < m_yRows; row++)
{
CGridEntry *cell = GridEntry(0, row);
y += cell->m_pPanel->getTall() + m_ySpacing;
if (cell->m_bUnderline)
{
drawSetColor(cell->m_UnderlineColor[0], cell->m_UnderlineColor[1], cell->m_UnderlineColor[2], cell->m_UnderlineColor[3]);
drawFilledRect(0, y - (cell->m_iUnderlineOffset + 1), getWide(), y - cell->m_iUnderlineOffset);
}
}
}
void CGrid::paintBackground()
{
Panel::paintBackground();
}
//-----------------------------------------------------------------------------
// Purpose: sets underline color for a particular row
//-----------------------------------------------------------------------------
void CGrid::SetRowUnderline(int row, bool enabled, int offset, int r, int g, int b, int a)
{
CGridEntry *cell = GridEntry(0, row);
cell->m_bUnderline = enabled;
if (enabled)
{
cell->m_iUnderlineOffset = offset;
cell->m_UnderlineColor[0] = r;
cell->m_UnderlineColor[1] = g;
cell->m_UnderlineColor[2] = b;
cell->m_UnderlineColor[3] = a;
}
}
void CGrid::Clear()
{
m_xCols = m_yRows = 0;
m_Widths = NULL;
m_GridEntries = NULL;
m_xSpacing = m_ySpacing = 0;
m_bDirty = false;
}
CGrid::CGridEntry* CGrid::GridEntry(int x, int y)
{
AssertCheck(x >= 0 && x < m_xCols && y >= 0 && y < m_yRows, "CGrid::GridEntry: invalid location specified");
return &m_GridEntries[y*m_xCols + x];
}
void CGrid::CalcColOffsets(int iStart)
{
int cur = m_xSpacing;
if(iStart != 0)
cur += m_ColOffsets[iStart-1] + m_Widths[iStart-1];
for(int i=iStart; i < m_xCols; i++)
{
m_ColOffsets[i] = cur;
cur += m_Widths[i] + m_xSpacing;
}
}
void CGrid::CalcRowOffsets(int iStart)
{
int cur = m_ySpacing;
if(iStart != 0)
cur += m_RowOffsets[iStart-1];
for(int i=iStart; i < m_yRows; i++)
{
m_RowOffsets[i] = cur;
cur += m_Heights[i] + m_ySpacing;
}
}
bool CGrid::getCellAtPoint(int worldX, int worldY, int &row, int &col)
{
row = -1; col = -1;
for(int x=0; x < m_xCols; x++)
{
for(int y=0; y < m_yRows; y++)
{
Panel *pPanel = GridEntry(x,y)->m_pPanel;
if (!pPanel)
continue;
if (pPanel->isWithin(worldX, worldY))
{
col = x;
row = y;
return true;
}
}
}
return false;
}

View File

@ -0,0 +1,124 @@
//========= Copyright <20> 1996-2002, Valve LLC, All rights reserved. ============
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#ifndef VGUI_GRID_H
#define VGUI_GRID_H
#ifdef _WIN32
#ifndef __MINGW32__
#pragma once
#endif /* not __MINGW32__ */
#endif
#include "vgui_panel.h"
namespace vgui
{
// The grid control simply manages a grid of panels. You can adjust column sizes and spacings and
// configure and fill the panels however you want.
// To use this control, call SetDimensions, SetSpacing and fill the controls.
class CGrid : public Panel
{
public:
CGrid();
virtual ~CGrid();
bool SetDimensions(int xCols, int yRows); // Set how many columns and rows in the grid.
void Term();
Panel* GetEntry(int x, int y); // Get the panel associated with a grid entry.
bool SetEntry(int x, int y, Panel *pPanel);
int GetXSpacing();
int GetYSpacing();
void SetSpacing(int xSpacing, int ySpacing); // Set spacing between rows and columns.
bool SetColumnWidth(int iColumn, int width); // Set a column's width.
bool SetRowHeight(int iRow, int height); // Set a row's height.
int GetColumnWidth(int iColumn);
int GetRowHeight(int iRow);
int CalcFitColumnWidth(int iColumn); // Returns the maximum width of all panels in the column.
int CalcFitRowHeight(int iRow); // Returns the maximum height of all panels in the row.
int CalcDrawHeight(); // Returns how many pixels high the grid control should be
// for all of its contents to be visible (based on its row heights
// and y spacing).
void AutoSetRowHeights(); // Just does SetRowHeight(iRow, CalcFitRowHeight(iRow)) for all rows.
bool GetEntryBox( // Returns the bounding box for the specified entry.
int col, int row, int &x, int &y, int &w, int &h);
bool CopyColumnWidths(CGrid *pOther); // Copy the column widths from the other grid. Fails if the
// column count is different.
void RepositionContents(); // Sets the size and position of all the grid entries based
// on current spacings and row/column widths.
// You usually only want to call this while setting up the control
// if you want to get the position or dimensions of the child
// controls. This will set them.
void SetRowUnderline(int row, bool enabled, int offset, int r, int g, int b, int a); // sets underline color for a particular row
// returns the true if found, false otherwise
bool getCellAtPoint(int worldX, int worldY, int &row, int &col);
// Panel overrides.
public:
virtual void paint();
virtual void paintBackground();
protected:
class CGridEntry
{
public:
CGridEntry();
~CGridEntry();
Panel *m_pPanel;
bool m_bUnderline;
short m_UnderlineColor[4];
int m_iUnderlineOffset;
};
void Clear();
CGridEntry* GridEntry(int x, int y);
void CalcColOffsets(int iStart);
void CalcRowOffsets(int iStart);
protected:
bool m_bDirty; // Set when controls will need to be repositioned.
int m_xCols;
int m_yRows;
int m_xSpacing;
int m_ySpacing;
int *m_Widths;
int *m_Heights;
int *m_ColOffsets;
int *m_RowOffsets;
CGridEntry *m_GridEntries;
};
};
#endif // VGUI_GRID_H

View File

@ -0,0 +1,45 @@
//========= Copyright <20> 1996-2002, Valve LLC, All rights reserved. ============
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#include "vgui_helpers.h"
using namespace vgui;
void AlignPanel(Panel *pChild, Panel *pParent, int alignment)
{
int w, h, cw, ch;
pParent->getSize(w, h);
pChild->getSize(cw, ch);
int xCenter = (w - cw) / 2;
int yCenter = (h - ch) / 2;
if(alignment == Label::a_west)
pChild->setPos(0, yCenter);
else if(alignment == Label::a_northwest)
pChild->setPos(0,0);
else if(alignment == Label::a_north)
pChild->setPos(xCenter, 0);
else if(alignment == Label::a_northeast)
pChild->setPos(w - cw, 0);
else if(alignment == Label::a_east)
pChild->setPos(w - cw, yCenter);
else if(alignment == Label::a_southeast)
pChild->setPos(w - cw, h - ch);
else if(alignment == Label::a_south)
pChild->setPos(xCenter, h - ch);
else if(alignment == Label::a_southwest)
pChild->setPos(0, h - ch);
else if(alignment == Label::a_center)
pChild->setPos(xCenter, yCenter);
}

View File

@ -0,0 +1,33 @@
//========= Copyright <20> 1996-2002, Valve LLC, All rights reserved. ============
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#ifndef VGUI_HELPERS_H
#define VGUI_HELPERS_H
#ifdef _WIN32
#ifndef __MINGW32__
#pragma once
#endif /* not __MINGW32__ */
#endif
#include "vgui_panel.h"
#include "vgui_label.h"
inline int PanelTop(vgui::Panel *pPanel) {int x,y,w,h; pPanel->getBounds(x,y,w,h); return y;}
inline int PanelLeft(vgui::Panel *pPanel) {int x,y,w,h; pPanel->getBounds(x,y,w,h); return x;}
inline int PanelRight(vgui::Panel *pPanel) {int x,y,w,h; pPanel->getBounds(x,y,w,h); return x+w;}
inline int PanelBottom(vgui::Panel *pPanel) {int x,y,w,h; pPanel->getBounds(x,y,w,h); return y+h;}
inline int PanelWidth(vgui::Panel *pPanel) {int x,y,w,h; pPanel->getBounds(x,y,w,h); return w;}
inline int PanelHeight(vgui::Panel *pPanel) {int x,y,w,h; pPanel->getBounds(x,y,w,h); return h;}
// Places child at the requested position inside pParent. iAlignment is from Label::Alignment.
void AlignPanel(vgui::Panel *pChild, vgui::Panel *pParent, int alignment);
#endif // VGUI_HELPERS_H

View File

@ -0,0 +1,207 @@
//========= Copyright <20> 1996-2002, Valve LLC, All rights reserved. ============
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#include "vgui_listbox.h"
using namespace vgui;
CListBox::CListBox() : Panel(0, 0, 0, 0),
m_ItemsPanel(0,0,0,0),
m_ScrollBar(0, 0, 0, 0, true),
m_Slider(0, 0, 10, 40, true)
{
m_Signal.m_pListBox = this;
m_ItemsPanel.setParent(this);
m_ItemsPanel.setBgColor(0,0,0,255);
m_Slider.setRangeWindow(50);
m_Slider.setRangeWindowEnabled(true);
m_ScrollBar.setParent(this);
m_ScrollBar.addIntChangeSignal(&m_Signal);
m_ScrollBar.setSlider(&m_Slider);
m_ScrollBar.setButtonPressedScrollValue(1);
m_Items.m_pNext = m_Items.m_pPrev = &m_Items;
m_ItemOffset = 0;
m_iScrollMax = -1;
}
CListBox::~CListBox()
{
Term();
}
void CListBox::Init()
{
Term();
}
void CListBox::Term()
{
m_ItemOffset = 0;
// Free the LBItems.
LBItem *pNext;
for(LBItem *pItem=m_Items.m_pNext; pItem != &m_Items; pItem=pNext)
{
pItem->m_pPanel->setParent(NULL); // detach the panel from us
pNext = pItem->m_pNext;
delete pItem;
}
m_Items.m_pPrev = m_Items.m_pNext = &m_Items;
}
void CListBox::AddItem(Panel* panel)
{
// Add the item.
LBItem *pItem = new LBItem;
if(!pItem)
return;
pItem->m_pPanel = panel;
pItem->m_pPanel->setParent(&m_ItemsPanel);
pItem->m_pPrev = m_Items.m_pPrev;
pItem->m_pNext = &m_Items;
pItem->m_pNext->m_pPrev = pItem->m_pPrev->m_pNext = pItem;
m_ScrollBar.setRange(0, GetScrollMax());
m_Slider.setRangeWindow(50);
m_Slider.setRangeWindowEnabled(true);
InternalLayout();
}
int CListBox::GetNumItems()
{
int count=0;
for(LBItem *pItem=m_Items.m_pNext; pItem != &m_Items; pItem=pItem->m_pNext)
++count;
return count;
}
int CListBox::GetItemWidth()
{
int wide, tall;
m_ItemsPanel.getSize(wide, tall);
return wide;
}
int CListBox::GetScrollPos()
{
return m_ItemOffset;
}
void CListBox::SetScrollPos(int pos)
{
int maxItems = GetScrollMax();
if(maxItems < 0)
return;
m_ItemOffset = (pos < 0) ? 0 : ((pos > maxItems) ? maxItems : pos);
InternalLayout();
}
void CListBox::setPos(int x, int y)
{
Panel::setPos(x, y);
InternalLayout();
}
void CListBox::setSize(int wide,int tall)
{
Panel::setSize(wide,tall);
InternalLayout();
}
void CListBox::setPixelScroll(int value)
{
m_ItemOffset = m_ScrollBar.getValue();
InternalLayout();
}
void CListBox::InternalLayout()
{
int x, y, wide, tall;
getBounds(x, y, wide, tall);
// Reposition the main panel and the scrollbar.
m_ItemsPanel.setBounds(0, 0, wide-15, tall);
m_ScrollBar.setBounds(wide-15, 0, 15, tall);
bool bNeedScrollbar = false;
// Reposition the items.
int curItem = 0;
int curY = 0;
int maxItem = GetScrollMax();
for(LBItem *pItem=m_Items.m_pNext; pItem != &m_Items; pItem=pItem->m_pNext)
{
if(curItem < m_ItemOffset)
{
pItem->m_pPanel->setVisible(false);
bNeedScrollbar = true;
}
else if (curItem >= maxItem)
{
// item is past the end of the items we care about
pItem->m_pPanel->setVisible(false);
}
else
{
pItem->m_pPanel->setVisible(true);
int itemWidth, itemHeight;
pItem->m_pPanel->getSize(itemWidth, itemHeight);
// Don't change the item's height but change its width to fit the listbox.
pItem->m_pPanel->setBounds(0, curY, wide, itemHeight);
curY += itemHeight;
if (curY > tall)
{
bNeedScrollbar = true;
}
}
++curItem;
}
m_ScrollBar.setVisible(bNeedScrollbar);
repaint();
}
void CListBox::paintBackground()
{
}
void CListBox::SetScrollRange(int maxScroll)
{
m_iScrollMax = maxScroll;
m_ScrollBar.setRange(0, maxScroll);
InternalLayout();
}
int CListBox::GetScrollMax()
{
if (m_iScrollMax < 0)
{
return GetNumItems() - 1;
}
return m_iScrollMax;
}

View File

@ -0,0 +1,117 @@
//========= Copyright <20> 1996-2002, Valve LLC, All rights reserved. ============
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#ifndef VOICE_LISTBOX_H
#define VOICE_LISTBOX_H
#ifdef _WIN32
#ifndef __MINGW32__
#pragma once
#endif /* not __MINGW32__ */
#endif
#include "VGUI_Panel.h"
#include "VGUI_IntChangeSignal.h"
#include "VGUI_Slider2.h"
#include "VGUI_ScrollBar2.h"
namespace vgui
{
// Listbox class used by voice code. Based off of vgui's list panel but with some modifications:
// - This listbox clips its child items to its rectangle.
// - You can access things like the scrollbar and find out the item width.
// - The scrollbar scrolls one element at a time and the range is correct.
// Note: this listbox does not provide notification when items are
class CListBox : public Panel
{
public:
CListBox();
~CListBox();
void Init();
void Term();
// Add an item to the listbox. This automatically sets the item's parent to the listbox
// and resizes the item's width to fit within the listbox.
void AddItem(Panel *pPanel);
// Get the number of items currently in the listbox.
int GetNumItems();
// Get the width that listbox items will be set to (this changes if you resize the listbox).
int GetItemWidth();
// Get/set the scrollbar position (position says which element is at the top of the listbox).
int GetScrollPos();
void SetScrollPos(int pos);
// sets the last item the listbox should scroll to
// scroll to GetNumItems() if not set
void SetScrollRange(int maxScroll);
// returns the maximum value the scrollbar can scroll to
int GetScrollMax();
// vgui overrides.
public:
virtual void setPos(int x, int y);
virtual void setSize(int wide,int tall);
virtual void setPixelScroll(int value);
virtual void paintBackground();
protected:
class LBItem
{
public:
Panel *m_pPanel;
LBItem *m_pPrev, *m_pNext;
};
class ListBoxSignal : public IntChangeSignal
{
public:
void intChanged(int value,Panel* panel)
{
m_pListBox->setPixelScroll(-value);
}
vgui::CListBox *m_pListBox;
};
protected:
void InternalLayout();
protected:
// All the items..
LBItem m_Items;
Panel m_ItemsPanel;
int m_ItemOffset; // where we're scrolled to
Slider2 m_Slider;
ScrollBar2 m_ScrollBar;
ListBoxSignal m_Signal;
int m_iScrollMax;
};
}
#endif // VOICE_LISTBOX_H

View File

@ -0,0 +1,93 @@
//========= Copyright <20> 1996-2002, Valve LLC, All rights reserved. ============
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#include "../cl_dll/wrect.h"
#include "../cl_dll/cl_dll.h"
#include "vgui.h"
#include "vgui_loadtga.h"
#include "vgui_inputstream.h"
// ---------------------------------------------------------------------- //
// Helper class for loading tga files.
// ---------------------------------------------------------------------- //
class MemoryInputStream : public vgui::InputStream
{
public:
MemoryInputStream()
{
m_pData = NULL;
m_DataLen = m_ReadPos = 0;
}
virtual void seekStart(bool& success) {m_ReadPos=0; success=true;}
virtual void seekRelative(int count,bool& success) {m_ReadPos+=count; success=true;}
virtual void seekEnd(bool& success) {m_ReadPos=m_DataLen; success=true;}
virtual int getAvailable(bool& success) {success=false; return 0;} // This is what vgui does for files...
virtual uchar readUChar(bool& success)
{
if(m_ReadPos>=0 && m_ReadPos<m_DataLen)
{
success=true;
uchar ret = m_pData[m_ReadPos];
++m_ReadPos;
return ret;
}
else
{
success=false;
return 0;
}
}
virtual void readUChar(uchar* buf,int count,bool& success)
{
for(int i=0; i < count; i++)
buf[i] = readUChar(success);
}
virtual void close(bool& success)
{
m_pData = NULL;
m_DataLen = m_ReadPos = 0;
}
uchar *m_pData;
int m_DataLen;
int m_ReadPos;
};
vgui::BitmapTGA* vgui_LoadTGA(char const *pFilename)
{
MemoryInputStream stream;
stream.m_pData = gEngfuncs.COM_LoadFile((char*)pFilename, 5, &stream.m_DataLen);
if(!stream.m_pData)
return NULL;
stream.m_ReadPos = 0;
vgui::BitmapTGA *pRet = new vgui::BitmapTGA(&stream, true);
gEngfuncs.COM_FreeFile(stream.m_pData);
return pRet;
}
vgui::BitmapTGA* vgui_LoadTGANoInvertAlpha(char const *pFilename)
{
MemoryInputStream stream;
stream.m_pData = gEngfuncs.COM_LoadFile((char*)pFilename, 5, &stream.m_DataLen);
if(!stream.m_pData)
return NULL;
stream.m_ReadPos = 0;
vgui::BitmapTGA *pRet = new vgui::BitmapTGA(&stream, false);
gEngfuncs.COM_FreeFile(stream.m_pData);
return pRet;
}

View File

@ -0,0 +1,24 @@
//========= Copyright <20> 1996-2002, Valve LLC, All rights reserved. ============
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#ifndef VGUI_LOADTGA_H
#define VGUI_LOADTGA_H
#ifdef _WIN32
#ifndef __MINGW32__
#pragma once
#endif /* not __MINGW32__ */
#endif
#include "vgui_bitmaptga.h"
vgui::BitmapTGA* vgui_LoadTGA(char const *pFilename);
vgui::BitmapTGA* vgui_LoadTGANoInvertAlpha(char const *pFilename);
#endif // VGUI_LOADTGA_H

View File

@ -0,0 +1,310 @@
//========= Copyright <20> 1996-2002, Valve LLC, All rights reserved. ============
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#include "VGUI_ScrollBar2.h"
#include "VGUI_Slider2.h"
#include "vgui_loadtga.h"
#include<VGUI_IntChangeSignal.h>
#include<VGUI_Button.h>
#include<VGUI_ActionSignal.h>
#include<VGUI_LineBorder.h>
using namespace vgui;
namespace
{
class FooDefaultScrollBarIntChangeSignal : public IntChangeSignal
{
public:
FooDefaultScrollBarIntChangeSignal(ScrollBar2* scrollBar)
{
_scrollBar=scrollBar;
}
virtual void intChanged(int value,Panel* panel)
{
_scrollBar->fireIntChangeSignal();
}
protected:
ScrollBar2* _scrollBar;
};
class FooDefaultButtonSignal : public ActionSignal
{
public:
ScrollBar2* _scrollBar;
int _buttonIndex;
public:
FooDefaultButtonSignal(ScrollBar2* scrollBar,int buttonIndex)
{
_scrollBar=scrollBar;
_buttonIndex=buttonIndex;
}
public:
virtual void actionPerformed(Panel* panel)
{
_scrollBar->doButtonPressed(_buttonIndex);
}
};
}
//-----------------------------------------------------------------------------
// Purpose: Default scrollbar button
// Draws in new scoreboard style
//-----------------------------------------------------------------------------
class ScrollBarButton : public Button
{
private:
LineBorder m_Border;
public:
ScrollBarButton(const char *filename, int x, int y, int wide, int tall) : m_Border(Color(60, 60, 60, 0)), Button("", x, y, wide, tall)
{
Image *image = vgui_LoadTGA(filename);
if (image)
{
image->setColor(Color(140, 140, 140, 0));
setImage(image);
}
setBorder(&m_Border);
}
virtual void paintBackground()
{
int wide,tall;
getPaintSize(wide,tall);
// fill the background
drawSetColor(0, 0, 0, 0);
drawFilledRect(0, 0, wide, tall);
}
};
//-----------------------------------------------------------------------------
// Purpose: Constructor
// Input : x -
// y -
// wide -
// tall -
// vertical -
//-----------------------------------------------------------------------------
ScrollBar2::ScrollBar2(int x,int y,int wide,int tall,bool vertical) : Panel(x,y,wide,tall)
{
_slider=null;
_button[0]=null;
_button[1]=null;
if(vertical)
{
setSlider(new Slider2(0,wide-1,wide,(tall-(wide*2))+2,true));
setButton(new ScrollBarButton("gfx/vgui/arrowup.tga",0,0,wide,wide),0);
setButton(new ScrollBarButton("gfx/vgui/arrowdown.tga",0,tall-wide,wide,wide),1);
}
else
{
// untested code
setSlider(new Slider2(tall,0,wide-(tall*2),tall,false));
setButton(new ScrollBarButton("gfx/vgui/320_arrowlt.tga",0,0,tall+1,tall+1),0);
setButton(new ScrollBarButton("gfx/vgui/320_arrowrt.tga",wide-tall,0,tall+1,tall+1),1);
}
setPaintBorderEnabled(true);
setPaintBackgroundEnabled(true);
setPaintEnabled(true);
setButtonPressedScrollValue(15);
validate();
}
void ScrollBar2::setSize(int wide,int tall)
{
Panel::setSize(wide,tall);
if(_slider==null)
{
return;
}
if(_button[0]==null)
{
return;
}
if(_button[1]==null)
{
return;
}
getPaintSize(wide,tall);
if(_slider->isVertical())
{
_slider->setBounds(0,wide,wide,tall-(wide*2));
//_slider->setBounds(0,0,wide,tall);
_button[0]->setBounds(0,0,wide,wide);
_button[1]->setBounds(0,tall-wide,wide,wide);
}
else
{
_slider->setBounds(tall,0,wide-(tall*2),tall);
//_slider->setBounds(0,0,wide,tall);
_button[0]->setBounds(0,0,tall,tall);
_button[1]->setBounds((wide-tall),0,tall,tall);
}
}
void ScrollBar2::performLayout()
{
}
void ScrollBar2::setValue(int value)
{
_slider->setValue(value);
}
int ScrollBar2::getValue()
{
return _slider->getValue();
}
void ScrollBar2::addIntChangeSignal(IntChangeSignal* s)
{
_intChangeSignalDar.putElement(s);
_slider->addIntChangeSignal(new FooDefaultScrollBarIntChangeSignal(this));
}
void ScrollBar2::setRange(int min,int max)
{
_slider->setRange(min,max);
}
void ScrollBar2::fireIntChangeSignal()
{
for(int i=0;i<_intChangeSignalDar.getCount();i++)
{
_intChangeSignalDar[i]->intChanged(_slider->getValue(),this);
}
}
bool ScrollBar2::isVertical()
{
return _slider->isVertical();
}
bool ScrollBar2::hasFullRange()
{
return _slider->hasFullRange();
}
//LEAK: new and old slider will leak
void ScrollBar2::setButton(Button* button,int index)
{
if(_button[index]!=null)
{
removeChild(_button[index]);
}
_button[index]=button;
addChild(_button[index]);
_button[index]->addActionSignal(new FooDefaultButtonSignal(this,index));
validate();
//_button[index]->setVisible(false);
}
Button* ScrollBar2::getButton(int index)
{
return _button[index];
}
//LEAK: new and old slider will leak
void ScrollBar2::setSlider(Slider2 *slider)
{
if(_slider!=null)
{
removeChild(_slider);
}
_slider=slider;
addChild(_slider);
_slider->addIntChangeSignal(new FooDefaultScrollBarIntChangeSignal(this));
validate();
}
Slider2 *ScrollBar2::getSlider()
{
return _slider;
}
void ScrollBar2::doButtonPressed(int buttonIndex)
{
if(buttonIndex==0)
{
_slider->setValue(_slider->getValue()-_buttonPressedScrollValue);
}
else
{
_slider->setValue(_slider->getValue()+_buttonPressedScrollValue);
}
}
void ScrollBar2::setButtonPressedScrollValue(int value)
{
_buttonPressedScrollValue=value;
}
void ScrollBar2::setRangeWindow(int rangeWindow)
{
_slider->setRangeWindow(rangeWindow);
}
void ScrollBar2::setRangeWindowEnabled(bool state)
{
_slider->setRangeWindowEnabled(state);
}
void ScrollBar2::validate()
{
if(_slider!=null)
{
int buttonOffset=0;
for(int i=0;i<2;i++)
{
if(_button[i]!=null)
{
if(_button[i]->isVisible())
{
if(_slider->isVertical())
{
buttonOffset+=_button[i]->getTall();
}
else
{
buttonOffset+=_button[i]->getWide();
}
}
}
}
_slider->setButtonOffset(buttonOffset);
}
int wide,tall;
getSize(wide,tall);
setSize(wide,tall);
}

View File

@ -0,0 +1,64 @@
//========= Copyright <20> 1996-2002, Valve LLC, All rights reserved. ============
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#ifndef VGUI_SCROLLBAR2_H
#define VGUI_SCROLLBAR2_H
#ifdef _WIN32
#ifndef __MINGW32__
#pragma once
#endif /* not __MINGW32__ */
#endif
#include<VGUI.h>
#include<VGUI_Panel.h>
#include<VGUI_Dar.h>
namespace vgui
{
class IntChangeSignal;
class Button;
class Slider2;
//-----------------------------------------------------------------------------
// Purpose: Hacked up version of the vgui scrollbar
//-----------------------------------------------------------------------------
class VGUIAPI ScrollBar2 : public Panel
{
public:
ScrollBar2(int x,int y,int wide,int tall,bool vertical);
public:
virtual void setValue(int value);
virtual int getValue();
virtual void addIntChangeSignal(IntChangeSignal* s);
virtual void setRange(int min,int max);
virtual void setRangeWindow(int rangeWindow);
virtual void setRangeWindowEnabled(bool state);
virtual void setSize(int wide,int tall);
virtual bool isVertical();
virtual bool hasFullRange();
virtual void setButton(Button *button,int index);
virtual Button* getButton(int index);
virtual void setSlider(Slider2 *slider);
virtual Slider2 *getSlider();
virtual void doButtonPressed(int buttonIndex);
virtual void setButtonPressedScrollValue(int value);
virtual void validate();
public: //bullshit public
virtual void fireIntChangeSignal();
protected:
virtual void performLayout();
protected:
Button* _button[2];
Slider2 *_slider;
Dar<IntChangeSignal*> _intChangeSignalDar;
int _buttonPressedScrollValue;
};
}
#endif // VGUI_SCROLLBAR2_H

View File

@ -0,0 +1,436 @@
//========= Copyright <20> 1996-2002, Valve LLC, All rights reserved. ============
//
// Purpose: New version of the slider bar
//
// $NoKeywords: $
//=============================================================================
#include "VGUI_Slider2.h"
#include<VGUI_InputSignal.h>
#include<VGUI_App.h>
#include<VGUI_IntChangeSignal.h>
#include<VGUI_MouseCode.h>
using namespace vgui;
namespace
{
class FooDefaultSliderSignal : public InputSignal
{
private:
Slider2* _slider;
public:
FooDefaultSliderSignal(Slider2* slider)
{
_slider=slider;
}
public:
void cursorMoved(int x,int y,Panel* panel)
{
_slider->privateCursorMoved(x,y,panel);
}
void cursorEntered(Panel* panel){}
void cursorExited(Panel* panel){}
void mouseDoublePressed(MouseCode code,Panel* panel){}
void mousePressed(MouseCode code,Panel* panel)
{
_slider->privateMousePressed(code,panel);
}
void mouseReleased(MouseCode code,Panel* panel)
{
_slider->privateMouseReleased(code,panel);
}
void mouseWheeled(int delta,Panel* panel){}
void keyPressed(KeyCode code,Panel* panel){}
void keyTyped(KeyCode code,Panel* panel){}
void keyReleased(KeyCode code,Panel* panel){}
void keyFocusTicked(Panel* panel){}
};
}
Slider2::Slider2(int x,int y,int wide,int tall,bool vertical) : Panel(x,y,wide,tall)
{
_vertical=vertical;
_dragging=false;
_value=0;
_range[0]=0;
_range[1]=299;
_rangeWindow=0;
_rangeWindowEnabled=false;
_buttonOffset=0;
recomputeNobPosFromValue();
addInputSignal(new FooDefaultSliderSignal(this));
}
void Slider2::setSize(int wide,int tall)
{
Panel::setSize(wide,tall);
recomputeNobPosFromValue();
}
bool Slider2::isVertical()
{
return _vertical;
}
void Slider2::setValue(int value)
{
int oldValue=_value;
if(value<_range[0])
{
value=_range[0];
}
if(value>_range[1])
{
value=_range[1];
}
_value=value;
recomputeNobPosFromValue();
if(_value!=oldValue)
{
fireIntChangeSignal();
}
}
int Slider2::getValue()
{
return _value;
}
void Slider2::recomputeNobPosFromValue()
{
int wide,tall;
getPaintSize(wide,tall);
float fwide=(float)wide;
float ftall=(float)tall;
float frange=(float)(_range[1]-_range[0]);
float fvalue=(float)(_value-_range[0]);
float fper=fvalue/frange;
float frangewindow=(float)(_rangeWindow);
if(frangewindow<0)
{
frangewindow=0;
}
if(!_rangeWindowEnabled)
{
frangewindow=frange;
}
if ( frangewindow > 0 )
{
if(_vertical)
{
float fnobsize=frangewindow;
float freepixels = ftall - fnobsize;
float firstpixel = freepixels * fper;
_nobPos[0]=(int)( firstpixel );
_nobPos[1]=(int)( firstpixel + fnobsize );
if(_nobPos[1]>tall)
{
_nobPos[0]=tall-((int)fnobsize);
_nobPos[1]=tall;
}
}
else
{
float fnobsize=frangewindow;
float freepixels = fwide - fnobsize;
float firstpixel = freepixels * fper;
_nobPos[0]=(int)( firstpixel );
_nobPos[1]=(int)( firstpixel + fnobsize );
if(_nobPos[1]>wide)
{
_nobPos[0]=wide-((int)fnobsize);
_nobPos[1]=wide;
}
}
}
repaint();
}
void Slider2::recomputeValueFromNobPos()
{
int wide,tall;
getPaintSize(wide,tall);
float fwide=(float)wide;
float ftall=(float)tall;
float frange=(float)(_range[1]-_range[0]);
float fvalue=(float)(_value-_range[0]);
float fnob=(float)_nobPos[0];
float frangewindow=(float)(_rangeWindow);
if(frangewindow<0)
{
frangewindow=0;
}
if(!_rangeWindowEnabled)
{
frangewindow=frange;
}
if ( frangewindow > 0 )
{
if(_vertical)
{
float fnobsize=frangewindow;
fvalue=frange*(fnob/(ftall-fnobsize));
}
else
{
float fnobsize=frangewindow;
fvalue=frange*(fnob/(fwide-fnobsize));
}
}
// Take care of rounding issues.
_value=(int)(fvalue+_range[0]+0.5);
// Clamp final result
_value = ( _value < _range[1] ) ? _value : _range[1];
}
bool Slider2::hasFullRange()
{
int wide,tall;
getPaintSize(wide,tall);
float fwide=(float)wide;
float ftall=(float)tall;
float frange=(float)(_range[1]-_range[0]);
float frangewindow=(float)(_rangeWindow);
if(frangewindow<0)
{
frangewindow=0;
}
if(!_rangeWindowEnabled)
{
frangewindow=frange;
}
if ( frangewindow > 0 )
{
if(_vertical)
{
if( frangewindow <= ( ftall + _buttonOffset ) )
{
return true;
}
}
else
{
if( frangewindow <= ( fwide + _buttonOffset ) )
{
return true;
}
}
}
return false;
}
void Slider2::addIntChangeSignal(IntChangeSignal* s)
{
_intChangeSignalDar.putElement(s);
}
void Slider2::fireIntChangeSignal()
{
for(int i=0;i<_intChangeSignalDar.getCount();i++)
{
_intChangeSignalDar[i]->intChanged(getValue(),this);
}
}
void Slider2::paintBackground()
{
int wide,tall;
getPaintSize(wide,tall);
if (_vertical)
{
// background behind slider
drawSetColor(40, 40, 40, 0);
drawFilledRect(0, 0, wide, tall);
// slider front
drawSetColor(0, 0, 0, 0);
drawFilledRect(0,_nobPos[0],wide,_nobPos[1]);
// slider border
drawSetColor(60, 60, 60, 0);
drawFilledRect(0,_nobPos[0],wide,_nobPos[0]+1); // top
drawFilledRect(0,_nobPos[1],wide,_nobPos[1]+1); // bottom
drawFilledRect(0,_nobPos[0]+1,1,_nobPos[1]); // left
drawFilledRect(wide-1,_nobPos[0]+1,wide,_nobPos[1]); // right
}
else
{
//!! doesn't work
drawSetColor(Scheme::sc_secondary3);
drawFilledRect(0,0,wide,tall);
drawSetColor(Scheme::sc_black);
drawOutlinedRect(0,0,wide,tall);
drawSetColor(Scheme::sc_primary2);
drawFilledRect(_nobPos[0],0,_nobPos[1],tall);
drawSetColor(Scheme::sc_black);
drawOutlinedRect(_nobPos[0],0,_nobPos[1],tall);
}
}
void Slider2::setRange(int min,int max)
{
if(max<min)
{
max=min;
}
if(min>max)
{
min=max;
}
_range[0]=min;
_range[1]=max;
}
void Slider2::getRange(int& min,int& max)
{
min=_range[0];
max=_range[1];
}
void Slider2::privateCursorMoved(int x,int y,Panel* panel)
{
if(!_dragging)
{
return;
}
getApp()->getCursorPos(x,y);
screenToLocal(x,y);
int wide,tall;
getPaintSize(wide,tall);
if(_vertical)
{
_nobPos[0]=_nobDragStartPos[0]+(y-_dragStartPos[1]);
_nobPos[1]=_nobDragStartPos[1]+(y-_dragStartPos[1]);
if(_nobPos[1]>tall)
{
_nobPos[0]=tall-(_nobPos[1]-_nobPos[0]);
_nobPos[1]=tall;
}
if(_nobPos[0]<0)
{
_nobPos[1]=_nobPos[1]-_nobPos[0];
_nobPos[0]=0;
}
}
else
{
_nobPos[0]=_nobDragStartPos[0]+(x-_dragStartPos[0]);
_nobPos[1]=_nobDragStartPos[1]+(x-_dragStartPos[0]);
if(_nobPos[1]>wide)
{
_nobPos[0]=wide-(_nobPos[1]-_nobPos[0]);
_nobPos[1]=wide;
}
if(_nobPos[0]<0)
{
_nobPos[1]=_nobPos[1]-_nobPos[0];
_nobPos[0]=0;
}
}
recomputeValueFromNobPos();
repaint();
fireIntChangeSignal();
}
void Slider2::privateMousePressed(MouseCode code,Panel* panel)
{
int x,y;
getApp()->getCursorPos(x,y);
screenToLocal(x,y);
if(_vertical)
{
if((y>=_nobPos[0])&&(y<_nobPos[1]))
{
_dragging=true;
getApp()->setMouseCapture(this);
_nobDragStartPos[0]=_nobPos[0];
_nobDragStartPos[1]=_nobPos[1];
_dragStartPos[0]=x;
_dragStartPos[1]=y;
}
}
else
{
if((x>=_nobPos[0])&&(x<_nobPos[1]))
{
_dragging=true;
getApp()->setMouseCapture(this);
_nobDragStartPos[0]=_nobPos[0];
_nobDragStartPos[1]=_nobPos[1];
_dragStartPos[0]=x;
_dragStartPos[1]=y;
}
}
}
void Slider2::privateMouseReleased(MouseCode code,Panel* panel)
{
_dragging=false;
getApp()->setMouseCapture(null);
}
void Slider2::getNobPos(int& min, int& max)
{
min=_nobPos[0];
max=_nobPos[1];
}
void Slider2::setRangeWindow(int rangeWindow)
{
_rangeWindow=rangeWindow;
}
void Slider2::setRangeWindowEnabled(bool state)
{
_rangeWindowEnabled=state;
}
void Slider2::setButtonOffset(int buttonOffset)
{
_buttonOffset=buttonOffset;
}

View File

@ -0,0 +1,69 @@
//========= Copyright <20> 1996-2002, Valve LLC, All rights reserved. ============
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#ifndef VGUI_SLIDER2_H
#define VGUI_SLIDER2_H
#ifdef _WIN32
#ifndef __MINGW32__
#pragma once
#endif /* not __MINGW32__ */
#endif
#include<VGUI.h>
#include<VGUI_Panel.h>
#include<VGUI_Dar.h>
namespace vgui
{
enum MouseCode;
class IntChangeSignal;
class VGUIAPI Slider2 : public Panel
{
private:
bool _vertical;
bool _dragging;
int _nobPos[2];
int _nobDragStartPos[2];
int _dragStartPos[2];
Dar<IntChangeSignal*> _intChangeSignalDar;
int _range[2];
int _value;
int _rangeWindow;
bool _rangeWindowEnabled;
int _buttonOffset;
public:
Slider2(int x,int y,int wide,int tall,bool vertical);
public:
virtual void setValue(int value);
virtual int getValue();
virtual bool isVertical();
virtual void addIntChangeSignal(IntChangeSignal* s);
virtual void setRange(int min,int max);
virtual void getRange(int& min,int& max);
virtual void setRangeWindow(int rangeWindow);
virtual void setRangeWindowEnabled(bool state);
virtual void setSize(int wide,int tall);
virtual void getNobPos(int& min, int& max);
virtual bool hasFullRange();
virtual void setButtonOffset(int buttonOffset);
private:
virtual void recomputeNobPosFromValue();
virtual void recomputeValueFromNobPos();
public: //bullshit public
virtual void privateCursorMoved(int x,int y,Panel* panel);
virtual void privateMousePressed(MouseCode code,Panel* panel);
virtual void privateMouseReleased(MouseCode code,Panel* panel);
protected:
virtual void fireIntChangeSignal();
virtual void paintBackground();
};
}
#endif // VGUI_SLIDER2_H

View File

@ -0,0 +1,205 @@
//========= Copyright <20> 1996-2002, Valve LLC, All rights reserved. ============
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#include <string.h>
#include <stdio.h>
#include "voice_banmgr.h"
#if defined _MSC_VER && _MSC_VER >= 1400
#ifndef _CRT_SECURE_NO_DEPRECATE
#define _CRT_SECURE_NO_DEPRECATE
#endif
#pragma warning(disable: 4996) // deprecated functions
#endif
#define BANMGR_FILEVERSION 1
char const *g_pBanMgrFilename = "voice_ban.dt";
// Hash a player ID to a byte.
unsigned char HashPlayerID(char const playerID[16])
{
unsigned char curHash = 0;
for(int i=0; i < 16; i++)
curHash += (unsigned char)playerID[i];
return curHash;
}
CVoiceBanMgr::CVoiceBanMgr()
{
Clear();
}
CVoiceBanMgr::~CVoiceBanMgr()
{
Term();
}
bool CVoiceBanMgr::Init(char const *pGameDir)
{
Term();
char filename[512];
_snprintf(filename, sizeof(filename), "%s/%s", pGameDir, g_pBanMgrFilename);
// Load in the squelch file.
FILE *fp = fopen(filename, "rb");
if(fp)
{
int version;
fread(&version, 1, sizeof(version), fp);
if(version == BANMGR_FILEVERSION)
{
fseek(fp, 0, SEEK_END);
int nIDs = (ftell(fp) - sizeof(version)) / 16;
fseek(fp, sizeof(version), SEEK_SET);
for(int i=0; i < nIDs; i++)
{
char playerID[16];
fread(playerID, 1, 16, fp);
AddBannedPlayer(playerID);
}
}
fclose(fp);
}
return true;
}
void CVoiceBanMgr::Term()
{
// Free all the player structures.
for(int i=0; i < 256; i++)
{
BannedPlayer *pListHead = &m_PlayerHash[i];
BannedPlayer *pNext;
for(BannedPlayer *pCur=pListHead->m_pNext; pCur != pListHead; pCur=pNext)
{
pNext = pCur->m_pNext;
delete pCur;
}
}
Clear();
}
void CVoiceBanMgr::SaveState(char const *pGameDir)
{
// Save the file out.
char filename[512];
_snprintf(filename, sizeof(filename), "%s/%s", pGameDir, g_pBanMgrFilename);
FILE *fp = fopen(filename, "wb");
if(fp)
{
int version = BANMGR_FILEVERSION;
fwrite(&version, 1, sizeof(version), fp);
for(int i=0; i < 256; i++)
{
BannedPlayer *pListHead = &m_PlayerHash[i];
for(BannedPlayer *pCur=pListHead->m_pNext; pCur != pListHead; pCur=pCur->m_pNext)
{
fwrite(pCur->m_PlayerID, 1, 16, fp);
}
}
fclose(fp);
}
}
bool CVoiceBanMgr::GetPlayerBan(char const playerID[16])
{
return !!InternalFindPlayerSquelch(playerID);
}
void CVoiceBanMgr::SetPlayerBan(char const playerID[16], bool bSquelch)
{
if(bSquelch)
{
// Is this guy already squelched?
if(GetPlayerBan(playerID))
return;
AddBannedPlayer(playerID);
}
else
{
BannedPlayer *pPlayer = InternalFindPlayerSquelch(playerID);
if(pPlayer)
{
pPlayer->m_pPrev->m_pNext = pPlayer->m_pNext;
pPlayer->m_pNext->m_pPrev = pPlayer->m_pPrev;
delete pPlayer;
}
}
}
void CVoiceBanMgr::ForEachBannedPlayer(void (*callback)(char id[16]))
{
for(int i=0; i < 256; i++)
{
for(BannedPlayer *pCur=m_PlayerHash[i].m_pNext; pCur != &m_PlayerHash[i]; pCur=pCur->m_pNext)
{
callback(pCur->m_PlayerID);
}
}
}
void CVoiceBanMgr::Clear()
{
// Tie off the hash table entries.
for(int i=0; i < 256; i++)
m_PlayerHash[i].m_pNext = m_PlayerHash[i].m_pPrev = &m_PlayerHash[i];
}
CVoiceBanMgr::BannedPlayer* CVoiceBanMgr::InternalFindPlayerSquelch(char const playerID[16])
{
int index = HashPlayerID(playerID);
BannedPlayer *pListHead = &m_PlayerHash[index];
for(BannedPlayer *pCur=pListHead->m_pNext; pCur != pListHead; pCur=pCur->m_pNext)
{
if(memcmp(playerID, pCur->m_PlayerID, 16) == 0)
return pCur;
}
return NULL;
}
CVoiceBanMgr::BannedPlayer* CVoiceBanMgr::AddBannedPlayer(char const playerID[16])
{
BannedPlayer *pNew = new BannedPlayer;
if(!pNew)
return NULL;
int index = HashPlayerID(playerID);
memcpy(pNew->m_PlayerID, playerID, 16);
pNew->m_pNext = &m_PlayerHash[index];
pNew->m_pPrev = m_PlayerHash[index].m_pPrev;
pNew->m_pPrev->m_pNext = pNew->m_pNext->m_pPrev = pNew;
return pNew;
}

View File

@ -0,0 +1,59 @@
//========= Copyright <20> 1996-2002, Valve LLC, All rights reserved. ============
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#ifndef VOICE_BANMGR_H
#define VOICE_BANMGR_H
#ifdef _WIN32
#ifndef __MINGW32__
#pragma once
#endif /* not __MINGW32__ */
#endif
// This class manages the (persistent) list of squelched players.
class CVoiceBanMgr
{
public:
CVoiceBanMgr();
~CVoiceBanMgr();
// Init loads the list of squelched players from disk.
bool Init(char const *pGameDir);
void Term();
// Saves the state into voice_squelch.dt.
void SaveState(char const *pGameDir);
bool GetPlayerBan(char const playerID[16]);
void SetPlayerBan(char const playerID[16], bool bSquelch);
// Call your callback for each banned player.
void ForEachBannedPlayer(void (*callback)(char id[16]));
protected:
class BannedPlayer
{
public:
char m_PlayerID[16];
BannedPlayer *m_pPrev, *m_pNext;
};
void Clear();
BannedPlayer* InternalFindPlayerSquelch(char const playerID[16]);
BannedPlayer* AddBannedPlayer(char const playerID[16]);
protected:
BannedPlayer m_PlayerHash[256];
};
#endif // VOICE_BANMGR_H

View File

@ -0,0 +1,26 @@
//========= Copyright <20> 1996-2002, Valve LLC, All rights reserved. ============
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#ifndef VOICE_COMMON_H
#define VOICE_COMMON_H
#ifdef _WIN32
#ifndef __MINGW32__
#pragma once
#endif /* not __MINGW32__ */
#endif
#include "bitvec.h"
#define VOICE_MAX_PLAYERS 32 // (todo: this should just be set to MAX_CLIENTS).
#define VOICE_MAX_PLAYERS_DW ((VOICE_MAX_PLAYERS / 32) + !!(VOICE_MAX_PLAYERS & 31))
typedef CBitVec<VOICE_MAX_PLAYERS> CPlayerBitVec;
#endif // VOICE_COMMON_H

View File

@ -0,0 +1,274 @@
//========= Copyright <20> 1996-2002, Valve LLC, All rights reserved. ============
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#include "voice_gamemgr.h"
#include <string.h>
#include <assert.h>
#include "extdll.h"
#include "util.h"
#include "cbase.h"
#include "player.h"
#define UPDATE_INTERVAL 0.3
// These are stored off as CVoiceGameMgr is created and deleted.
CPlayerBitVec g_PlayerModEnable; // Set to 1 for each player if the player wants to use voice in this mod.
// (If it's zero, then the server reports that the game rules are saying the
// player can't hear anyone).
CPlayerBitVec g_BanMasks[VOICE_MAX_PLAYERS]; // Tells which players don't want to hear each other.
// These are indexed as clients and each bit represents a client
// (so player entity is bit+1).
CPlayerBitVec g_SentGameRulesMasks[VOICE_MAX_PLAYERS]; // These store the masks we last sent to each client so we can determine if
CPlayerBitVec g_SentBanMasks[VOICE_MAX_PLAYERS]; // we need to resend them.
CPlayerBitVec g_bWantModEnable;
cvar_t voice_serverdebug = {"voice_serverdebug", "0"};
// Set game rules to allow all clients to talk to each other.
// Muted players still can't talk to each other.
cvar_t sv_alltalk = {"sv_alltalk", "0"};
// ------------------------------------------------------------------------ //
// Static helpers.
// ------------------------------------------------------------------------ //
// Find a player with a case-insensitive name search.
/*static CBasePlayer* FindPlayerByName(const char *pTestName)
{
for(int i=1; i <= gpGlobals->maxClients; i++)
{
edict_t *pEdict = g_engfuncs.pfnPEntityOfEntIndex(i);
if(pEdict)
{
CBaseEntity *pEnt = CBaseEntity::Instance(pEdict);
if(pEnt && pEnt->IsPlayer())
{
const char *pNetName = STRING(pEnt->pev->netname);
if(stricmp(pNetName, pTestName) == 0)
{
return (CBasePlayer*)pEnt;
}
}
}
}
return NULL;
}*/
static void VoiceServerDebug( char const *pFmt, ... )
{
char msg[4096];
va_list marker;
if( !voice_serverdebug.value )
return;
va_start( marker, pFmt );
_vsnprintf( msg, sizeof(msg), pFmt, marker );
va_end( marker );
ALERT( at_console, "%s", msg );
}
// ------------------------------------------------------------------------ //
// CVoiceGameMgr.
// ------------------------------------------------------------------------ //
CVoiceGameMgr::CVoiceGameMgr()
{
m_UpdateInterval = 0;
m_nMaxPlayers = 0;
}
CVoiceGameMgr::~CVoiceGameMgr()
{
}
bool CVoiceGameMgr::Init(
IVoiceGameMgrHelper *pHelper,
int maxClients)
{
m_pHelper = pHelper;
m_nMaxPlayers = VOICE_MAX_PLAYERS < maxClients ? VOICE_MAX_PLAYERS : maxClients;
g_engfuncs.pfnPrecacheModel("sprites/voiceicon.spr");
m_msgPlayerVoiceMask = REG_USER_MSG( "VoiceMask", VOICE_MAX_PLAYERS_DW*4 * 2 );
m_msgRequestState = REG_USER_MSG( "ReqState", 0 );
// register voice_serverdebug if it hasn't been registered already
if ( !CVAR_GET_POINTER( "voice_serverdebug" ) )
CVAR_REGISTER( &voice_serverdebug );
if( !CVAR_GET_POINTER( "sv_alltalk" ) )
CVAR_REGISTER( &sv_alltalk );
return true;
}
void CVoiceGameMgr::SetHelper(IVoiceGameMgrHelper *pHelper)
{
m_pHelper = pHelper;
}
void CVoiceGameMgr::Update(double frametime)
{
// Only update periodically.
m_UpdateInterval += frametime;
if(m_UpdateInterval < UPDATE_INTERVAL)
return;
UpdateMasks();
}
void CVoiceGameMgr::ClientConnected(edict_t *pEdict)
{
int index = ENTINDEX(pEdict) - 1;
// Clear out everything we use for deltas on this guy.
g_bWantModEnable[index] = true;
g_SentGameRulesMasks[index].Init(0);
g_SentBanMasks[index].Init(0);
}
// Called to determine if the Receiver has muted (blocked) the Sender
// Returns true if the receiver has blocked the sender
bool CVoiceGameMgr::PlayerHasBlockedPlayer(CBasePlayer *pReceiver, CBasePlayer *pSender)
{
int iReceiverIndex, iSenderIndex;
if ( !pReceiver || !pSender )
return false;
iReceiverIndex = pReceiver->entindex() - 1;
iSenderIndex = pSender->entindex() - 1;
if ( iReceiverIndex < 0 || iReceiverIndex >= m_nMaxPlayers || iSenderIndex < 0 || iSenderIndex >= m_nMaxPlayers )
return false;
return ( g_BanMasks[iReceiverIndex][iSenderIndex] ? true : false );
}
bool CVoiceGameMgr::ClientCommand(CBasePlayer *pPlayer, const char *cmd)
{
int playerClientIndex = pPlayer->entindex() - 1;
if(playerClientIndex < 0 || playerClientIndex >= m_nMaxPlayers)
{
VoiceServerDebug( "CVoiceGameMgr::ClientCommand: cmd %s from invalid client (%d)\n", cmd, playerClientIndex );
return true;
}
bool bBan = stricmp(cmd, "vban") == 0;
if(bBan && CMD_ARGC() >= 2)
{
for(int i=1; i < CMD_ARGC(); i++)
{
unsigned long mask = 0;
sscanf(CMD_ARGV(i), "%lx", &mask);
if(i <= VOICE_MAX_PLAYERS_DW)
{
VoiceServerDebug( "CVoiceGameMgr::ClientCommand: vban (0x%x) from %d\n", mask, playerClientIndex );
g_BanMasks[playerClientIndex].SetDWord(i-1, mask);
}
else
{
VoiceServerDebug( "CVoiceGameMgr::ClientCommand: invalid index (%d)\n", i );
}
}
// Force it to update the masks now.
//UpdateMasks();
return true;
}
else if(stricmp(cmd, "VModEnable") == 0 && CMD_ARGC() >= 2)
{
VoiceServerDebug( "CVoiceGameMgr::ClientCommand: VModEnable (%d)\n", !!atoi(CMD_ARGV(1)) );
g_PlayerModEnable[playerClientIndex] = !!atoi(CMD_ARGV(1));
g_bWantModEnable[playerClientIndex] = false;
//UpdateMasks();
return true;
}
else
{
return false;
}
}
void CVoiceGameMgr::UpdateMasks()
{
m_UpdateInterval = 0;
bool bAllTalk = !!g_engfuncs.pfnCVarGetFloat( "sv_alltalk" );
for(int iClient=0; iClient < m_nMaxPlayers; iClient++)
{
CBaseEntity *pEnt = UTIL_PlayerByIndex(iClient+1);
if(!pEnt || !pEnt->IsPlayer())
continue;
// Request the state of their "VModEnable" cvar.
if(g_bWantModEnable[iClient])
{
MESSAGE_BEGIN(MSG_ONE, m_msgRequestState, NULL, pEnt->pev);
MESSAGE_END();
}
CBasePlayer *pPlayer = (CBasePlayer*)pEnt;
CPlayerBitVec gameRulesMask;
if( g_PlayerModEnable[iClient] )
{
// Build a mask of who they can hear based on the game rules.
for(int iOtherClient=0; iOtherClient < m_nMaxPlayers; iOtherClient++)
{
CBaseEntity *pEnt = UTIL_PlayerByIndex(iOtherClient+1);
if(pEnt && pEnt->IsPlayer() &&
(bAllTalk || m_pHelper->CanPlayerHearPlayer(pPlayer, (CBasePlayer*)pEnt)) )
{
gameRulesMask[iOtherClient] = true;
}
}
}
// If this is different from what the client has, send an update.
if(gameRulesMask != g_SentGameRulesMasks[iClient] ||
g_BanMasks[iClient] != g_SentBanMasks[iClient])
{
g_SentGameRulesMasks[iClient] = gameRulesMask;
g_SentBanMasks[iClient] = g_BanMasks[iClient];
MESSAGE_BEGIN(MSG_ONE, m_msgPlayerVoiceMask, NULL, pPlayer->pev);
int dw;
for(dw=0; dw < VOICE_MAX_PLAYERS_DW; dw++)
{
WRITE_LONG(gameRulesMask.GetDWord(dw));
WRITE_LONG(g_BanMasks[iClient].GetDWord(dw));
}
MESSAGE_END();
}
// Tell the engine.
for(int iOtherClient=0; iOtherClient < m_nMaxPlayers; iOtherClient++)
{
bool bCanHear = gameRulesMask[iOtherClient] && !g_BanMasks[iClient][iOtherClient];
g_engfuncs.pfnVoice_SetClientListening(iClient+1, iOtherClient+1, bCanHear);
}
}
}

View File

@ -0,0 +1,83 @@
//========= Copyright <20> 1996-2002, Valve LLC, All rights reserved. ============
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#ifndef VOICE_GAMEMGR_H
#define VOICE_GAMEMGR_H
#ifdef _WIN32
#ifndef __MINGW32__
#pragma once
#endif /* not __MINGW32__ */
#endif
#include "voice_common.h"
class CGameRules;
class CBasePlayer;
class IVoiceGameMgrHelper
{
public:
virtual ~IVoiceGameMgrHelper() {}
// Called each frame to determine which players are allowed to hear each other. This overrides
// whatever squelch settings players have.
virtual bool CanPlayerHearPlayer(CBasePlayer *pListener, CBasePlayer *pTalker) = 0;
};
// CVoiceGameMgr manages which clients can hear which other clients.
class CVoiceGameMgr
{
public:
CVoiceGameMgr();
virtual ~CVoiceGameMgr();
bool Init(
IVoiceGameMgrHelper *m_pHelper,
int maxClients
);
void SetHelper(IVoiceGameMgrHelper *pHelper);
// Updates which players can hear which other players.
// If gameplay mode is DM, then only players within the PVS can hear each other.
// If gameplay mode is teamplay, then only players on the same team can hear each other.
// Player masks are always applied.
void Update(double frametime);
// Called when a new client connects (unsquelches its entity for everyone).
void ClientConnected(struct edict_s *pEdict);
// Called on ClientCommand. Checks for the squelch and unsquelch commands.
// Returns true if it handled the command.
bool ClientCommand(CBasePlayer *pPlayer, const char *cmd);
// Called to determine if the Receiver has muted (blocked) the Sender
// Returns true if the receiver has blocked the sender
bool PlayerHasBlockedPlayer(CBasePlayer *pReceiver, CBasePlayer *pSender);
private:
// Force it to update the client masks.
void UpdateMasks();
private:
int m_msgPlayerVoiceMask;
int m_msgRequestState;
IVoiceGameMgrHelper *m_pHelper;
int m_nMaxPlayers;
double m_UpdateInterval; // How long since the last update.
};
#endif // VOICE_GAMEMGR_H

View File

@ -0,0 +1,874 @@
//========= Copyright <20> 1996-2002, Valve LLC, All rights reserved. ============
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
// There are hud.h's coming out of the woodwork so this ensures that we get the right one.
#if defined( DMC_BUILD )
#include "../dmc/cl_dll/hud.h"
#include "../dmc/cl_dll/cl_util.h"
#elif defined( RICOCHET_BUILD )
#include "../ricochet/cl_dll/hud.h"
#include "../ricochet/cl_dll/cl_util.h"
#else
#include "../cl_dll/hud.h"
#include "../cl_dll/cl_util.h"
#endif
#include <assert.h>
#include <string.h>
#include <stdio.h>
#if defined( DMC_BUILD )
#include "../dmc/cl_dll/parsemsg.h"
#include "../dmc/cl_dll/hud_servers.h"
#include "../dmc/cl_dll/demo.h"
#elif defined( RICOCHET_BUILD )
#include "../ricochet/cl_dll/parsemsg.h"
#include "../ricochet/cl_dll/hud_servers.h"
#include "../ricochet/cl_dll/demo.h"
#else
#include "../cl_dll/parsemsg.h"
#include "../cl_dll/hud_servers.h"
#include "../cl_dll/demo.h"
#endif
#include "demo_api.h"
#include "voice_status.h"
#include "r_efx.h"
#include "entity_types.h"
#include "VGUI_ActionSignal.h"
#include "VGUI_Scheme.h"
#include "VGUI_TextImage.h"
#include "vgui_loadtga.h"
#include "vgui_helpers.h"
#include "vgui_mousecode.h"
using namespace vgui;
extern int cam_thirdperson;
#define VOICE_MODEL_INTERVAL 0.3
#define SCOREBOARD_BLINK_FREQUENCY 0.3 // How often to blink the scoreboard icons.
#define SQUELCHOSCILLATE_PER_SECOND 2.0f
extern BitmapTGA *LoadTGA( const char* pImageName );
// ---------------------------------------------------------------------- //
// The voice manager for the client.
// ---------------------------------------------------------------------- //
CVoiceStatus g_VoiceStatus;
CVoiceStatus* GetClientVoiceMgr()
{
return &g_VoiceStatus;
}
// ---------------------------------------------------------------------- //
// CVoiceStatus.
// ---------------------------------------------------------------------- //
static CVoiceStatus *g_pInternalVoiceStatus = NULL;
int __MsgFunc_VoiceMask(const char *pszName, int iSize, void *pbuf)
{
if(g_pInternalVoiceStatus)
g_pInternalVoiceStatus->HandleVoiceMaskMsg(iSize, pbuf);
return 1;
}
int __MsgFunc_ReqState(const char *pszName, int iSize, void *pbuf)
{
if(g_pInternalVoiceStatus)
g_pInternalVoiceStatus->HandleReqStateMsg(iSize, pbuf);
return 1;
}
int g_BannedPlayerPrintCount;
void ForEachBannedPlayer(char id[16])
{
char str[256];
sprintf(str, "Ban %d: %2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x\n",
g_BannedPlayerPrintCount++,
id[0], id[1], id[2], id[3],
id[4], id[5], id[6], id[7],
id[8], id[9], id[10], id[11],
id[12], id[13], id[14], id[15]
);
strupr(str);
gEngfuncs.pfnConsolePrint(str);
}
void ShowBannedCallback()
{
if(g_pInternalVoiceStatus)
{
g_BannedPlayerPrintCount = 0;
gEngfuncs.pfnConsolePrint("------- BANNED PLAYERS -------\n");
g_pInternalVoiceStatus->m_BanMgr.ForEachBannedPlayer(ForEachBannedPlayer);
gEngfuncs.pfnConsolePrint("------------------------------\n");
}
}
// ---------------------------------------------------------------------- //
// CVoiceStatus.
// ---------------------------------------------------------------------- //
CVoiceStatus::CVoiceStatus()
{
m_bBanMgrInitialized = false;
m_LastUpdateServerState = 0;
m_pSpeakerLabelIcon = NULL;
m_pScoreboardNeverSpoken = NULL;
m_pScoreboardNotSpeaking = NULL;
m_pScoreboardSpeaking = NULL;
m_pScoreboardSpeaking2 = NULL;
m_pScoreboardSquelch = NULL;
m_pScoreboardBanned = NULL;
m_pLocalBitmap = NULL;
m_pAckBitmap = NULL;
m_bTalking = m_bServerAcked = false;
memset(m_pBanButtons, 0, sizeof(m_pBanButtons));
m_bServerModEnable = -1;
m_pchGameDir = NULL;
}
CVoiceStatus::~CVoiceStatus()
{
g_pInternalVoiceStatus = NULL;
for(int i=0; i < MAX_VOICE_SPEAKERS; i++)
{
delete m_Labels[i].m_pLabel;
m_Labels[i].m_pLabel = NULL;
delete m_Labels[i].m_pIcon;
m_Labels[i].m_pIcon = NULL;
delete m_Labels[i].m_pBackground;
m_Labels[i].m_pBackground = NULL;
}
delete m_pLocalLabel;
m_pLocalLabel = NULL;
FreeBitmaps();
if(m_pchGameDir)
{
if(m_bBanMgrInitialized)
{
m_BanMgr.SaveState(m_pchGameDir);
}
free(m_pchGameDir);
}
}
int CVoiceStatus::Init(
IVoiceStatusHelper *pHelper,
Panel **pParentPanel)
{
// Setup the voice_modenable cvar.
gEngfuncs.pfnRegisterVariable("voice_modenable", "1", FCVAR_ARCHIVE);
gEngfuncs.pfnRegisterVariable("voice_clientdebug", "0", 0);
gEngfuncs.pfnAddCommand("voice_showbanned", ShowBannedCallback);
if(gEngfuncs.pfnGetGameDirectory())
{
m_BanMgr.Init(gEngfuncs.pfnGetGameDirectory());
m_bBanMgrInitialized = true;
}
assert(!g_pInternalVoiceStatus);
g_pInternalVoiceStatus = this;
m_BlinkTimer = 0;
m_VoiceHeadModel = NULL;
memset(m_Labels, 0, sizeof(m_Labels));
for(int i=0; i < MAX_VOICE_SPEAKERS; i++)
{
CVoiceLabel *pLabel = &m_Labels[i];
pLabel->m_pBackground = new Label("");
if(pLabel->m_pLabel = new Label(""))
{
pLabel->m_pLabel->setVisible( true );
pLabel->m_pLabel->setFont( Scheme::sf_primary2 );
pLabel->m_pLabel->setTextAlignment( Label::a_east );
pLabel->m_pLabel->setContentAlignment( Label::a_east );
pLabel->m_pLabel->setParent( pLabel->m_pBackground );
}
if( pLabel->m_pIcon = new ImagePanel( NULL ) )
{
pLabel->m_pIcon->setVisible( true );
pLabel->m_pIcon->setParent( pLabel->m_pBackground );
}
pLabel->m_clientindex = -1;
}
m_pLocalLabel = new ImagePanel(NULL);
m_bInSquelchMode = false;
m_pHelper = pHelper;
m_pParentPanel = pParentPanel;
gHUD.AddHudElem(this);
m_iFlags = HUD_ACTIVE;
HOOK_MESSAGE(VoiceMask);
HOOK_MESSAGE(ReqState);
// Cache the game directory for use when we shut down
const char *pchGameDirT = gEngfuncs.pfnGetGameDirectory();
m_pchGameDir = (char *)malloc(strlen(pchGameDirT) + 1);
strcpy(m_pchGameDir, pchGameDirT);
return 1;
}
int CVoiceStatus::VidInit()
{
FreeBitmaps();
if( m_pLocalBitmap = vgui_LoadTGA("gfx/vgui/icntlk_pl.tga") )
{
m_pLocalBitmap->setColor(Color(255,255,255,135));
}
if( m_pAckBitmap = vgui_LoadTGA("gfx/vgui/icntlk_sv.tga") )
{
m_pAckBitmap->setColor(Color(255,255,255,135)); // Give just a tiny bit of translucency so software draws correctly.
}
m_pLocalLabel->setImage( m_pLocalBitmap );
m_pLocalLabel->setVisible( false );
if( m_pSpeakerLabelIcon = vgui_LoadTGANoInvertAlpha("gfx/vgui/speaker4.tga" ) )
m_pSpeakerLabelIcon->setColor( Color(255,255,255,1) ); // Give just a tiny bit of translucency so software draws correctly.
if (m_pScoreboardNeverSpoken = vgui_LoadTGANoInvertAlpha("gfx/vgui/640_speaker1.tga"))
m_pScoreboardNeverSpoken->setColor(Color(255,255,255,1)); // Give just a tiny bit of translucency so software draws correctly.
if(m_pScoreboardNotSpeaking = vgui_LoadTGANoInvertAlpha("gfx/vgui/640_speaker2.tga"))
m_pScoreboardNotSpeaking->setColor(Color(255,255,255,1)); // Give just a tiny bit of translucency so software draws correctly.
if(m_pScoreboardSpeaking = vgui_LoadTGANoInvertAlpha("gfx/vgui/640_speaker3.tga"))
m_pScoreboardSpeaking->setColor(Color(255,255,255,1)); // Give just a tiny bit of translucency so software draws correctly.
if(m_pScoreboardSpeaking2 = vgui_LoadTGANoInvertAlpha("gfx/vgui/640_speaker4.tga"))
m_pScoreboardSpeaking2->setColor(Color(255,255,255,1)); // Give just a tiny bit of translucency so software draws correctly.
if(m_pScoreboardSquelch = vgui_LoadTGA("gfx/vgui/icntlk_squelch.tga"))
m_pScoreboardSquelch->setColor(Color(255,255,255,1)); // Give just a tiny bit of translucency so software draws correctly.
if(m_pScoreboardBanned = vgui_LoadTGA("gfx/vgui/640_voiceblocked.tga"))
m_pScoreboardBanned->setColor(Color(255,255,255,1)); // Give just a tiny bit of translucency so software draws correctly.
// Figure out the voice head model height.
m_VoiceHeadModelHeight = 45;
char *pFile = (char *)gEngfuncs.COM_LoadFile("scripts/voicemodel.txt", 5, NULL);
if(pFile)
{
char token[4096];
gEngfuncs.COM_ParseFile(pFile, token);
if(token[0] >= '0' && token[0] <= '9')
{
m_VoiceHeadModelHeight = (float)atof(token);
}
gEngfuncs.COM_FreeFile(pFile);
}
m_VoiceHeadModel = gEngfuncs.pfnSPR_Load("sprites/voiceicon.spr");
return TRUE;
}
void CVoiceStatus::Frame(double frametime)
{
// check server banned players once per second
if(gEngfuncs.GetClientTime() - m_LastUpdateServerState > 1)
{
UpdateServerState(false);
}
m_BlinkTimer += frametime;
// Update speaker labels.
if( m_pHelper->CanShowSpeakerLabels() )
{
for( int i=0; i < MAX_VOICE_SPEAKERS; i++ )
m_Labels[i].m_pBackground->setVisible( m_Labels[i].m_clientindex != -1 );
}
else
{
for( int i=0; i < MAX_VOICE_SPEAKERS; i++ )
m_Labels[i].m_pBackground->setVisible( false );
}
for(int i=0; i < VOICE_MAX_PLAYERS; i++)
UpdateBanButton(i);
}
void CVoiceStatus::CreateEntities()
{
if(!m_VoiceHeadModel)
return;
cl_entity_t *localPlayer = gEngfuncs.GetLocalPlayer();
int iOutModel = 0;
for(int i=0; i < VOICE_MAX_PLAYERS; i++)
{
if(!m_VoicePlayers[i])
continue;
cl_entity_s *pClient = gEngfuncs.GetEntityByIndex(i+1);
// Don't show an icon if the player is not in our PVS.
if(!pClient || pClient->curstate.messagenum < localPlayer->curstate.messagenum)
continue;
// Don't show an icon for dead or spectating players (ie: invisible entities).
if(pClient->curstate.effects & EF_NODRAW)
continue;
// Don't show an icon for the local player unless we're in thirdperson mode.
if(pClient == localPlayer && !cam_thirdperson)
continue;
cl_entity_s *pEnt = &m_VoiceHeadModels[iOutModel];
++iOutModel;
memset(pEnt, 0, sizeof(*pEnt));
pEnt->curstate.rendermode = kRenderTransAdd;
pEnt->curstate.renderamt = 255;
pEnt->baseline.renderamt = 255;
pEnt->curstate.renderfx = kRenderFxNoDissipation;
pEnt->curstate.framerate = 1;
pEnt->curstate.frame = 0;
pEnt->model = (struct model_s*)gEngfuncs.GetSpritePointer(m_VoiceHeadModel);
pEnt->angles[0] = pEnt->angles[1] = pEnt->angles[2] = 0;
pEnt->curstate.scale = 0.5f;
pEnt->origin[0] = pEnt->origin[1] = 0;
pEnt->origin[2] = 45;
VectorAdd(pEnt->origin, pClient->origin, pEnt->origin);
// Tell the engine.
gEngfuncs.CL_CreateVisibleEntity(ET_NORMAL, pEnt);
}
}
void CVoiceStatus::UpdateSpeakerStatus(int entindex, qboolean bTalking)
{
if(!*m_pParentPanel)
return;
if( gEngfuncs.pfnGetCvarFloat("voice_clientdebug") )
{
char msg[256];
_snprintf( msg, sizeof(msg), "CVoiceStatus::UpdateSpeakerStatus: ent %d talking = %d\n", entindex, bTalking );
gEngfuncs.pfnConsolePrint( msg );
}
// Is it the local player talking?
if( entindex == -1 )
{
m_bTalking = !!bTalking;
if( bTalking )
{
// Enable voice for them automatically if they try to talk.
gEngfuncs.pfnClientCmd( "voice_modenable 1" );
}
}
else if( entindex == -2 )
{
m_bServerAcked = !!bTalking;
}
else if(entindex >= 0 && entindex <= VOICE_MAX_PLAYERS)
{
int iClient = entindex - 1;
if(iClient < 0)
return;
CVoiceLabel *pLabel = FindVoiceLabel(iClient);
if(bTalking)
{
m_VoicePlayers[iClient] = true;
m_VoiceEnabledPlayers[iClient] = true;
// If we don't have a label for this guy yet, then create one.
if(!pLabel)
{
if(pLabel = GetFreeVoiceLabel())
{
// Get the name from the engine.
hud_player_info_t info;
memset(&info, 0, sizeof(info));
GetPlayerInfo(entindex, &info);
char paddedName[512];
_snprintf(paddedName, sizeof(paddedName), "%s ", info.name);
int color[3];
m_pHelper->GetPlayerTextColor( entindex, color );
if( pLabel->m_pBackground )
{
pLabel->m_pBackground->setBgColor( color[0], color[1], color[2], 135 );
pLabel->m_pBackground->setParent( *m_pParentPanel );
pLabel->m_pBackground->setVisible( m_pHelper->CanShowSpeakerLabels() );
}
if( pLabel->m_pLabel )
{
pLabel->m_pLabel->setFgColor( 255, 255, 255, 0 );
pLabel->m_pLabel->setBgColor( 0, 0, 0, 255 );
pLabel->m_pLabel->setText( paddedName );
}
pLabel->m_clientindex = iClient;
}
}
}
else
{
m_VoicePlayers[iClient] = false;
// If we have a label for this guy, kill it.
if(pLabel)
{
pLabel->m_pBackground->setVisible(false);
pLabel->m_clientindex = -1;
}
}
}
RepositionLabels();
}
void CVoiceStatus::UpdateServerState(bool bForce)
{
// Can't do anything when we're not in a level.
char const *pLevelName = gEngfuncs.pfnGetLevelName();
if( pLevelName[0] == 0 )
{
if( gEngfuncs.pfnGetCvarFloat("voice_clientdebug") )
{
gEngfuncs.pfnConsolePrint( "CVoiceStatus::UpdateServerState: pLevelName[0]==0\n" );
}
return;
}
int bCVarModEnable = !!gEngfuncs.pfnGetCvarFloat("voice_modenable");
if(bForce || m_bServerModEnable != bCVarModEnable)
{
m_bServerModEnable = bCVarModEnable;
char str[256];
_snprintf(str, sizeof(str), "VModEnable %d", m_bServerModEnable);
ServerCmd(str);
if(gEngfuncs.pfnGetCvarFloat("voice_clientdebug"))
{
char msg[256];
sprintf(msg, "CVoiceStatus::UpdateServerState: Sending '%s'\n", str);
gEngfuncs.pfnConsolePrint(msg);
}
}
char str[2048];
sprintf(str, "vban");
bool bChange = false;
for(unsigned long dw=0; dw < VOICE_MAX_PLAYERS_DW; dw++)
{
unsigned long serverBanMask = 0;
unsigned long banMask = 0;
for(unsigned long i=0; i < 32; i++)
{
char playerID[16];
if(!gEngfuncs.GetPlayerUniqueID(i+1, playerID))
continue;
if(m_BanMgr.GetPlayerBan(playerID))
banMask |= 1 << i;
if(m_ServerBannedPlayers[dw*32 + i])
serverBanMask |= 1 << i;
}
if(serverBanMask != banMask)
bChange = true;
// Ok, the server needs to be updated.
char numStr[512];
sprintf(numStr, " %x", banMask);
strcat(str, numStr);
}
if(bChange || bForce)
{
if(gEngfuncs.pfnGetCvarFloat("voice_clientdebug"))
{
char msg[256];
sprintf(msg, "CVoiceStatus::UpdateServerState: Sending '%s'\n", str);
gEngfuncs.pfnConsolePrint(msg);
}
gEngfuncs.pfnServerCmdUnreliable(str); // Tell the server..
}
else
{
if (gEngfuncs.pfnGetCvarFloat("voice_clientdebug"))
{
gEngfuncs.pfnConsolePrint( "CVoiceStatus::UpdateServerState: no change\n" );
}
}
m_LastUpdateServerState = gEngfuncs.GetClientTime();
}
void CVoiceStatus::UpdateSpeakerImage(Label *pLabel, int iPlayer)
{
m_pBanButtons[iPlayer-1] = pLabel;
UpdateBanButton(iPlayer-1);
}
void CVoiceStatus::UpdateBanButton(int iClient)
{
Label *pPanel = m_pBanButtons[iClient];
if (!pPanel)
return;
char playerID[16];
extern bool HACK_GetPlayerUniqueID( int iPlayer, char playerID[16] );
if(!HACK_GetPlayerUniqueID(iClient+1, playerID))
return;
// Figure out if it's blinking or not.
bool bBlink = fmod(m_BlinkTimer, SCOREBOARD_BLINK_FREQUENCY*2) < SCOREBOARD_BLINK_FREQUENCY;
bool bTalking = !!m_VoicePlayers[iClient];
bool bBanned = m_BanMgr.GetPlayerBan(playerID);
bool bNeverSpoken = !m_VoiceEnabledPlayers[iClient];
// Get the appropriate image to display on the panel.
if (bBanned)
{
pPanel->setImage(m_pScoreboardBanned);
}
else if (bTalking)
{
if (bBlink)
{
pPanel->setImage(m_pScoreboardSpeaking2);
}
else
{
pPanel->setImage(m_pScoreboardSpeaking);
}
pPanel->setFgColor(255, 170, 0, 1);
}
else if (bNeverSpoken)
{
pPanel->setImage(m_pScoreboardNeverSpoken);
pPanel->setFgColor(100, 100, 100, 1);
}
else
{
pPanel->setImage(m_pScoreboardNotSpeaking);
}
}
void CVoiceStatus::HandleVoiceMaskMsg(int iSize, void *pbuf)
{
BEGIN_READ( pbuf, iSize );
unsigned long dw;
for(dw=0; dw < VOICE_MAX_PLAYERS_DW; dw++)
{
m_AudiblePlayers.SetDWord(dw, (unsigned long)READ_LONG());
m_ServerBannedPlayers.SetDWord(dw, (unsigned long)READ_LONG());
if(gEngfuncs.pfnGetCvarFloat("voice_clientdebug"))
{
char str[256];
gEngfuncs.pfnConsolePrint("CVoiceStatus::HandleVoiceMaskMsg\n");
sprintf(str, " - m_AudiblePlayers[%d] = %lu\n", dw, m_AudiblePlayers.GetDWord(dw));
gEngfuncs.pfnConsolePrint(str);
sprintf(str, " - m_ServerBannedPlayers[%d] = %lu\n", dw, m_ServerBannedPlayers.GetDWord(dw));
gEngfuncs.pfnConsolePrint(str);
}
}
m_bServerModEnable = READ_BYTE();
}
void CVoiceStatus::HandleReqStateMsg(int iSize, void *pbuf)
{
if(gEngfuncs.pfnGetCvarFloat("voice_clientdebug"))
{
gEngfuncs.pfnConsolePrint("CVoiceStatus::HandleReqStateMsg\n");
}
UpdateServerState(true);
}
void CVoiceStatus::StartSquelchMode()
{
if(m_bInSquelchMode)
return;
m_bInSquelchMode = true;
m_pHelper->UpdateCursorState();
}
void CVoiceStatus::StopSquelchMode()
{
m_bInSquelchMode = false;
m_pHelper->UpdateCursorState();
}
bool CVoiceStatus::IsInSquelchMode()
{
return m_bInSquelchMode;
}
CVoiceLabel* CVoiceStatus::FindVoiceLabel(int clientindex)
{
for(int i=0; i < MAX_VOICE_SPEAKERS; i++)
{
if(m_Labels[i].m_clientindex == clientindex)
return &m_Labels[i];
}
return NULL;
}
CVoiceLabel* CVoiceStatus::GetFreeVoiceLabel()
{
return FindVoiceLabel(-1);
}
void CVoiceStatus::RepositionLabels()
{
// find starting position to draw from, along right-hand side of screen
int y = ScreenHeight / 2;
int iconWide = 8, iconTall = 8;
if( m_pSpeakerLabelIcon )
{
m_pSpeakerLabelIcon->getSize( iconWide, iconTall );
}
// Reposition active labels.
for(int i = 0; i < MAX_VOICE_SPEAKERS; i++)
{
CVoiceLabel *pLabel = &m_Labels[i];
if( pLabel->m_clientindex == -1 || !pLabel->m_pLabel )
{
if( pLabel->m_pBackground )
pLabel->m_pBackground->setVisible( false );
continue;
}
int textWide, textTall;
pLabel->m_pLabel->getContentSize( textWide, textTall );
// Don't let it stretch too far across their screen.
if( textWide > (ScreenWidth*2)/3 )
textWide = (ScreenWidth*2)/3;
// Setup the background label to fit everything in.
int border = 2;
int bgWide = textWide + iconWide + border*3;
int bgTall = max( textTall, iconTall ) + border*2;
pLabel->m_pBackground->setBounds( ScreenWidth - bgWide - 8, y, bgWide, bgTall );
// Put the text at the left.
pLabel->m_pLabel->setBounds( border, (bgTall - textTall) / 2, textWide, textTall );
// Put the icon at the right.
int iconLeft = border + textWide + border;
int iconTop = (bgTall - iconTall) / 2;
if( pLabel->m_pIcon )
{
pLabel->m_pIcon->setImage( m_pSpeakerLabelIcon );
pLabel->m_pIcon->setBounds( iconLeft, iconTop, iconWide, iconTall );
}
y += bgTall + 2;
}
if( m_pLocalBitmap && m_pAckBitmap && m_pLocalLabel && (m_bTalking || m_bServerAcked) )
{
m_pLocalLabel->setParent(*m_pParentPanel);
m_pLocalLabel->setVisible( true );
if( m_bServerAcked && !!gEngfuncs.pfnGetCvarFloat("voice_clientdebug") )
m_pLocalLabel->setImage( m_pAckBitmap );
else
m_pLocalLabel->setImage( m_pLocalBitmap );
int sizeX, sizeY;
m_pLocalBitmap->getSize(sizeX, sizeY);
int local_xPos = ScreenWidth - sizeX - 10;
int local_yPos = m_pHelper->GetAckIconHeight() - sizeY;
m_pLocalLabel->setPos( local_xPos, local_yPos );
}
else
{
m_pLocalLabel->setVisible( false );
}
}
void CVoiceStatus::FreeBitmaps()
{
// Delete all the images we have loaded.
delete m_pLocalBitmap;
m_pLocalBitmap = NULL;
delete m_pAckBitmap;
m_pAckBitmap = NULL;
delete m_pSpeakerLabelIcon;
m_pSpeakerLabelIcon = NULL;
delete m_pScoreboardNeverSpoken;
m_pScoreboardNeverSpoken = NULL;
delete m_pScoreboardNotSpeaking;
m_pScoreboardNotSpeaking = NULL;
delete m_pScoreboardSpeaking;
m_pScoreboardSpeaking = NULL;
delete m_pScoreboardSpeaking2;
m_pScoreboardSpeaking2 = NULL;
delete m_pScoreboardSquelch;
m_pScoreboardSquelch = NULL;
delete m_pScoreboardBanned;
m_pScoreboardBanned = NULL;
// Clear references to the images in panels.
for(int i=0; i < VOICE_MAX_PLAYERS; i++)
{
if (m_pBanButtons[i])
{
m_pBanButtons[i]->setImage(NULL);
}
}
if(m_pLocalLabel)
m_pLocalLabel->setImage(NULL);
}
//-----------------------------------------------------------------------------
// Purpose: returns true if the target client has been banned
// Input : playerID -
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool CVoiceStatus::IsPlayerBlocked(int iPlayer)
{
char playerID[16];
if (!gEngfuncs.GetPlayerUniqueID(iPlayer, playerID))
return false;
return m_BanMgr.GetPlayerBan(playerID);
}
//-----------------------------------------------------------------------------
// Purpose: returns true if the player can't hear the other client due to game rules (eg. the other team)
// Input : playerID -
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool CVoiceStatus::IsPlayerAudible(int iPlayer)
{
return !!m_AudiblePlayers[iPlayer-1];
}
//-----------------------------------------------------------------------------
// Purpose: blocks/unblocks the target client from being heard
// Input : playerID -
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
void CVoiceStatus::SetPlayerBlockedState(int iPlayer, bool blocked)
{
if (gEngfuncs.pfnGetCvarFloat("voice_clientdebug"))
{
gEngfuncs.pfnConsolePrint( "CVoiceStatus::SetPlayerBlockedState part 1\n" );
}
char playerID[16];
if (!gEngfuncs.GetPlayerUniqueID(iPlayer, playerID))
return;
if (gEngfuncs.pfnGetCvarFloat("voice_clientdebug"))
{
gEngfuncs.pfnConsolePrint( "CVoiceStatus::SetPlayerBlockedState part 2\n" );
}
// Squelch or (try to) unsquelch this player.
if (gEngfuncs.pfnGetCvarFloat("voice_clientdebug"))
{
char str[256];
sprintf(str, "CVoiceStatus::SetPlayerBlockedState: setting player %d ban to %d\n", iPlayer, !m_BanMgr.GetPlayerBan(playerID));
gEngfuncs.pfnConsolePrint(str);
}
m_BanMgr.SetPlayerBan( playerID, blocked );
UpdateServerState(false);
}

View File

@ -0,0 +1,232 @@
//========= Copyright <20> 1996-2002, Valve LLC, All rights reserved. ============
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#ifndef VOICE_STATUS_H
#define VOICE_STATUS_H
#ifdef _WIN32
#ifndef __MINGW32__
#pragma once
#endif /* not __MINGW32__ */
#endif
#include "VGUI_Label.h"
#include "VGUI_LineBorder.h"
#include "VGUI_ImagePanel.h"
#include "VGUI_BitmapTGA.h"
#include "VGUI_InputSignal.h"
#include "VGUI_Button.h"
#include "voice_common.h"
#include "cl_entity.h"
#include "voice_banmgr.h"
#include "vgui_checkbutton2.h"
#include "vgui_defaultinputsignal.h"
class CVoiceStatus;
class CVoiceLabel
{
public:
vgui::Label *m_pLabel;
vgui::Label *m_pBackground;
vgui::ImagePanel *m_pIcon; // Voice icon next to player name.
int m_clientindex; // Client index of the speaker. -1 if this label isn't being used.
};
// This is provided by each mod to access data that may not be the same across mods.
class IVoiceStatusHelper
{
public:
virtual ~IVoiceStatusHelper() {}
// Get RGB color for voice status text about this player.
virtual void GetPlayerTextColor(int entindex, int color[3]) = 0;
// Force it to update the cursor state.
virtual void UpdateCursorState() = 0;
// Return the height above the bottom that the voice ack icons should be drawn at.
virtual int GetAckIconHeight() = 0;
// Return true if the voice manager is allowed to show speaker labels
// (mods usually return false when the scoreboard is up).
virtual bool CanShowSpeakerLabels() = 0;
};
//-----------------------------------------------------------------------------
// Purpose: Holds a color for the shared image
//-----------------------------------------------------------------------------
class VoiceImagePanel : public vgui::ImagePanel
{
virtual void paintBackground()
{
if (_image!=null)
{
vgui::Color col;
getFgColor(col);
_image->setColor(col);
_image->doPaint(this);
}
}
};
class CVoiceStatus : public CHudBase, public vgui::CDefaultInputSignal
{
public:
CVoiceStatus();
virtual ~CVoiceStatus();
// CHudBase overrides.
public:
// Initialize the cl_dll's voice manager.
virtual int Init(
IVoiceStatusHelper *m_pHelper,
vgui::Panel **pParentPanel);
// ackPosition is the bottom position of where CVoiceStatus will draw the voice acknowledgement labels.
virtual int VidInit();
public:
// Call from HUD_Frame each frame.
void Frame(double frametime);
// Called when a player starts or stops talking.
// entindex is -1 to represent the local client talking (before the data comes back from the server).
// When the server acknowledges that the local client is talking, then entindex will be gEngfuncs.GetLocalPlayer().
// entindex is -2 to represent the local client's voice being acked by the server.
void UpdateSpeakerStatus(int entindex, qboolean bTalking);
// sets the correct image in the label for the player
void UpdateSpeakerImage(vgui::Label *pLabel, int iPlayer);
// Call from the HUD_CreateEntities function so it can add sprites above player heads.
void CreateEntities();
// Called when the server registers a change to who this client can hear.
void HandleVoiceMaskMsg(int iSize, void *pbuf);
// The server sends this message initially to tell the client to send their state.
void HandleReqStateMsg(int iSize, void *pbuf);
// Squelch mode functions.
public:
// When you enter squelch mode, pass in
void StartSquelchMode();
void StopSquelchMode();
bool IsInSquelchMode();
// returns true if the target client has been banned
// playerIndex is of range 1..maxplayers
bool IsPlayerBlocked(int iPlayerIndex);
// returns false if the player can't hear the other client due to game rules (eg. the other team)
bool IsPlayerAudible(int iPlayerIndex);
// blocks the target client from being heard
void SetPlayerBlockedState(int iPlayerIndex, bool blocked);
public:
CVoiceLabel* FindVoiceLabel(int clientindex); // Find a CVoiceLabel representing the specified speaker.
// Returns NULL if none.
// entindex can be -1 if you want a currently-unused voice label.
CVoiceLabel* GetFreeVoiceLabel(); // Get an unused voice label. Returns NULL if none.
void RepositionLabels();
void FreeBitmaps();
void UpdateServerState(bool bForce);
// Update the button artwork to reflect the client's current state.
void UpdateBanButton(int iClient);
public:
enum {MAX_VOICE_SPEAKERS=7};
float m_LastUpdateServerState; // Last time we called this function.
int m_bServerModEnable; // What we've sent to the server about our "voice_modenable" cvar.
vgui::Panel **m_pParentPanel;
CPlayerBitVec m_VoicePlayers; // Who is currently talking. Indexed by client index.
// This is the gamerules-defined list of players that you can hear. It is based on what teams people are on
// and is totally separate from the ban list. Indexed by client index.
CPlayerBitVec m_AudiblePlayers;
// Players who have spoken at least once in the game so far
CPlayerBitVec m_VoiceEnabledPlayers;
// This is who the server THINKS we have banned (it can become incorrect when a new player arrives on the server).
// It is checked periodically, and the server is told to squelch or unsquelch the appropriate players.
CPlayerBitVec m_ServerBannedPlayers;
cl_entity_s m_VoiceHeadModels[VOICE_MAX_PLAYERS]; // These aren't necessarily in the order of players. They are just
// a place for it to put data in during CreateEntities.
IVoiceStatusHelper *m_pHelper; // Each mod provides an implementation of this.
// Scoreboard icons.
double m_BlinkTimer; // Blink scoreboard icons..
vgui::BitmapTGA *m_pScoreboardNeverSpoken;
vgui::BitmapTGA *m_pScoreboardNotSpeaking;
vgui::BitmapTGA *m_pScoreboardSpeaking;
vgui::BitmapTGA *m_pScoreboardSpeaking2;
vgui::BitmapTGA *m_pScoreboardSquelch;
vgui::BitmapTGA *m_pScoreboardBanned;
vgui::Label *m_pBanButtons[VOICE_MAX_PLAYERS]; // scoreboard buttons.
// Squelch mode stuff.
bool m_bInSquelchMode;
HSPRITE m_VoiceHeadModel; // Voice head model (goes above players who are speaking).
float m_VoiceHeadModelHeight; // Height above their head to place the model.
vgui::Image *m_pSpeakerLabelIcon; // Icon next to speaker labels.
// Lower-right icons telling when the local player is talking..
vgui::BitmapTGA *m_pLocalBitmap; // Represents the local client talking.
vgui::BitmapTGA *m_pAckBitmap; // Represents the server ack'ing the client talking.
vgui::ImagePanel *m_pLocalLabel; // Represents the local client talking.
bool m_bTalking; // Set to true when the client thinks it's talking.
bool m_bServerAcked; // Set to true when the server knows the client is talking.
public:
CVoiceBanMgr m_BanMgr; // Tracks which users we have squelched and don't want to hear.
public:
bool m_bBanMgrInitialized;
// Labels telling who is speaking.
CVoiceLabel m_Labels[MAX_VOICE_SPEAKERS];
// Cache the game directory for use when we shut down
char * m_pchGameDir;
};
// Get the (global) voice manager.
CVoiceStatus* GetClientVoiceMgr();
#endif // VOICE_STATUS_H

View File

@ -0,0 +1,289 @@
//========= Copyright <20> 1996-2002, Valve LLC, All rights reserved. ============
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#include "../cl_dll/hud.h"
#include "../cl_dll/cl_util.h"
#include "../cl_dll/vgui_teamfortressviewport.h"
#include "vgui_actionsignal.h"
#include "voice_vgui_tweakdlg.h"
#include "voice_vgui_tweakdlg.h"
#include "vgui_panel.h"
#include "vgui_scrollbar.h"
#include "vgui_slider.h"
#include "ivoicetweak.h"
#include "vgui_button.h"
#include "vgui_checkbutton2.h"
#include "vgui_helpers.h"
#define ITEM_BORDER 40 // Border between text and scrollbars on left and right.
#define VOICETWEAK_TRANSPARENCY 150
class TweakScroller
{
public:
TweakScroller();
void Init(Panel *pParent, char *pText, int yPos);
// Get/set value. Values are 0-1.
float GetValue();
void SetValue(float val);
public:
Label m_Label;
ScrollBar m_Scroll;
Slider m_Slider;
};
class CVoiceVGUITweakDlg : public CMenuPanel, public ICheckButton2Handler
{
typedef CMenuPanel BaseClass;
public:
CVoiceVGUITweakDlg();
~CVoiceVGUITweakDlg();
// CMenuPanel overrides.
public:
virtual void Open();
virtual void Close();
// ICheckButton2Handler overrides.
public:
virtual void StateChanged(CCheckButton2 *pButton);
// Panel overrides.
public:
virtual void paintBackground();
private:
int m_DlgWidth;
int m_DlgHeight;
Label m_Label;
IVoiceTweak *m_pVoiceTweak; // Engine voice tweak API.
TweakScroller m_MicVolume;
TweakScroller m_SpeakerVolume;
CCheckButton2 m_VoiceModEnable;
Button m_Button_OK;
};
bool g_bTweakDlgOpen = false;
bool IsTweakDlgOpen()
{
return g_bTweakDlgOpen;
}
// ------------------------------------------------------------------------ //
// Global functions.
// ------------------------------------------------------------------------ //
static CVoiceVGUITweakDlg g_VoiceTweakDlg;
CMenuPanel* GetVoiceTweakDlg()
{
return &g_VoiceTweakDlg;
}
class CVoiceTweakOKButton : public ActionSignal
{
public:
virtual void actionPerformed(Panel *pPanel)
{
gViewPort->HideVGUIMenu();
}
};
CVoiceTweakOKButton g_OKButtonSignal;
// ------------------------------------------------------------------------ //
// TweakScroller
// ------------------------------------------------------------------------ //
TweakScroller::TweakScroller() :
m_Label(""),
m_Scroll(0,0,0,0,false),
m_Slider(0,0,10,10,false)
{
}
void TweakScroller::Init(Panel *pParent, char *pText, int yPos)
{
int parentWidth, parentHeight;
pParent->getSize(parentWidth, parentHeight);
// Setup the volume scroll bar.
m_Label.setParent(pParent);
m_Label.setFont(Scheme::sf_primary1);
m_Label.setContentAlignment(vgui::Label::a_northwest);
m_Label.setBgColor(0, 0, 0, 255);
m_Label.setFgColor(255,255,255,0);
m_Label.setPos(ITEM_BORDER, yPos);
m_Label.setSize(parentWidth/2-ITEM_BORDER, 20);
m_Label.setText(pText);
m_Label.setVisible(true);
m_Slider.setRangeWindow(10);
m_Slider.setRangeWindowEnabled(true);
m_Scroll.setPos(parentWidth/2+ITEM_BORDER, yPos);
m_Scroll.setSize(parentWidth/2-ITEM_BORDER*2, 20);
m_Scroll.setSlider(&m_Slider);
m_Scroll.setParent(pParent);
m_Scroll.setRange(0, 100);
m_Scroll.setFgColor(255,255,255,0);
m_Scroll.setBgColor(255,255,255,0);
}
float TweakScroller::GetValue()
{
return m_Scroll.getValue() / 100.0f;
}
void TweakScroller::SetValue(float val)
{
m_Scroll.setValue((int)(val * 100.0f));
}
// ------------------------------------------------------------------------ //
// CVoiceVGUITweakDlg implementation.
// ------------------------------------------------------------------------ //
CVoiceVGUITweakDlg::CVoiceVGUITweakDlg()
: CMenuPanel(VOICETWEAK_TRANSPARENCY, false, 0, 0, 0, 0),
m_Button_OK("",0,0),
m_Label("")
{
m_pVoiceTweak = NULL;
m_Button_OK.addActionSignal(&g_OKButtonSignal);
m_Label.setBgColor(255,255,255,200);
}
CVoiceVGUITweakDlg::~CVoiceVGUITweakDlg()
{
}
void CVoiceVGUITweakDlg::Open()
{
if(g_bTweakDlgOpen)
return;
g_bTweakDlgOpen = true;
m_DlgWidth = ScreenWidth;
m_DlgHeight = ScreenHeight;
m_pVoiceTweak = gEngfuncs.pVoiceTweak;
// Tell the engine to start voice tweak mode (pipe voice output right to speakers).
m_pVoiceTweak->StartVoiceTweakMode();
// Set our size.
setPos((ScreenWidth - m_DlgWidth) / 2, (ScreenHeight - m_DlgHeight) / 2);
setSize(m_DlgWidth, m_DlgHeight);
int curY = ITEM_BORDER;
m_MicVolume.Init(this, gHUD.m_TextMessage.BufferedLocaliseTextString("#Mic_Volume"), curY);
m_MicVolume.SetValue(m_pVoiceTweak->GetControlFloat(MicrophoneVolume));
curY = PanelBottom(&m_MicVolume.m_Label);
m_SpeakerVolume.Init(this, gHUD.m_TextMessage.BufferedLocaliseTextString("#Speaker_Volume"), curY);
m_SpeakerVolume.SetValue(m_pVoiceTweak->GetControlFloat(OtherSpeakerScale));
curY = PanelBottom(&m_SpeakerVolume.m_Label);
m_VoiceModEnable.setParent(this);
m_VoiceModEnable.SetImages("gfx/vgui/checked.tga", "gfx/vgui/unchecked.tga");
m_VoiceModEnable.SetText("Enable Voice In This Mod");
m_VoiceModEnable.setPos(ITEM_BORDER, curY);
m_VoiceModEnable.SetCheckboxLeft(false);
m_VoiceModEnable.SetChecked(!!gEngfuncs.pfnGetCvarFloat("voice_modenable"));
m_VoiceModEnable.SetHandler(this);
// Setup the OK button.
int buttonWidth, buttonHeight;
m_Button_OK.setText(gHUD.m_TextMessage.BufferedLocaliseTextString("#Menu_OK"));
m_Button_OK.getSize(buttonWidth, buttonHeight);
m_Button_OK.setPos((m_DlgWidth - buttonWidth) / 2, m_DlgHeight - buttonHeight - 3);
m_Button_OK.setParent(this);
// Put the label on the top.
m_Label.setBgColor(0, 0, 0, 255);
m_Label.setFgColor(255,255,255,0);
m_Label.setText(gHUD.m_TextMessage.BufferedLocaliseTextString("#Voice_Properties"));
int labelWidth, labelHeight;
m_Label.getSize(labelWidth, labelHeight);
m_Label.setPos((m_DlgWidth - labelWidth) / 2, 5);
m_Label.setParent(this);
BaseClass::Open();
}
void CVoiceVGUITweakDlg::Close()
{
m_pVoiceTweak->EndVoiceTweakMode();
g_bTweakDlgOpen = false;
BaseClass::Close();
}
void CVoiceVGUITweakDlg::paintBackground()
{
BaseClass::paintBackground();
// Draw our border.
int w,h;
getSize(w,h);
drawSetColor(128,128,128,1);
drawOutlinedRect(0, 0, w, h);
float volume = m_MicVolume.GetValue();
m_pVoiceTweak->SetControlFloat(MicrophoneVolume, volume);
m_pVoiceTweak->SetControlFloat(OtherSpeakerScale, m_SpeakerVolume.GetValue());
}
void CVoiceVGUITweakDlg::StateChanged(CCheckButton2 *pButton)
{
if(pButton == &m_VoiceModEnable)
{
if(pButton->IsChecked())
gEngfuncs.pfnClientCmd("voice_modenable 1");
else
gEngfuncs.pfnClientCmd("voice_modenable 0");
}
}

View File

@ -0,0 +1,27 @@
//========= Copyright <20> 1996-2002, Valve LLC, All rights reserved. ============
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#ifndef VOICE_VGUI_TWEAKDLG_H
#define VOICE_VGUI_TWEAKDLG_H
#ifdef _WIN32
#ifndef __MINGW32__
#pragma once
#endif /* not __MINGW32__ */
#endif
class CMenuPanel;
// Returns true if the tweak dialog is currently up.
bool IsTweakDlgOpen();
// Returns a global instance of the tweak dialog.
CMenuPanel* GetVoiceTweakDlg();
#endif // VOICE_VGUI_TWEAKDLG_H