mirror of
https://github.com/unknownworlds/NS.git
synced 2024-12-12 21:51:52 +00:00
755 lines
23 KiB
C++
755 lines
23 KiB
C++
|
#include "ui/UIComponent.h"
|
||
|
#include "ui/UIManager.h"
|
||
|
#include "ui/UIFactory.h"
|
||
|
#include "ui/UITags.h"
|
||
|
#include "vgui_Menu.h"
|
||
|
#include "vgui_App.h"
|
||
|
#include "cl_dll/hud.h"
|
||
|
#include "cl_dll/cl_util.h"
|
||
|
#include "textrep/TRFactory.h"
|
||
|
#include "cl_dll/vgui_SchemeManager.h"
|
||
|
#include "vgui_TextPanel.h"
|
||
|
#include "vgui_Label.h"
|
||
|
#include "cl_dll/vgui_TeamFortressViewport.h"
|
||
|
#include "ui/GammaAwareComponent.h"
|
||
|
#include "ui/ReloadableComponent.h"
|
||
|
|
||
|
//using vgui::Label;
|
||
|
//extern CImageLabel *gTestLabel;
|
||
|
|
||
|
extern vgui::BitmapTGA *vgui_LoadTGA( const char* pImageName, bool bInvertAlpha = true);
|
||
|
|
||
|
const int kTranslation = 1000;
|
||
|
|
||
|
// Stupid messy externs
|
||
|
extern "C"
|
||
|
{
|
||
|
void* VGui_GetPanel();
|
||
|
}
|
||
|
extern int g_iVisibleMouse;
|
||
|
|
||
|
UIManager::UIManager(UIFactory* inFactory)
|
||
|
{
|
||
|
this->mEditMode = false;
|
||
|
this->mDraggingLMB = false;
|
||
|
this->mUsingVGUI = false;
|
||
|
|
||
|
this->mLMBDownX = this->mLMBDownY = -1;
|
||
|
this->mLastMouseX = this->mLastMouseY = -1;
|
||
|
|
||
|
this->mComponentMouseOver = NULL;
|
||
|
this->mBlankCursor = NULL;
|
||
|
|
||
|
this->mFactory = inFactory;
|
||
|
this->mGammaSlope = 1.0f;
|
||
|
}
|
||
|
|
||
|
UIManager::~UIManager(void)
|
||
|
{
|
||
|
delete this->mFactory;
|
||
|
this->mFactory = NULL;
|
||
|
|
||
|
delete this->mBlankCursor;
|
||
|
this->mBlankCursor = NULL;
|
||
|
}
|
||
|
|
||
|
void UIManager::AddInputSignal(InputSignal* inInputSignal)
|
||
|
{
|
||
|
UIComponentListType::iterator theCompIter;
|
||
|
|
||
|
for(theCompIter = this->mComponentList.begin(); theCompIter != this->mComponentList.end(); theCompIter++)
|
||
|
{
|
||
|
UIComponent* theComponent = *theCompIter;
|
||
|
ASSERT(theComponent);
|
||
|
Panel* theVGUIComponent = theComponent->GetComponentPointer();
|
||
|
ASSERT(theVGUIComponent);
|
||
|
theVGUIComponent->addInputSignal(inInputSignal);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bool UIManager::Clear(void)
|
||
|
{
|
||
|
bool theSuccess = false;
|
||
|
|
||
|
// Make sure we aren't in edit mode
|
||
|
if(!this->mEditMode)
|
||
|
{
|
||
|
// Delete every component in the list
|
||
|
UIComponentListType::iterator theCompIter;
|
||
|
for(theCompIter = this->mComponentList.begin(); theCompIter != this->mComponentList.end(); theCompIter++)
|
||
|
{
|
||
|
delete *theCompIter;
|
||
|
theSuccess = true;
|
||
|
}
|
||
|
|
||
|
// Delete the list
|
||
|
this->mComponentList.clear();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// TODO: Emit error indicating manager can't be cleared in edit mode
|
||
|
}
|
||
|
|
||
|
return theSuccess;
|
||
|
}
|
||
|
|
||
|
UIComponent* UIManager::GetComponentFromPanel(Panel* inPanel)
|
||
|
{
|
||
|
UIComponent* theComponent = NULL;
|
||
|
|
||
|
UIComponentListType::iterator theCompIter;
|
||
|
for(theCompIter = this->mComponentList.begin(); theCompIter != this->mComponentList.end(); theCompIter++)
|
||
|
{
|
||
|
if((*theCompIter)->GetComponentPointer() == inPanel)
|
||
|
{
|
||
|
theComponent = *theCompIter;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
return theComponent;
|
||
|
}
|
||
|
|
||
|
UIComponent* UIManager::GetComponentNamed(const string& inName)
|
||
|
{
|
||
|
UIComponent* theResult = NULL;
|
||
|
|
||
|
UIComponentListType::iterator theCompIter;
|
||
|
for(theCompIter = this->mComponentList.begin(); theCompIter != this->mComponentList.end(); theCompIter++)
|
||
|
{
|
||
|
if((*theCompIter)->GetName() == inName)
|
||
|
{
|
||
|
theResult = *theCompIter;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return theResult;
|
||
|
}
|
||
|
|
||
|
const UIComponent* UIManager::GetComponentNamed(const string& inName) const
|
||
|
{
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
// TODO: Add list of components that are "hidden" and fail if the component is already hidden
|
||
|
bool UIManager::HideComponent(const string& inName)
|
||
|
{
|
||
|
bool theSuccess = false;
|
||
|
vgui::Panel* thePanel = NULL;
|
||
|
|
||
|
if(this->GetVGUIComponentNamed(inName, thePanel))
|
||
|
{
|
||
|
ASSERT(thePanel != NULL);
|
||
|
//this->TranslateComponent(thePanel, true);
|
||
|
thePanel->setVisible(false);
|
||
|
theSuccess = true;
|
||
|
}
|
||
|
|
||
|
return theSuccess;
|
||
|
}
|
||
|
|
||
|
void UIManager::HideComponents()
|
||
|
{
|
||
|
typedef vector<UIComponent*> UIComponentListType;
|
||
|
|
||
|
for(UIComponentListType::iterator theIter = this->mComponentList.begin(); theIter != this->mComponentList.end(); theIter++)
|
||
|
{
|
||
|
this->HideComponent((*theIter)->GetName());
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bool UIManager::Initialize(const TRDescriptionList& inDesc, CSchemeManager* inSchemeManager)
|
||
|
{
|
||
|
bool theSuccess = false;
|
||
|
|
||
|
// Clear out everything in case we have already been used once
|
||
|
this->Clear();
|
||
|
|
||
|
// Now loop through entities found
|
||
|
for(TRDescriptionList::const_iterator theListIter = inDesc.begin(); theListIter != inDesc.end(); theListIter++)
|
||
|
{
|
||
|
// See if the factory knows how to create such a thing. It is giving the memory to us forever so take care of it.
|
||
|
UIComponent* theCurrentComponent = this->mFactory->BuildComponent(*theListIter, inSchemeManager);
|
||
|
|
||
|
// Tell it to set all the tags it knows about
|
||
|
if(theCurrentComponent)
|
||
|
{
|
||
|
// Check for named root tag, look up that component and set it
|
||
|
Panel* theRoot = NULL;
|
||
|
string theRootName;
|
||
|
|
||
|
if(theListIter->GetTagValue("root", theRootName))
|
||
|
{
|
||
|
UIComponent* theUIComponent = NULL;
|
||
|
theUIComponent = this->GetComponentNamed(theRootName);
|
||
|
if(theUIComponent)
|
||
|
{
|
||
|
theRoot = theUIComponent->GetComponentPointer();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// If none specified or it couldn't be found, use default
|
||
|
if(!theRoot)
|
||
|
{
|
||
|
theRoot = (Panel*)VGui_GetPanel();
|
||
|
}
|
||
|
|
||
|
// Set the root
|
||
|
theCurrentComponent->GetComponentPointer()->setParent(theRoot);
|
||
|
|
||
|
// Add to menu if specified
|
||
|
string theMenuName;
|
||
|
if(theListIter->GetTagValue(UITagMenuAddItem, theMenuName))
|
||
|
{
|
||
|
Menu* theParentMenu = NULL;
|
||
|
if(this->GetVGUIComponentNamed(theMenuName, theParentMenu))
|
||
|
{
|
||
|
theParentMenu->addMenuItem(theCurrentComponent->GetComponentPointer());
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Set up scheme if specified
|
||
|
if(inSchemeManager)
|
||
|
{
|
||
|
this->SetSchemeValues(*theListIter, theCurrentComponent, inSchemeManager);
|
||
|
}
|
||
|
|
||
|
// <sigh> If we are currently using the regular VGUI instead of the manager, translate
|
||
|
// this component out of the way so it doesn't suck up input
|
||
|
if(this->mUsingVGUI)
|
||
|
{
|
||
|
this->TranslateComponent(theCurrentComponent->GetComponentPointer(), true);
|
||
|
}
|
||
|
|
||
|
// If gamma aware, tell it immediately
|
||
|
GammaAwareComponent* theGammaAwareComponent = dynamic_cast<GammaAwareComponent*>(theCurrentComponent->GetComponentPointer());
|
||
|
if(theGammaAwareComponent)
|
||
|
{
|
||
|
theGammaAwareComponent->NotifyGammaChange(this->mGammaSlope);
|
||
|
}
|
||
|
|
||
|
// Save it. It is now part of the world.
|
||
|
this->mComponentList.push_back(theCurrentComponent);
|
||
|
|
||
|
// Return success if we found at least one component
|
||
|
theSuccess = true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Build default blank cursor
|
||
|
this->mBlankCursor = new Cursor(vgui_LoadTGA("blank"), 0, 0);
|
||
|
|
||
|
// Register for notification for all input events
|
||
|
//this->AddInputSignal(this);
|
||
|
|
||
|
return theSuccess;
|
||
|
}
|
||
|
|
||
|
bool UIManager::InMouseMode(void) const
|
||
|
{
|
||
|
return (g_iVisibleMouse ? true : false);
|
||
|
}
|
||
|
|
||
|
void UIManager::NotifyGammaChange(float inGammaSlope)
|
||
|
{
|
||
|
UIComponentListType::iterator theCompIter;
|
||
|
for(theCompIter = this->mComponentList.begin(); theCompIter != this->mComponentList.end(); theCompIter++)
|
||
|
{
|
||
|
GammaAwareComponent* theGammaAwareComponent = dynamic_cast<GammaAwareComponent*>((*theCompIter)->GetComponentPointer());
|
||
|
if(theGammaAwareComponent)
|
||
|
{
|
||
|
theGammaAwareComponent->NotifyGammaChange(inGammaSlope);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
this->mGammaSlope = inGammaSlope;
|
||
|
}
|
||
|
|
||
|
bool UIManager::Save(const string& outFilename, const string& outHeader)
|
||
|
{
|
||
|
// Build description list
|
||
|
TRDescriptionList theDescriptionList;
|
||
|
|
||
|
UIComponentListType::iterator theCompIter;
|
||
|
for(theCompIter = this->mComponentList.begin(); theCompIter != this->mComponentList.end(); theCompIter++)
|
||
|
{
|
||
|
theDescriptionList.push_back((*theCompIter)->GetDescription());
|
||
|
}
|
||
|
|
||
|
// Write it out!
|
||
|
TRFactory::WriteDescriptions(outFilename, theDescriptionList, outHeader);
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
bool UIManager::SetLMBActionAbsolute(const TRTag& inTag)
|
||
|
{
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
bool UIManager::SetLMBActionRelative(const TRTag& inTag)
|
||
|
{
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
void UIManager::SetMouseVisibility(bool inState)
|
||
|
{
|
||
|
// To change whether the mouse is visible, just change this variable
|
||
|
g_iVisibleMouse = inState;
|
||
|
|
||
|
// Update cursor
|
||
|
if(g_iVisibleMouse)
|
||
|
{
|
||
|
//ClientCmd("say Entering mouse mode.");
|
||
|
//App::getInstance()->setCursorOveride(App::getInstance()->getScheme()->getCursor(Scheme::SchemeCursor::scu_arrow));
|
||
|
// Remove above line and put this line back in for sprite cursors
|
||
|
App::getInstance()->setCursorOveride(this->mBlankCursor);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//ClientCmd("say Exiting mouse mode.");
|
||
|
// Move mouse to center of screen so mouse look isn't changed
|
||
|
|
||
|
// Only do this when in full screen
|
||
|
App::getInstance()->setCursorPos(ScreenWidth()/2, ScreenHeight()/2);
|
||
|
|
||
|
// Hide cursor again
|
||
|
App::getInstance()->setCursorOveride( App::getInstance()->getScheme()->getCursor(Scheme::SchemeCursor::scu_none) );
|
||
|
}
|
||
|
|
||
|
//App::getInstance()->setCursorOveride( App::getInstance()->getScheme()->getCursor(Scheme::SchemeCursor::scu_none) );
|
||
|
|
||
|
}
|
||
|
|
||
|
// Set up default scheme values if a scheme was specified (overrides other tags specified)
|
||
|
void UIManager::SetSchemeValues(const TRDescription& inDesc, UIComponent* inComponent, CSchemeManager* inSchemeManager)
|
||
|
{
|
||
|
std::string theSchemeName;
|
||
|
if(inDesc.GetTagValue(UITagScheme, theSchemeName))
|
||
|
{
|
||
|
// Get the vgui panel inside
|
||
|
Panel* thePanelPointer = inComponent->GetComponentPointer();
|
||
|
|
||
|
// Get the scheme specified in the layout
|
||
|
const char* theSchemeCString = theSchemeName.c_str();
|
||
|
SchemeHandle_t theSchemeHandle = inSchemeManager->getSchemeHandle(theSchemeCString);
|
||
|
int r, g, b, a;
|
||
|
|
||
|
// Set fg color
|
||
|
inSchemeManager->getFgColor(theSchemeHandle, r, g, b, a);
|
||
|
thePanelPointer->setFgColor(r, g, b, a);
|
||
|
|
||
|
// Set bg color
|
||
|
inSchemeManager->getBgColor(theSchemeHandle, r, g, b, a);
|
||
|
thePanelPointer->setBgColor(r, g, b, a);
|
||
|
|
||
|
// Set font if applicable
|
||
|
vgui::Font* theFont = inSchemeManager->getFont(theSchemeHandle);
|
||
|
vgui::TextPanel* theTextPanel = dynamic_cast<vgui::TextPanel*>(thePanelPointer);
|
||
|
if(theFont && theTextPanel)
|
||
|
{
|
||
|
theTextPanel->setFont(theFont);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bool UIManager::SetRMBActionAbsolute(const TRTag& inTag)
|
||
|
{
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
bool UIManager::SetRMBActionRelative(const TRTag& inTag)
|
||
|
{
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
void UIManager::SetUsingVGUI(bool inState)
|
||
|
{
|
||
|
if(inState)
|
||
|
{
|
||
|
if(!this->mUsingVGUI)
|
||
|
{
|
||
|
// Translate all components away
|
||
|
this->TranslateComponents(true);
|
||
|
this->mUsingVGUI = true;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if(this->mUsingVGUI)
|
||
|
{
|
||
|
// Translate everything back
|
||
|
this->TranslateComponents(false);
|
||
|
this->mUsingVGUI = false;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bool UIManager::TranslateComponent(const string& inName, bool inAway)
|
||
|
{
|
||
|
bool theSuccess = false;
|
||
|
|
||
|
UIComponent* theComponent = this->GetComponentNamed(inName);
|
||
|
if(theComponent)
|
||
|
{
|
||
|
this->TranslateComponent(theComponent->GetComponentPointer(), inAway);
|
||
|
theSuccess = true;
|
||
|
}
|
||
|
return theSuccess;
|
||
|
|
||
|
}
|
||
|
|
||
|
void UIManager::TranslateComponent(vgui::Panel* inPanel, bool inAway)
|
||
|
{
|
||
|
int theX, theY;
|
||
|
inPanel->getPos(theX, theY);
|
||
|
int theAmount = kTranslation*(inAway ? 1 : -1);
|
||
|
inPanel->setPos(theX + theAmount, theY + theAmount);
|
||
|
}
|
||
|
|
||
|
void UIManager::TranslateComponents(bool inAway)
|
||
|
{
|
||
|
UIComponentListType::iterator theCompIter;
|
||
|
for(theCompIter = this->mComponentList.begin(); theCompIter != this->mComponentList.end(); theCompIter++)
|
||
|
{
|
||
|
vgui::Panel* theCurrentPanel = (*theCompIter)->GetComponentPointer();
|
||
|
this->TranslateComponent(theCurrentPanel, inAway);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bool UIManager::ToggleEditMode(void)
|
||
|
{
|
||
|
bool theWasInEditMode = this->mEditMode;
|
||
|
|
||
|
this->mEditMode = !this->mEditMode;
|
||
|
|
||
|
// if(this->mEditMode)
|
||
|
// {
|
||
|
// ClientCmd("say Entering edit mode.");
|
||
|
// }
|
||
|
// else
|
||
|
// {
|
||
|
// ClientCmd("say Exiting edit mode.");
|
||
|
// }
|
||
|
|
||
|
// If we enter edit mode, disable all components. If we leave, reenable them.
|
||
|
this->SetEnabledState(!this->mEditMode);
|
||
|
|
||
|
//CLIENT_PRINTF( pEntity, print_console, UTIL_VarArgs( "\"fov\" is \"%d\"\n", (int)GetClassPtr((CBasePlayer *)pev)->m_iFOV ) );
|
||
|
if(!this->mEditMode)
|
||
|
{
|
||
|
// Reset graphical layout variables
|
||
|
this->mComponentMouseOver = NULL;
|
||
|
this->mDraggingLMB = false;
|
||
|
this->mLastMouseX = this->mLastMouseY = -1;
|
||
|
this->mLMBDownX = this->mLMBDownY = -1;
|
||
|
}
|
||
|
|
||
|
return theWasInEditMode;
|
||
|
}
|
||
|
|
||
|
// TODO: Add list of components that are "hidden" and fail if the component is not currently hidden
|
||
|
bool UIManager::UnhideComponent(const string& inName)
|
||
|
{
|
||
|
bool theSuccess = false;
|
||
|
vgui::Panel* thePanel = NULL;
|
||
|
|
||
|
if(this->GetVGUIComponentNamed(inName, thePanel))
|
||
|
{
|
||
|
ASSERT(thePanel != NULL);
|
||
|
//this->TranslateComponent(thePanel, false);
|
||
|
thePanel->setVisible(true);
|
||
|
theSuccess = true;
|
||
|
}
|
||
|
|
||
|
return theSuccess;
|
||
|
}
|
||
|
|
||
|
void UIManager::Update(float inCurrentTime)
|
||
|
{
|
||
|
UIComponentListType::iterator theCompIter;
|
||
|
for(theCompIter = this->mComponentList.begin(); theCompIter != this->mComponentList.end(); theCompIter++)
|
||
|
{
|
||
|
(*theCompIter)->Update(inCurrentTime);
|
||
|
}
|
||
|
|
||
|
// int r, g, b, a;
|
||
|
// r = g = b = a = 0;
|
||
|
// //gTestLabel->getFgColor(r, g, b, a);
|
||
|
// vgui::Color theColor;
|
||
|
// gTestLabel->m_pTGA->getColor(theColor);
|
||
|
// theColor.getColor(r, g, b, a);
|
||
|
// r = (r + 1) % 255;
|
||
|
// theColor.setColor(r, g, b, a);
|
||
|
// gTestLabel->m_pTGA->setColor(theColor);
|
||
|
// //gTestLabel->setFgColor(r, g, b, a);
|
||
|
//
|
||
|
// gTestLabel->getBgColor(r, g, b, a);
|
||
|
// a = (a + 1) % 255;
|
||
|
// gTestLabel->setBgColor(r, g, b, a);
|
||
|
}
|
||
|
|
||
|
void UIManager::VidInit(void)
|
||
|
{
|
||
|
UIComponentListType::iterator theCompIter;
|
||
|
for(theCompIter = this->mComponentList.begin(); theCompIter != this->mComponentList.end(); theCompIter++)
|
||
|
{
|
||
|
ReloadableComponent* theReloadableComponent = dynamic_cast<ReloadableComponent*>((*theCompIter)->GetComponentPointer());
|
||
|
if(theReloadableComponent)
|
||
|
{
|
||
|
theReloadableComponent->VidInit();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
void UIManager::ToggleMouse(void)
|
||
|
{
|
||
|
this->SetMouseVisibility(!g_iVisibleMouse);
|
||
|
}
|
||
|
|
||
|
////////////////////////////////
|
||
|
// Functions from InputSignal //
|
||
|
////////////////////////////////
|
||
|
void UIManager::cursorMoved(int inX, int inY, Panel* inPanel)
|
||
|
{
|
||
|
if(!inPanel)
|
||
|
{
|
||
|
ClientCmd("say cursorMoved with null inPanel! Yeah!\n");
|
||
|
}
|
||
|
|
||
|
// x,y are local to the upper left of the panel.
|
||
|
int theLocalX = inX;
|
||
|
int theLocalY = inY;
|
||
|
|
||
|
// Get screen coordinates
|
||
|
int theScreenX, theScreenY;
|
||
|
this->GetScreenCoords(theScreenX, theScreenY);
|
||
|
|
||
|
// This function should only be called when mouse visible and we are in edit mode
|
||
|
if(this->mEditMode)
|
||
|
{
|
||
|
// We can't assume that a cursorEntered will always get called before a cursor moved, so
|
||
|
// call cursorEntered if we don't have a component yet (happens when toggling between the two modes
|
||
|
if(!this->mComponentMouseOver)
|
||
|
{
|
||
|
this->cursorEntered(inPanel);
|
||
|
}
|
||
|
|
||
|
// Number of pixels to move with the mouse button down before we start dragging
|
||
|
const int START_DRAG_PIXEL_DIST = 6;
|
||
|
const int MIN_DRAG_PIXEL_DIST = 4;
|
||
|
static int theStartDragLocalXOffset = 0;
|
||
|
static int theStartDragLocalYOffset = 0;
|
||
|
|
||
|
// Check how far we have moved, are we dragging yet?
|
||
|
if((!this->mDraggingLMB) &&
|
||
|
(this->mLMBDownX != -1) &&
|
||
|
(this->mLMBDownY != -1))
|
||
|
{
|
||
|
int theXDiff = theScreenX - this->mLMBDownX;
|
||
|
int theYDiff = theScreenY - this->mLMBDownY;
|
||
|
|
||
|
// Requires more movement in diagonal direction, probably not
|
||
|
// worth the extra complexity to change
|
||
|
if((abs(theXDiff) > START_DRAG_PIXEL_DIST) ||
|
||
|
(abs(theYDiff) > START_DRAG_PIXEL_DIST))
|
||
|
{
|
||
|
//ClientCmd("say Starting drag");
|
||
|
|
||
|
// Save the offset from the component's upper left. Preserve
|
||
|
// this when for more intuitive dragging (so dragging doesn't
|
||
|
// suddenly move the component relative to the mouse).
|
||
|
theStartDragLocalXOffset = theLocalX;
|
||
|
theStartDragLocalYOffset = theLocalY;
|
||
|
|
||
|
//inPanel->setAsMouseArena(true);
|
||
|
|
||
|
this->mDraggingLMB = true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Are we dragging?
|
||
|
if(this->mDraggingLMB)
|
||
|
{
|
||
|
// If so, set the component's new position. The position corresponds to the upper
|
||
|
// left corner of the component, so subtract out the local offset.
|
||
|
// The component's new position is equal to the current screen pos of the mouse, MINUS
|
||
|
// the local component offset which we started the drag. If we were dragging the component
|
||
|
// around by the upper left corner, this would be like setting the component's position equal
|
||
|
// to whatever the mouse was at during a mouse move. If we were dragging it by the center,
|
||
|
// it would set the component's position to the current screen mouse pos minus half the component
|
||
|
// width and height. Make sense?
|
||
|
//ClientCmd("say Setting new component position");
|
||
|
int theChangeX = theScreenX - theStartDragLocalXOffset;
|
||
|
int theChangeY = theScreenY - theStartDragLocalYOffset;
|
||
|
|
||
|
// Make sure we move at least a few pixels, because we're bound by control and we
|
||
|
// could've grabbed it near one of the edges
|
||
|
theChangeX = max(theChangeX, MIN_DRAG_PIXEL_DIST);
|
||
|
theChangeY = max(theChangeY, MIN_DRAG_PIXEL_DIST);
|
||
|
this->SetPanelPosition(inPanel, theChangeX, theChangeY);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Update new mouse position
|
||
|
this->mLastMouseX = theScreenX;
|
||
|
this->mLastMouseY = theScreenY;
|
||
|
}
|
||
|
|
||
|
|
||
|
void UIManager::SetPanelPosition(Panel* inPanel, int inX, int inY)
|
||
|
{
|
||
|
// Look up the component
|
||
|
UIComponent* theUIComp = this->GetComponentFromPanel(inPanel);
|
||
|
if(theUIComp)
|
||
|
{
|
||
|
// Update run-time version
|
||
|
// Set the vgui panel's position (pixel coords)
|
||
|
// Clip so component never goes off the screen in any way
|
||
|
int theCompWidth = 0;
|
||
|
int theCompHeight = 0;
|
||
|
inPanel->getSize(theCompWidth, theCompHeight);
|
||
|
|
||
|
int theClippedScreenX = max(min(inX, ScreenWidth() - theCompWidth), 0);
|
||
|
int theClippedScreenY = max(min(inY, ScreenHeight() - theCompHeight), 0);
|
||
|
inPanel->setPos(theClippedScreenX, theClippedScreenY);
|
||
|
|
||
|
// repaint parent if present
|
||
|
Panel* inPanelParent = inPanel->getParent();
|
||
|
if(inPanelParent != NULL)
|
||
|
{
|
||
|
inPanelParent->repaint();
|
||
|
}
|
||
|
|
||
|
// Convert to normalized coords for text representation.
|
||
|
float theClippedNormX = (float)theClippedScreenX/ScreenWidth();
|
||
|
float theClippedNormY = (float)theClippedScreenY/ScreenHeight();
|
||
|
|
||
|
// Change the text represntation so it has the update coordinates (normalized coords)
|
||
|
// This means it can save out again with the player's changes!
|
||
|
TRDescription& theCompDesc = theUIComp->GetDescription();
|
||
|
theCompDesc.SetTagValue(UITagXPos, theClippedNormX);
|
||
|
theCompDesc.SetTagValue(UITagYPos, theClippedNormY);
|
||
|
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//ClientCmd("say Can't find UIComponent that you're dragging, can't save changes to it.");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void UIManager::cursorEntered(Panel* inPanel)
|
||
|
{
|
||
|
// Handle stacking of ui components. Only enter component if we aren't already on a component
|
||
|
if(!this->mComponentMouseOver)
|
||
|
{
|
||
|
if(!this->mDraggingLMB)
|
||
|
{
|
||
|
//ClientCmd("say Cursor entered component");
|
||
|
this->mComponentMouseOver = inPanel;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void UIManager::cursorExited(Panel* inPanel)
|
||
|
{
|
||
|
// Only leave the component we are currently on for stacking purposes
|
||
|
if(this->mComponentMouseOver == inPanel)
|
||
|
{
|
||
|
if(!this->mDraggingLMB)
|
||
|
{
|
||
|
//ClientCmd("say Cursor exited component");
|
||
|
this->mComponentMouseOver = NULL;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void UIManager::mousePressed(MouseCode inCode, Panel* inPanel)
|
||
|
{
|
||
|
// Track dragging state
|
||
|
if(inCode == MOUSE_LEFT)
|
||
|
{
|
||
|
if(this->mComponentMouseOver)
|
||
|
{
|
||
|
//ClientCmd("say Left mouse pressed on component");
|
||
|
this->mLMBDownX = this->mLastMouseX;
|
||
|
this->mLMBDownY = this->mLastMouseY;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void UIManager::mouseDoublePressed(MouseCode inCode, Panel* inPanel)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
// Take into account the mouse offset into the component
|
||
|
// Note: This doesn't work in windowed mode, as it returns the cursor position in pixels,
|
||
|
// and the desktop resolution is different than HL resolution in windowed mode. If there
|
||
|
// are function to tell if we are in windowed mode, and to find the upper left x,y this
|
||
|
// could be fixed.
|
||
|
void UIManager::GetScreenCoords(int& outLocalX, int& outLocalY)
|
||
|
{
|
||
|
int theX, theY;
|
||
|
App::getInstance()->getCursorPos(theX, theY);
|
||
|
|
||
|
// int theLocalX = theX;
|
||
|
// int theLocalY = theY;
|
||
|
// inPanel->screenToLocal(theLocalX, theLocalY);
|
||
|
|
||
|
// theX += ioLocalX;
|
||
|
// theY += ioLocalY;
|
||
|
|
||
|
outLocalX = theX;
|
||
|
outLocalY = theY;
|
||
|
}
|
||
|
|
||
|
void UIManager::SetEnabledState(bool inState)
|
||
|
{
|
||
|
UIComponentListType::iterator theCompIter;
|
||
|
for(theCompIter = this->mComponentList.begin(); theCompIter != this->mComponentList.end(); theCompIter++)
|
||
|
{
|
||
|
(*theCompIter)->GetComponentPointer()->setEnabled(inState);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
void UIManager::mouseReleased(MouseCode code, Panel* inPanel)
|
||
|
{
|
||
|
// Track dragging state
|
||
|
if(code == MOUSE_LEFT)
|
||
|
{
|
||
|
//ClientCmd("say Left mouse released on component");
|
||
|
|
||
|
//ALERT(at_console, "Down xy = -1\n");
|
||
|
this->mLMBDownX = -1;
|
||
|
this->mLMBDownY = -1;
|
||
|
this->mDraggingLMB = false;
|
||
|
|
||
|
//App::getInstance()->setMouseArena(NULL);
|
||
|
//inPanel->setAsMouseArena(false);
|
||
|
//App::getInstance()->setMouseArena(NULL);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void UIManager::mouseWheeled(int delta,Panel* panel)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
void UIManager::keyPressed(KeyCode code,Panel* panel)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
void UIManager::keyTyped(KeyCode code,Panel* panel)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
void UIManager::keyReleased(KeyCode code,Panel* panel)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
void UIManager::keyFocusTicked(Panel* panel)
|
||
|
{
|
||
|
}
|
||
|
|