mirror of
https://github.com/unknownworlds/NS.git
synced 2024-12-22 10:21:16 +00:00
1423 lines
39 KiB
C++
1423 lines
39 KiB
C++
|
//======== (C) Copyright 2002 Charles G. Cleveland All rights reserved. =========
|
||
|
//
|
||
|
// The copyright to the contents herein is the property of Charles G. Cleveland.
|
||
|
// The contents may be used and/or copied only with the written permission of
|
||
|
// Charles G. Cleveland, or in accordance with the terms and conditions stipulated in
|
||
|
// the agreement/contract under which the contents have been supplied.
|
||
|
//
|
||
|
// Purpose:
|
||
|
//
|
||
|
// $Workfile: PieNode.cpp $
|
||
|
// $Date: 2002/08/31 18:04:32 $
|
||
|
//
|
||
|
//-------------------------------------------------------------------------------
|
||
|
// $Log: PieNode.cpp,v $
|
||
|
// Revision 1.18 2002/08/31 18:04:32 Flayra
|
||
|
// - Work at VALVe
|
||
|
//
|
||
|
// Revision 1.17 2002/08/16 02:29:19 Flayra
|
||
|
// - Added document headers
|
||
|
// - Started to add support for pie nodes with both images and text
|
||
|
//
|
||
|
// Revision 1.16 2002/07/08 16:18:52 Flayra
|
||
|
// - Tried to turn off mouse capture so menu can be binded to keyboard and mouse properly
|
||
|
//
|
||
|
//===============================================================================
|
||
|
#include "ui/PieNode.h"
|
||
|
#include "util/Tokenizer.h"
|
||
|
#include "cl_dll/vgui_int.h"
|
||
|
#include "ui/UIUtil.h"
|
||
|
|
||
|
const float kTwoPI = 2.0f*3.141519f;
|
||
|
int PieNode::mDegrees[kNumNodes] = {90, 135, 180, 225, 270, 315, 0, 45};
|
||
|
PieNode* gNodeToTrack = NULL;
|
||
|
const int kDarkGreenColor = 130;
|
||
|
const int kDisabledColorComponent = 180;
|
||
|
|
||
|
PieNode::PieNode(const string& inNodeString, int inMessageID) : FadingImageLabel(0, 0) //, 640, 480)
|
||
|
{
|
||
|
memset(this->mArray, 0, kNumNodes*sizeof(PieNode*));
|
||
|
this->mBaseText = inNodeString;
|
||
|
this->mPointCost = 0;
|
||
|
this->setText(inNodeString.c_str());
|
||
|
this->mNodeName = inNodeString;
|
||
|
this->mParentPieNode = NULL;
|
||
|
this->mMessageID = inMessageID;
|
||
|
this->mDrawSelected = false;
|
||
|
this->setVisible(false);
|
||
|
this->mEnabled = true;
|
||
|
this->mColorBias = 1.0f;
|
||
|
|
||
|
this->ComputeAndSetLocalizedText();
|
||
|
|
||
|
// Save defaults for resetting back to
|
||
|
this->mDefaultText = this->mBaseText;
|
||
|
this->mDefaultID = this->mMessageID;
|
||
|
this->mConnectorSprite = 0;
|
||
|
|
||
|
//this->SetFadeState(false);
|
||
|
}
|
||
|
|
||
|
PieNode::~PieNode()
|
||
|
{
|
||
|
for(int i = 0; i < kNumNodes; i++)
|
||
|
{
|
||
|
delete this->mArray[i];
|
||
|
this->mArray[i] = NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void PieNode::AddInputSignalForNodes(InputSignal* s)
|
||
|
{
|
||
|
FadingImageLabel::addInputSignal(s);
|
||
|
|
||
|
for(int i = 0; i < kNumNodes; i++)
|
||
|
{
|
||
|
PieNode* theCurrentPieNode = this->mArray[i];
|
||
|
if(theCurrentPieNode)
|
||
|
{
|
||
|
theCurrentPieNode->AddInputSignalForNodes(s);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bool PieNode::AttachNode(PieNode* inNode, int inAngularOffset, float inNodeXDistance, float inNodeYDistance)
|
||
|
{
|
||
|
bool theSuccess = false;
|
||
|
|
||
|
if((inAngularOffset >= 0) && (inAngularOffset < kNumNodes))
|
||
|
{
|
||
|
if(this->mArray[inAngularOffset] == NULL)
|
||
|
{
|
||
|
this->mArray[inAngularOffset] = inNode;
|
||
|
|
||
|
inNode->SetPosFromOffset(inAngularOffset, inNodeXDistance, inNodeYDistance);
|
||
|
|
||
|
//this->addChild(inNode);
|
||
|
|
||
|
//inNode->setParent(this);
|
||
|
|
||
|
inNode->mParentPieNode = this;
|
||
|
|
||
|
theSuccess = true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return theSuccess;
|
||
|
}
|
||
|
|
||
|
void PieNode::ChangeNode(int inMessageID, int inNewMessageID, const string& inNewText)
|
||
|
{
|
||
|
if(this->mMessageID == inMessageID)
|
||
|
{
|
||
|
this->mMessageID = inNewMessageID;
|
||
|
if(inNewText != "")
|
||
|
{
|
||
|
this->mBaseText = inNewText;
|
||
|
this->ComputeAndSetLocalizedText();
|
||
|
}
|
||
|
}
|
||
|
for(int i = 0; i < kNumNodes; i++)
|
||
|
{
|
||
|
PieNode* theCurrentPieNode = this->mArray[i];
|
||
|
if(theCurrentPieNode)
|
||
|
{
|
||
|
theCurrentPieNode->ChangeNode(inMessageID, inNewMessageID, inNewText);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void PieNode::ChangeNode(int inNewMessageID, const string& inNewText)
|
||
|
{
|
||
|
this->mMessageID = inNewMessageID;
|
||
|
if(inNewText != "")
|
||
|
{
|
||
|
this->mBaseText = inNewText;
|
||
|
this->ComputeAndSetLocalizedText();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
void PieNode::ComputeAndSetLocalizedText()
|
||
|
{
|
||
|
string theString = this->mBaseText;
|
||
|
|
||
|
char theLocalizedString[128];
|
||
|
if(CHudTextMessage::LocaliseTextString(theString.c_str(), theLocalizedString, 128))
|
||
|
{
|
||
|
// Remove newlines and junk
|
||
|
for(int i = 0; i < 128; i++)
|
||
|
{
|
||
|
char theCurrentChar = theLocalizedString[i];
|
||
|
if((theCurrentChar == '\n') || (theCurrentChar == '\r'))
|
||
|
{
|
||
|
theLocalizedString[i] = '\0';
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
theString = theLocalizedString;
|
||
|
}
|
||
|
|
||
|
// Save it
|
||
|
this->mLocalizedText = theString;
|
||
|
this->setText(theString.c_str());
|
||
|
}
|
||
|
|
||
|
void PieNode::DisableNodesNotInMessageList(const MessageIDList& inList)
|
||
|
{
|
||
|
this->mEnabled = false;
|
||
|
|
||
|
// If node is in list, enable it
|
||
|
MessageIDList::const_iterator theFindIter = std::find(inList.begin(), inList.end(), this->mMessageID);
|
||
|
if(theFindIter != inList.end())
|
||
|
{
|
||
|
this->mEnabled = true;
|
||
|
}
|
||
|
|
||
|
// Call recursively on children
|
||
|
for(int i = 0; i < kNumNodes; i++)
|
||
|
{
|
||
|
PieNode* theCurrentPieNode = this->mArray[i];
|
||
|
if(theCurrentPieNode)
|
||
|
{
|
||
|
theCurrentPieNode->DisableNodesNotInMessageList(inList);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void PieNode::DisableNodesWhoseChildrenAreDisabled()
|
||
|
{
|
||
|
for(int i = 0; i < kNumNodes; i++)
|
||
|
{
|
||
|
PieNode* theCurrentPieNode = this->mArray[i];
|
||
|
if(theCurrentPieNode)
|
||
|
{
|
||
|
theCurrentPieNode->DisableNodesWhoseChildrenAreDisabled();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Now disable ourself we have children and they are all disabled
|
||
|
bool theHasChildren = false;
|
||
|
bool theHasEnabledChild = false;
|
||
|
|
||
|
for(i = 0; i < kNumNodes; i++)
|
||
|
{
|
||
|
PieNode* theCurrentPieNode = this->mArray[i];
|
||
|
if(theCurrentPieNode)
|
||
|
{
|
||
|
theHasChildren = true;
|
||
|
if(theCurrentPieNode->GetEnabled())
|
||
|
{
|
||
|
theHasEnabledChild = true;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if(theHasChildren && !theHasEnabledChild)
|
||
|
{
|
||
|
this->mEnabled = false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//vgui::Color PieNode::GetColor() const
|
||
|
//{
|
||
|
// return vgui::Color(0, (this->GetDrawSelected() ? 255 : kDarkGreenColor), 0, this->GetValveAlpha());
|
||
|
// //return vgui::Color(0, kDarkGreenColor, 0, this->GetValveAlpha());
|
||
|
//}
|
||
|
|
||
|
void PieNode::getBgColor(int& r, int& g,int& b, int& a)
|
||
|
{
|
||
|
Color theColor;
|
||
|
this->getBgColor(theColor);
|
||
|
|
||
|
theColor.getColor(r, g, b, a);
|
||
|
}
|
||
|
|
||
|
void PieNode::getBgColor(Color& outColor)
|
||
|
{
|
||
|
Color theBGColor;
|
||
|
FadingImageLabel::getBgColor(theBGColor);
|
||
|
|
||
|
if(this->mEnabled)
|
||
|
{
|
||
|
if(this->mDrawSelected)
|
||
|
{
|
||
|
// Brighten color slightly
|
||
|
int theR, theG, theB, theA;
|
||
|
theBGColor.getColor(theR, theG, theB, theA);
|
||
|
|
||
|
float theScalar = 1.4f;
|
||
|
theBGColor.setColor(min(theScalar*theR, 255), min(theScalar*theG, 255), min(theScalar*theB, 255), theA);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
int theR, theG, theB, theA;
|
||
|
theBGColor.getColor(theR, theG, theB, theA);
|
||
|
|
||
|
theBGColor.setColor(kDisabledColorComponent, kDisabledColorComponent, kDisabledColorComponent, theA);
|
||
|
}
|
||
|
|
||
|
outColor = theBGColor;
|
||
|
}
|
||
|
|
||
|
// Override and provide no behavior so node visibility isn't changed. This is needed so
|
||
|
// the node can still receive input signal events and be faded in when the mouse moves
|
||
|
// over it
|
||
|
//void PieNode::FadedIn()
|
||
|
//{
|
||
|
//}
|
||
|
|
||
|
//void PieNode::FadedOut()
|
||
|
//{
|
||
|
//}
|
||
|
|
||
|
bool PieNode::GetDrawHighlighted() const
|
||
|
{
|
||
|
return this->GetDrawSelected();
|
||
|
}
|
||
|
|
||
|
bool PieNode::GetDrawSelected() const
|
||
|
{
|
||
|
return this->mDrawSelected;
|
||
|
}
|
||
|
|
||
|
bool PieNode::GetEnabled() const
|
||
|
{
|
||
|
return this->mEnabled;
|
||
|
}
|
||
|
|
||
|
bool PieNode::GetHasChild(const PieNode* inNode) const
|
||
|
{
|
||
|
bool theHasChild = false;
|
||
|
|
||
|
for(int i = 0; i < kNumNodes; i++)
|
||
|
{
|
||
|
if(this->mArray[i] == inNode)
|
||
|
{
|
||
|
theHasChild = true;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return theHasChild;
|
||
|
}
|
||
|
|
||
|
bool PieNode::GetIsAbove(const PieNode* inNode) const
|
||
|
{
|
||
|
bool thisIsAbove = false;
|
||
|
|
||
|
const PieNode* thePieNode = inNode;
|
||
|
|
||
|
while(thePieNode != NULL)
|
||
|
{
|
||
|
if(thePieNode == this)
|
||
|
{
|
||
|
thisIsAbove = true;
|
||
|
break;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
thePieNode = thePieNode->mParentPieNode;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return thisIsAbove;
|
||
|
}
|
||
|
|
||
|
int PieNode::GetMessageID() const
|
||
|
{
|
||
|
return this->mMessageID;
|
||
|
}
|
||
|
|
||
|
PieNode* PieNode::GetNodeAtAngularOffset(int inAngularOffset)
|
||
|
{
|
||
|
PieNode* thePieNode = NULL;
|
||
|
|
||
|
if((inAngularOffset >= 0) && (inAngularOffset < kNumNodes))
|
||
|
{
|
||
|
thePieNode = this->mArray[inAngularOffset];
|
||
|
}
|
||
|
|
||
|
return thePieNode;
|
||
|
}
|
||
|
|
||
|
const string& PieNode::GetNodeName() const
|
||
|
{
|
||
|
return this->mNodeName;
|
||
|
}
|
||
|
|
||
|
int PieNode::GetPointCost() const
|
||
|
{
|
||
|
return this->mPointCost;
|
||
|
}
|
||
|
|
||
|
PieNode* PieNode::GetRoot()
|
||
|
{
|
||
|
PieNode* theRoot = this;
|
||
|
|
||
|
while(theRoot->mParentPieNode != NULL)
|
||
|
{
|
||
|
theRoot = theRoot->mParentPieNode;
|
||
|
}
|
||
|
|
||
|
return theRoot;
|
||
|
}
|
||
|
|
||
|
bool PieNode::HasChildren(void) const
|
||
|
{
|
||
|
bool theHasChildren = false;
|
||
|
|
||
|
for(int i = 0; i < kNumNodes; i++)
|
||
|
{
|
||
|
PieNode* theCurrentPieNode = this->mArray[i];
|
||
|
if(theCurrentPieNode)
|
||
|
{
|
||
|
theHasChildren = true;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
return theHasChildren;
|
||
|
}
|
||
|
|
||
|
bool PieNode::HighlightNode(void)
|
||
|
{
|
||
|
bool theSuccess = false;
|
||
|
|
||
|
// Only valid if parent is NULL, or parent is already selected
|
||
|
// This prevents selecting from the edge, you must follow track
|
||
|
//if(!this->mParentPieNode || this->mParentPieNode->GetFadeState())
|
||
|
//{
|
||
|
// Get root then set all of it's children as faded out
|
||
|
PieNode* theRoot = this->GetRoot();
|
||
|
theRoot->SetNodeAndAllChildrenFadeState(false);
|
||
|
theRoot->SetFadeState(true);
|
||
|
|
||
|
// For each non-root parent, set it's fade out state to true
|
||
|
PieNode* theCurrentPieNode = this->mParentPieNode;
|
||
|
while(theCurrentPieNode && (theCurrentPieNode != theRoot))
|
||
|
{
|
||
|
theCurrentPieNode->SetFadeState(true);
|
||
|
theCurrentPieNode = theCurrentPieNode->mParentPieNode;
|
||
|
}
|
||
|
|
||
|
// Set self and adjacent children to fade in
|
||
|
// If there are no nodes below us, parent node and its adjacents (comment
|
||
|
// this out if you don't believe it looks better)
|
||
|
PieNode* theBottomFullNode = /*this->HasChildren() ?*/ this/* : this->mParentPieNode*/;
|
||
|
if(theBottomFullNode)
|
||
|
{
|
||
|
theBottomFullNode->SetNodeAndAdjacentChildrenFadeState(true);
|
||
|
}
|
||
|
|
||
|
theSuccess = true;
|
||
|
//}
|
||
|
|
||
|
this->setAsMouseCapture(false);
|
||
|
|
||
|
return theSuccess;
|
||
|
}
|
||
|
|
||
|
bool PieNode::IsAdjacentTo(const PieNode* inNode)
|
||
|
{
|
||
|
bool isAdjacent = false;
|
||
|
|
||
|
if(inNode == this->mParentPieNode)
|
||
|
{
|
||
|
isAdjacent = true;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
isAdjacent = this->GetHasChild(inNode);
|
||
|
|
||
|
// Check siblings
|
||
|
if(!isAdjacent && (this->mParentPieNode))
|
||
|
{
|
||
|
isAdjacent = this->mParentPieNode->GetHasChild(inNode);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return isAdjacent;
|
||
|
}
|
||
|
|
||
|
bool PieNode::IsChildOf(const PieNode* inNode)
|
||
|
{
|
||
|
bool isChild = false;
|
||
|
|
||
|
if(inNode && (inNode == this->mParentPieNode))
|
||
|
{
|
||
|
isChild = true;
|
||
|
}
|
||
|
|
||
|
return isChild;
|
||
|
}
|
||
|
|
||
|
bool PieNode::isVisible()
|
||
|
{
|
||
|
//return (this->GetValveAlpha() < 255);
|
||
|
return FadingImageLabel::isVisible();
|
||
|
}
|
||
|
|
||
|
// Important: Assumes both pie nodes are the same size
|
||
|
// The first coords it returns are the start of the connector, relative to this node
|
||
|
// The second coords it returns are the end of the connector (designated by inChildPieNode), relative to this node
|
||
|
bool PieNode::ComputeRelativeConnectorCoordinates(PieNode* inChildPieNode, int& theOutX0, int& theOutY0, int& theOutX1, int& theOutY1)
|
||
|
{
|
||
|
ASSERT(this != inChildPieNode);
|
||
|
|
||
|
// Check position of dest pie node relative to us
|
||
|
bool theSuccess = false;
|
||
|
|
||
|
int x0, y0;
|
||
|
this->getPos(x0, y0);
|
||
|
|
||
|
int x1, y1;
|
||
|
inChildPieNode->getPos(x1, y1);
|
||
|
|
||
|
int theFirstQuadrant, theSecondQuadrant;
|
||
|
int theDX = x1 - x0;
|
||
|
int theDY = y1 - y0;
|
||
|
|
||
|
// directly above/below or left/right
|
||
|
if((theDX == 0) || (theDY == 0))
|
||
|
{
|
||
|
if(theDY == 0)
|
||
|
{
|
||
|
// If left
|
||
|
if(x1 < x0)
|
||
|
{
|
||
|
// x0/y0 -> left edge
|
||
|
theFirstQuadrant = 2;
|
||
|
// x1/y1 -> right edge
|
||
|
theSecondQuadrant = 6;
|
||
|
}
|
||
|
// If right
|
||
|
else
|
||
|
{
|
||
|
// x0/y0 -> right edge
|
||
|
theFirstQuadrant = 6;
|
||
|
// x1/y1 -> left edge
|
||
|
theSecondQuadrant = 2;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// If below
|
||
|
if(y1 > y0)
|
||
|
{
|
||
|
// x0/y0 -> bottom edge
|
||
|
theFirstQuadrant = 4;
|
||
|
// x1/y1 -> top edge
|
||
|
theSecondQuadrant = 0;
|
||
|
}
|
||
|
// If above
|
||
|
else
|
||
|
{
|
||
|
// x0/y0 -> top edge
|
||
|
theFirstQuadrant = 0;
|
||
|
// x1/y1 -> bottom edge
|
||
|
theSecondQuadrant = 4;
|
||
|
}
|
||
|
}
|
||
|
theSuccess = true;
|
||
|
}
|
||
|
// otherwise draw from middle of nearest edge (not required yet)
|
||
|
//else
|
||
|
//{
|
||
|
// ASSERT(false);
|
||
|
//}
|
||
|
|
||
|
//ASSERT(theSuccess);
|
||
|
|
||
|
// Don't draw lines if we failed above
|
||
|
if(theSuccess)
|
||
|
{
|
||
|
// Now compute the coords relative to each
|
||
|
//this->GetCenteredCoordinatesFromQuadrant(theFirstQuadrant, 0, 0, theOutX0, theOutY0);
|
||
|
//this->GetCenteredCoordinatesFromQuadrant(theSecondQuadrant, theDX, theDY, theOutX1, theOutY1);
|
||
|
this->GetCenteredCoordinatesFromQuadrant(theFirstQuadrant, theOutX0, theOutY0);
|
||
|
//this->GetCenteredCoordinatesFromQuadrant(theSecondQuadrant, theOutX1, theOutY1);
|
||
|
inChildPieNode->GetCenteredCoordinatesFromQuadrant(theSecondQuadrant, theOutX1, theOutY1);
|
||
|
theOutX1 += theDX;
|
||
|
theOutY1 += theDY;
|
||
|
}
|
||
|
|
||
|
return theSuccess;
|
||
|
}
|
||
|
|
||
|
// inQuadrant = 0 -> top edge
|
||
|
// inQuadrant = 2 -> left edge
|
||
|
// inQuadrant = 4 -> bottom edge
|
||
|
// inQuadrant = 6 -> right edge
|
||
|
void PieNode::GetCenteredCoordinatesFromQuadrant(int inQuadrant, int& outX, int& outY)
|
||
|
{
|
||
|
int theWidth, theHeight;
|
||
|
this->getSize(theWidth, theHeight);
|
||
|
|
||
|
int theVisibleWidth, theVisibleHeight;
|
||
|
this->GetVisibleSize(theVisibleWidth, theVisibleHeight);
|
||
|
|
||
|
int theVisibleXOffset, theVisibleYOffset;
|
||
|
theVisibleXOffset = (theWidth - theVisibleWidth)/2;
|
||
|
theVisibleYOffset = (theHeight - theVisibleHeight)/2;
|
||
|
|
||
|
// Corner nodes no longer supported
|
||
|
ASSERT(inQuadrant != 1);
|
||
|
ASSERT(inQuadrant != 3);
|
||
|
ASSERT(inQuadrant != 5);
|
||
|
ASSERT(inQuadrant != 7);
|
||
|
|
||
|
switch(inQuadrant)
|
||
|
{
|
||
|
case 0:
|
||
|
outX = theWidth/2;
|
||
|
outY = theVisibleYOffset;
|
||
|
break;
|
||
|
case 2:
|
||
|
outX = theVisibleXOffset;
|
||
|
outY = theHeight/2;
|
||
|
break;
|
||
|
case 4:
|
||
|
outX = theWidth/2;
|
||
|
outY = theVisibleYOffset + theVisibleHeight;
|
||
|
break;
|
||
|
case 6:
|
||
|
outX = theVisibleXOffset + theVisibleWidth;
|
||
|
outY = theHeight/2;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
// Draw nodes
|
||
|
void PieNode::DoPaint()
|
||
|
{
|
||
|
FadingImageLabel::DoPaint();
|
||
|
}
|
||
|
|
||
|
// Draw node lines
|
||
|
void PieNode::paintBackground()
|
||
|
{
|
||
|
// For each child
|
||
|
for(int i = 0; i < kNumNodes; i++)
|
||
|
{
|
||
|
PieNode* theCurrentPieNode = this->mArray[i];
|
||
|
if(theCurrentPieNode)
|
||
|
{
|
||
|
// Draw line from us to them indicating pie node in that direction
|
||
|
if(theCurrentPieNode->GetValveAlpha() < 255)
|
||
|
{
|
||
|
// If node above us isn't highlighted, don't draw line to us
|
||
|
//if(theCurrentPieNode->HasSelectedNodeAbove() || theCurrentPieNode->HasSelectedNodeBelow())
|
||
|
|
||
|
// All those lines are getting confusing. Only draw the lines around this pie node that
|
||
|
// connect to a selected parent or selected child
|
||
|
if(theCurrentPieNode->HasSelectedNodeBelow() || this->GetDrawSelected())
|
||
|
{
|
||
|
// Find correct line to draw from center of edge of source pie node to center
|
||
|
// of edge of dest pie node
|
||
|
int theRelativeLineX0, theRelativeLineY0, theRelativeLineX1, theRelativeLineY1;
|
||
|
if(this->ComputeRelativeConnectorCoordinates(theCurrentPieNode, theRelativeLineX0, theRelativeLineY0, theRelativeLineX1, theRelativeLineY1))
|
||
|
{
|
||
|
// What color to draw the line in?
|
||
|
//vgui::Color theCurrentColor = this->GetColor();
|
||
|
vgui::Color theCurrentColor;
|
||
|
//theCurrentPieNode->getBgColor(theCurrentColor);
|
||
|
|
||
|
if(this->mEnabled)
|
||
|
{
|
||
|
theCurrentPieNode->getFgColor(theCurrentColor);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
theCurrentPieNode->getBgColor(theCurrentColor);
|
||
|
}
|
||
|
|
||
|
int r, g, b, a;
|
||
|
theCurrentColor.getColor(r, g, b, a);
|
||
|
|
||
|
// Take gamma into account
|
||
|
//r *= this->mColorBias;
|
||
|
//g *= this->mColorBias;
|
||
|
//b *= this->mColorBias;
|
||
|
a = this->GetValveAlpha();
|
||
|
|
||
|
// //if(theCurrentPieNode->GetEnabled())
|
||
|
// //{
|
||
|
// g = (theCurrentPieNode->HasSelectedNodeBelow() ? 255 : kDarkGreenColor);
|
||
|
// //g = (theCurrentPieNode->HasSelectedNodeAbove() ? 255 : kDarkGreenColor);
|
||
|
// //}
|
||
|
// // ...else this will draw lines in disabled color too, using current fade alpha
|
||
|
|
||
|
// Stupid Valve-alpha, vguiSimpleLine wants normal alpha of course
|
||
|
a = 255 - a;
|
||
|
a *= this->mColorBias;
|
||
|
|
||
|
// Only draw if child isn't invisible. Draw line
|
||
|
// relative from current node.
|
||
|
|
||
|
if(this->mConnectorSprite == 0 && (this->mConnectorSpriteName != ""))
|
||
|
{
|
||
|
this->mConnectorSprite = Safe_SPR_Load(this->mConnectorSpriteName.c_str());
|
||
|
}
|
||
|
|
||
|
if(this->mConnectorSprite > 0)
|
||
|
{
|
||
|
// Approximate alpha
|
||
|
float theAlpha = a/255.0f;
|
||
|
int theSpriteRed = theAlpha*r;
|
||
|
int theSpriteGreen = theAlpha*g;
|
||
|
int theSpriteBlue = theAlpha*b;
|
||
|
|
||
|
SPR_Set(this->mConnectorSprite, theSpriteRed, theSpriteGreen, theSpriteBlue);
|
||
|
int theLineWidth = abs(theRelativeLineX1 - theRelativeLineX0);
|
||
|
int theLineHeight = abs(theRelativeLineY1 - theRelativeLineY0);
|
||
|
|
||
|
// Use second frame if vertical
|
||
|
int theConnectorFrame = 0;
|
||
|
if(theLineHeight > 0)
|
||
|
{
|
||
|
theConnectorFrame = 1;
|
||
|
}
|
||
|
|
||
|
int theConnectorSpriteWidth = SPR_Width(this->mConnectorSprite, theConnectorFrame);
|
||
|
int theConnectorSpriteHeight = SPR_Height(this->mConnectorSprite, theConnectorFrame);
|
||
|
|
||
|
int thePieNodeWidth, thePieNodeHeight;
|
||
|
this->getContentSize(thePieNodeWidth, thePieNodeHeight);
|
||
|
|
||
|
int thePieNodeX, thePieNodeY;
|
||
|
this->getPos(thePieNodeX, thePieNodeY);
|
||
|
|
||
|
int theStartX = 0;
|
||
|
int theStartY = 0;
|
||
|
|
||
|
if(theConnectorFrame == 0)
|
||
|
{
|
||
|
int theXOffset = (theLineWidth - theConnectorSpriteWidth)/2;
|
||
|
//if(theXOffset < 0)
|
||
|
// theXOffset = 0;
|
||
|
|
||
|
theStartX = min(theRelativeLineX0, theRelativeLineX1) + theXOffset;
|
||
|
theStartY = min(theRelativeLineY0, theRelativeLineY1) - theConnectorSpriteHeight/2;
|
||
|
|
||
|
// int theScissorStartX = thePieNodeX + min(theRelativeLineX0, theRelativeLineX1) + thePieNodeWidth/2;
|
||
|
// int theScissorStartY = thePieNodeY + theStartY;
|
||
|
// int theScissorEndX = theScissorStartX + theLineWidth - thePieNodeWidth/2;
|
||
|
// int theScissorEndY = theScissorStartY + theConnectorSpriteHeight;
|
||
|
|
||
|
//vguiSimpleBox(theScissorStartX - thePieNodeX, theScissorStartY - thePieNodeY, theScissorEndX - thePieNodeX, theScissorEndY - thePieNodeY, 255, 255, 0, 128);
|
||
|
|
||
|
// SPR_EnableScissor(theScissorStartX, theScissorStartY, theLineWidth, theConnectorSpriteHeight);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
int theYOffset = (theLineHeight - theConnectorSpriteHeight)/2;
|
||
|
//if(theYOffset < 0)
|
||
|
// theYOffset = 0;
|
||
|
|
||
|
theStartX = min(theRelativeLineX0, theRelativeLineX1) - theConnectorSpriteWidth/2;
|
||
|
theStartY = min(theRelativeLineY0, theRelativeLineY1) + theYOffset;
|
||
|
|
||
|
// int theScissorStartX = thePieNodeX + theStartX;
|
||
|
// int theScissorStartY = thePieNodeY + min(theRelativeLineY0, theRelativeLineY1);
|
||
|
// int theScissorEndX = theScissorStartX + theConnectorSpriteWidth;
|
||
|
// int theScissorEndY = theScissorStartY + theLineHeight - thePieNodeHeight;
|
||
|
|
||
|
//vguiSimpleBox(theScissorStartX - thePieNodeX, theScissorStartY - thePieNodeY, theScissorEndX - thePieNodeX, theScissorEndY - thePieNodeY, 255, 255, 0, 128);
|
||
|
|
||
|
// SPR_EnableScissor(theScissorStartX, theScissorStartY, theConnectorSpriteWidth, theLineHeight);
|
||
|
}
|
||
|
|
||
|
// Take into account our position, including our parent(s), when drawing
|
||
|
// Panel* theParent = this->getParent();
|
||
|
// while(theParent)
|
||
|
// {
|
||
|
// int theX, theY;
|
||
|
// theParent->getPos(theX, theY);
|
||
|
// theStartX += theX;
|
||
|
// theStartY += theY;
|
||
|
// theParent = theParent->getParent();
|
||
|
// }
|
||
|
|
||
|
// Draw it
|
||
|
//SPR_DrawAdditive(theConnectorFrame, theStartX, theStartY, NULL);
|
||
|
SPR_DrawHoles(theConnectorFrame, theStartX, theStartY, NULL);
|
||
|
// gEngfuncs.pfnSPR_DisableScissor();
|
||
|
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
vguiSimpleLine(theRelativeLineX0, theRelativeLineY0, theRelativeLineX1, theRelativeLineY1, r, g, b, a);
|
||
|
}
|
||
|
|
||
|
vguiSimpleBox(theRelativeLineX0, theRelativeLineY0, theRelativeLineX1, theRelativeLineY1, 255, 255, 0, 128);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void PieNode::GetMaxTextSize(int& outWidth, int& outHeight)
|
||
|
{
|
||
|
int theTempWidth, theTempHeight;
|
||
|
const float kTextHeightBias = 1.5f;
|
||
|
|
||
|
// Use the text extents to dictate desired node size
|
||
|
// Bias text size a bit for usability
|
||
|
this->getTextSize(theTempWidth, theTempHeight);
|
||
|
|
||
|
theTempHeight *= kTextHeightBias;
|
||
|
if(theTempWidth > outWidth)
|
||
|
{
|
||
|
outWidth = theTempWidth;
|
||
|
}
|
||
|
if(theTempHeight > outHeight)
|
||
|
{
|
||
|
outHeight = theTempHeight;
|
||
|
}
|
||
|
|
||
|
for(int i = 0; i < kNumNodes; i++)
|
||
|
{
|
||
|
PieNode* theCurrentNode = this->mArray[i];
|
||
|
if(theCurrentNode)
|
||
|
{
|
||
|
theCurrentNode->GetMaxTextSize(theTempWidth, theTempHeight);
|
||
|
if(theTempWidth > outWidth)
|
||
|
{
|
||
|
outWidth = theTempWidth;
|
||
|
}
|
||
|
if(theTempHeight > outHeight)
|
||
|
{
|
||
|
outHeight = theTempHeight;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bool PieNode::GetSelectedNode(PieNode*& outNode)
|
||
|
{
|
||
|
bool theFoundNode = false;
|
||
|
|
||
|
if(this->mDrawSelected)
|
||
|
{
|
||
|
outNode = this;
|
||
|
theFoundNode = true;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
for(int i = 0; i < kNumNodes; i++)
|
||
|
{
|
||
|
PieNode* theCurrentNode = this->mArray[i];
|
||
|
if(theCurrentNode)
|
||
|
{
|
||
|
theFoundNode = theCurrentNode->GetSelectedNode(outNode);
|
||
|
if(theFoundNode)
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return theFoundNode;
|
||
|
}
|
||
|
|
||
|
bool PieNode::HasSelectedNodeAbove(void) const
|
||
|
{
|
||
|
bool hasSelectedNodeAbove = false;
|
||
|
|
||
|
const PieNode* thePieNode = this;
|
||
|
|
||
|
while(thePieNode != NULL)
|
||
|
{
|
||
|
if(thePieNode->GetDrawSelected())
|
||
|
{
|
||
|
hasSelectedNodeAbove = true;
|
||
|
break;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
thePieNode = thePieNode->mParentPieNode;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return hasSelectedNodeAbove;
|
||
|
}
|
||
|
|
||
|
|
||
|
bool PieNode::HasSelectedNodeBelow(void) const
|
||
|
{
|
||
|
bool hasSelectedNodeBelow = false;
|
||
|
|
||
|
// For each of our children
|
||
|
if(this->GetDrawSelected())
|
||
|
{
|
||
|
hasSelectedNodeBelow = true;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
for(int i = 0; i < kNumNodes; i++)
|
||
|
{
|
||
|
PieNode* theCurrentNode = this->mArray[i];
|
||
|
if(theCurrentNode)
|
||
|
{
|
||
|
// If child has selected node below
|
||
|
if(theCurrentNode->HasSelectedNodeBelow())
|
||
|
{
|
||
|
// break
|
||
|
hasSelectedNodeBelow = true;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return hasSelectedNodeBelow;
|
||
|
}
|
||
|
|
||
|
void PieNode::MoveTree(int inDeltaX, int inDeltaY)
|
||
|
{
|
||
|
int theCurrentX, theCurrentY;
|
||
|
this->getPos(theCurrentX, theCurrentY);
|
||
|
this->setPos(theCurrentX + inDeltaX, theCurrentY + inDeltaY);
|
||
|
|
||
|
for(int i = 0; i < kNumNodes; i++)
|
||
|
{
|
||
|
PieNode* theCurrentPieNode = this->mArray[i];
|
||
|
if(theCurrentPieNode)
|
||
|
{
|
||
|
theCurrentPieNode->MoveTree(inDeltaX, inDeltaY);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void PieNode::ResetToDefaults()
|
||
|
{
|
||
|
this->mMessageID = this->mDefaultID;
|
||
|
this->mBaseText = this->mDefaultText;
|
||
|
this->ComputeAndSetLocalizedText();
|
||
|
}
|
||
|
|
||
|
void PieNode::SetColorBias(float inBias)
|
||
|
{
|
||
|
this->mColorBias = inBias;
|
||
|
|
||
|
for(int i = 0; i < kNumNodes; i++)
|
||
|
{
|
||
|
PieNode* theCurrentPieNode = this->mArray[i];
|
||
|
if(theCurrentPieNode)
|
||
|
{
|
||
|
theCurrentPieNode->SetColorBias(this->mColorBias);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void PieNode::SetConnectorName(const string& inConnectorName)
|
||
|
{
|
||
|
string theNewSpriteName = UINameToSprite(inConnectorName, ScreenWidth());
|
||
|
if(theNewSpriteName != this->mConnectorSpriteName)
|
||
|
{
|
||
|
// Mark it to be reloaded
|
||
|
this->mConnectorSpriteName = theNewSpriteName;
|
||
|
this->mConnectorSprite = 0;
|
||
|
|
||
|
for(int i = 0; i < kNumNodes; i++)
|
||
|
{
|
||
|
PieNode* theCurrentPieNode = this->mArray[i];
|
||
|
if(theCurrentPieNode)
|
||
|
{
|
||
|
theCurrentPieNode->SetConnectorName(inConnectorName);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void PieNode::SetDefaultImage(const string& inDefaultImage)
|
||
|
{
|
||
|
this->mDefaultImage = inDefaultImage;
|
||
|
this->SetSpriteName(this->mDefaultImage);
|
||
|
}
|
||
|
|
||
|
void PieNode::SetDrawSelected(bool inDrawSelected)
|
||
|
{
|
||
|
if(this->mEnabled)
|
||
|
{
|
||
|
this->mDrawSelected = inDrawSelected;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void PieNode::SetNodeAndAllChildrenFadeState(bool inNewFadeState)
|
||
|
{
|
||
|
this->SetFadeState(inNewFadeState);
|
||
|
|
||
|
for(int i = 0; i < kNumNodes; i++)
|
||
|
{
|
||
|
PieNode* theCurrentPieNode = this->mArray[i];
|
||
|
if(theCurrentPieNode)
|
||
|
{
|
||
|
theCurrentPieNode->SetNodeAndAllChildrenFadeState(inNewFadeState);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void PieNode::SetNodeDistance(float inNewXDistance, float inNewYDistance)
|
||
|
{
|
||
|
for(int i = 0; i < kNumNodes; i++)
|
||
|
{
|
||
|
PieNode* theCurrentPieNode = this->mArray[i];
|
||
|
if(theCurrentPieNode)
|
||
|
{
|
||
|
theCurrentPieNode->SetPosFromOffset(i, inNewXDistance, inNewYDistance);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bool PieNode::SetPosFromOffset(int inAngularOffset, float inNodeXDistance, float inNodeYDistance)
|
||
|
{
|
||
|
bool theSuccess = false;
|
||
|
|
||
|
if((inAngularOffset >= 0) && (inAngularOffset < kNumNodes))
|
||
|
{
|
||
|
// 0 corresponds to north (90 degrees), 90 corresponds to west (180 degrees)
|
||
|
// Invert y because half-life uses +Y towards top of screen
|
||
|
float theDegrees = kTwoPI*(this->mDegrees[inAngularOffset]/360.0f);
|
||
|
|
||
|
// Calculate spacing in pixels from inNodeDistance. Use same number of pixels
|
||
|
// as base for both x and y offset so the spacing is even (as opposed to using
|
||
|
// inNodeDistance*ScreenHeight for the y-component)
|
||
|
float theNodeXPixelDist = inNodeXDistance*ScreenWidth();
|
||
|
int xDiff = (int)(cos(theDegrees)*theNodeXPixelDist);
|
||
|
float theNodeYPixelDist = inNodeYDistance*ScreenHeight();
|
||
|
int yDiff = -(int)(sin(theDegrees)*theNodeYPixelDist);
|
||
|
this->setPos(xDiff, yDiff);
|
||
|
|
||
|
theSuccess = true;
|
||
|
}
|
||
|
return theSuccess;
|
||
|
}
|
||
|
|
||
|
//void PieNode::SetTolerance(int inPercentage)
|
||
|
//{
|
||
|
//}
|
||
|
|
||
|
//void PieNode::setSize(int wide, int tall)
|
||
|
//{
|
||
|
// // set size for self
|
||
|
// FadingImageLabel::setSize(wide, tall);
|
||
|
//
|
||
|
// // set size for all children
|
||
|
// for(int i = 0; i < kNumNodes; i++)
|
||
|
// {
|
||
|
// PieNode* theCurrentPieNode = this->mArray[i];
|
||
|
// if(theCurrentPieNode)
|
||
|
// {
|
||
|
// theCurrentPieNode->setSize(wide, tall);
|
||
|
// }
|
||
|
// }
|
||
|
//}
|
||
|
|
||
|
void PieNode::SetSizeKeepCenter(int inWidth, int inHeight)
|
||
|
{
|
||
|
// set size for self
|
||
|
FadingImageLabel::SetSizeKeepCenter(inWidth, inHeight);
|
||
|
|
||
|
// set size for all children
|
||
|
for(int i = 0; i < kNumNodes; i++)
|
||
|
{
|
||
|
PieNode* theCurrentPieNode = this->mArray[i];
|
||
|
if(theCurrentPieNode)
|
||
|
{
|
||
|
theCurrentPieNode->SetSizeKeepCenter(inWidth, inHeight);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void PieNode::SetNodeAndAdjacentChildrenFadeState(bool inFadeState)
|
||
|
{
|
||
|
this->SetFadeState(inFadeState);
|
||
|
|
||
|
for(int i = 0; i < kNumNodes; i++)
|
||
|
{
|
||
|
PieNode* theCurrentPieNode = this->mArray[i];
|
||
|
if(theCurrentPieNode)
|
||
|
{
|
||
|
theCurrentPieNode->SetFadeState(inFadeState);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void PieNode::SetFadeState(bool inNewFadeState)
|
||
|
{
|
||
|
FadingImageLabel::SetFadeState(inNewFadeState);
|
||
|
}
|
||
|
|
||
|
void PieNode::SetVisibleSize(int inVisWidth, int inVisHeight)
|
||
|
{
|
||
|
FadingImageLabel::SetVisibleSize(inVisWidth, inVisHeight);
|
||
|
|
||
|
for(int i = 0; i < kNumNodes; i++)
|
||
|
{
|
||
|
PieNode* theCurrentPieNode = this->mArray[i];
|
||
|
if(theCurrentPieNode)
|
||
|
{
|
||
|
theCurrentPieNode->SetVisibleSize(inVisWidth, inVisHeight);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
void PieNode::SetNodeAndChildrenVisible(bool inVisibilityState)
|
||
|
{
|
||
|
this->setVisible(inVisibilityState);
|
||
|
|
||
|
for(int i = 0; i < kNumNodes; i++)
|
||
|
{
|
||
|
PieNode* theCurrentPieNode = this->mArray[i];
|
||
|
if(theCurrentPieNode)
|
||
|
{
|
||
|
theCurrentPieNode->SetNodeAndChildrenVisible(inVisibilityState);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void PieNode::Update(float theCurrentTime)
|
||
|
{
|
||
|
FadingImageLabel::Update(theCurrentTime);
|
||
|
|
||
|
// Update all children
|
||
|
for(int i = 0; i < kNumNodes; i++)
|
||
|
{
|
||
|
PieNode* theCurrentPieNode = this->mArray[i];
|
||
|
if(theCurrentPieNode)
|
||
|
{
|
||
|
theCurrentPieNode->Update(theCurrentTime);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void PieNode::UpdateMenuFromTech(const AvHTechTree& inMenuCosts, int inPurchaseLevel)
|
||
|
{
|
||
|
// Set our next text
|
||
|
//string theNewText = this->mBaseText;
|
||
|
string theNewText = this->mLocalizedText;
|
||
|
this->mPointCost = 0;
|
||
|
|
||
|
AvHMessageID theMessageID = (AvHMessageID)this->mMessageID;
|
||
|
|
||
|
// Lookup message id and append onto it if it exists
|
||
|
bool theResearchable = false;
|
||
|
int theCost = 0;
|
||
|
float theTime = 0;
|
||
|
if(inMenuCosts.GetResearchInfo(theMessageID, theResearchable, theCost, theTime))
|
||
|
{
|
||
|
// Only append point cost if it isn't a sprite and there is a point cost greater than 0
|
||
|
this->mPointCost = theCost;
|
||
|
if(this->mPointCost > 0 && (theNewText[0] != '!'))
|
||
|
{
|
||
|
char theCharArray[6];
|
||
|
sprintf(theCharArray, " (%d)", this->mPointCost);
|
||
|
theNewText += string(theCharArray);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Set it
|
||
|
this->setText(theNewText.c_str());
|
||
|
|
||
|
// Disable or enable node
|
||
|
bool theMessageIsAvailable = inMenuCosts.GetIsMessageAvailable(theMessageID);
|
||
|
|
||
|
this->mEnabled = true;
|
||
|
if((theCost >= 0) && ((this->mPointCost > inPurchaseLevel) /*|| (this->mPointCost == -1)*/ || !theResearchable || !theMessageIsAvailable))
|
||
|
{
|
||
|
this->mEnabled = false;
|
||
|
}
|
||
|
|
||
|
// do the same for our children
|
||
|
for(int i = 0; i < kNumNodes; i++)
|
||
|
{
|
||
|
PieNode* theCurrentPieNode = this->mArray[i];
|
||
|
if(theCurrentPieNode)
|
||
|
{
|
||
|
theCurrentPieNode->UpdateMenuFromTech(inMenuCosts, inPurchaseLevel);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void PieNode::VidInit(void)
|
||
|
{
|
||
|
FadingImageLabel::VidInit();
|
||
|
|
||
|
if(this->mConnectorSprite > 0)
|
||
|
{
|
||
|
// TODO: Can we unload it?
|
||
|
}
|
||
|
|
||
|
// Mark it to be reloaded next draw
|
||
|
this->mConnectorSprite = 0;
|
||
|
|
||
|
// do the same for our children
|
||
|
for(int i = 0; i < kNumNodes; i++)
|
||
|
{
|
||
|
PieNode* theCurrentPieNode = this->mArray[i];
|
||
|
if(theCurrentPieNode)
|
||
|
{
|
||
|
theCurrentPieNode->VidInit();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
PieNodeList::PieNodeList(const string& inRootName, float inDist)
|
||
|
{
|
||
|
this->mRoot = new PieNode(inRootName, 0);
|
||
|
this->mRoot->setVisible(false);
|
||
|
this->mNodeXDistance = this->mNodeYDistance = inDist;
|
||
|
}
|
||
|
|
||
|
PieNodeList::~PieNodeList()
|
||
|
{
|
||
|
delete this->mRoot;
|
||
|
}
|
||
|
|
||
|
void PieNodeList::AddInputSignalForNodes(InputSignal* s)
|
||
|
{
|
||
|
this->mRoot->AddInputSignalForNodes(s);
|
||
|
}
|
||
|
|
||
|
// Accepts input in the form of:
|
||
|
// #/#/#/#/nodename/msgID
|
||
|
bool PieNodeList::AddNode(const string& inNodeString, Font* inFont, const Color& inBGColor, const Color& inFGColor, const string& inDefaultImage)
|
||
|
{
|
||
|
bool theSuccess = false;
|
||
|
|
||
|
// Parse inNodeString to get node offsets and node name
|
||
|
StringVector theTokens;
|
||
|
string theDelimiters("/");
|
||
|
Tokenizer::split(inNodeString, theDelimiters, theTokens);
|
||
|
|
||
|
if(theTokens.size() > 1)
|
||
|
{
|
||
|
// Grab directional indicies
|
||
|
typedef vector<int> DirectionalListType;
|
||
|
DirectionalListType theDirectionalList;
|
||
|
|
||
|
// For each direction until the last, get the sub node (skip the last two nodes, should be the node name and msg id)
|
||
|
for(StringVector::iterator theStringIter = theTokens.begin(); ((theStringIter != theTokens.end()) && (theStringIter + 2 != theTokens.end())) ; theStringIter++)
|
||
|
{
|
||
|
string theCurrentToken = *theStringIter;
|
||
|
int theCurrentOffset;
|
||
|
if(sscanf(theCurrentToken.c_str(), "%d", &theCurrentOffset) == 1)
|
||
|
{
|
||
|
theDirectionalList.push_back(theCurrentOffset);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Grab node name (second to last in the list)
|
||
|
string theNodeName = *(theTokens.end() - 2);
|
||
|
|
||
|
// Grab the message id (last in list)
|
||
|
string theCurrentToken = *(theTokens.end() - 1);
|
||
|
int theMessageID;
|
||
|
if(sscanf(theCurrentToken.c_str(), "%d", &theMessageID) != 1)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
// Build the new node
|
||
|
PieNode* theCurrentNode = this->mRoot;
|
||
|
ASSERT(theCurrentNode);
|
||
|
|
||
|
for(DirectionalListType::iterator theIter = theDirectionalList.begin(); ((theIter != theDirectionalList.end()) && (theIter + 1 != theDirectionalList.end()) && (theCurrentNode != NULL)); theIter++)
|
||
|
{
|
||
|
theCurrentNode = theCurrentNode->GetNodeAtAngularOffset(*theIter);
|
||
|
}
|
||
|
|
||
|
if(theCurrentNode != NULL)
|
||
|
{
|
||
|
int theLastOffset = *(theDirectionalList.end() - 1);
|
||
|
|
||
|
// At this last node, add the new node with the last index
|
||
|
PieNode* theNewNode = new PieNode(theNodeName, theMessageID);
|
||
|
|
||
|
if(inFont)
|
||
|
{
|
||
|
theNewNode->setFont(inFont);
|
||
|
}
|
||
|
|
||
|
theNewNode->setFgColor(inFGColor);
|
||
|
theNewNode->setBgColor(inBGColor);
|
||
|
theNewNode->setAsMouseCapture(false);
|
||
|
theNewNode->SetDefaultImage(inDefaultImage);
|
||
|
|
||
|
// Set size to be the default size for the rest of the nodes
|
||
|
//int theNodeListSizeX, theNodeListSizeY;
|
||
|
//this->mRoot->getSize(theNodeListSizeX, theNodeListSizeY);
|
||
|
//theNewNode->setSize(theNodeListSizeX, theNodeListSizeY);
|
||
|
|
||
|
theCurrentNode->AttachNode(theNewNode, theLastOffset, this->mNodeXDistance, this->mNodeYDistance);
|
||
|
|
||
|
// Set x/y as it's current x/y plus the node "before" it in the pie hierarchy
|
||
|
int thePreviousMenuX, thePreviousMenuY;
|
||
|
theCurrentNode->getPos(thePreviousMenuX, thePreviousMenuY);
|
||
|
|
||
|
int theNewNodeRelX, theNewNodeRelY;
|
||
|
theNewNode->getPos(theNewNodeRelX, theNewNodeRelY);
|
||
|
theNewNode->setPos(thePreviousMenuX + theNewNodeRelX, thePreviousMenuY + theNewNodeRelY);
|
||
|
|
||
|
// TODO: Just added this.
|
||
|
theNewNode->setSize(this->mNodeXDistance*ScreenWidth(), this->mNodeYDistance*ScreenHeight());
|
||
|
|
||
|
// Set new node's parent as root node's parent
|
||
|
theNewNode->setParent(this->mRoot->getParent());
|
||
|
|
||
|
theSuccess = true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return theSuccess;
|
||
|
}
|
||
|
|
||
|
void PieNodeList::ChangeNode(int inMessageID, int inNewMessageID, const string& inNewText)
|
||
|
{
|
||
|
this->mRoot->ChangeNode(inMessageID, inNewMessageID, inNewText);
|
||
|
this->RecomputeVisibleSize();
|
||
|
}
|
||
|
|
||
|
void PieNodeList::DisableNodesNotInMessageList(const MessageIDList& inList)
|
||
|
{
|
||
|
this->mRoot->DisableNodesNotInMessageList(inList);
|
||
|
}
|
||
|
|
||
|
void PieNodeList::DisableNodesWhoseChildrenAreDisabled()
|
||
|
{
|
||
|
this->mRoot->DisableNodesWhoseChildrenAreDisabled();
|
||
|
}
|
||
|
|
||
|
PieNode* PieNodeList::GetRoot()
|
||
|
{
|
||
|
return this->mRoot;
|
||
|
}
|
||
|
|
||
|
bool PieNodeList::GetSelectedNode(PieNode*& outNode)
|
||
|
{
|
||
|
return this->mRoot->GetSelectedNode(outNode);
|
||
|
}
|
||
|
|
||
|
void PieNodeList::RecomputeVisibleSize(void)
|
||
|
{
|
||
|
int theMaxWidth = 0;
|
||
|
int theMaxHeight = 0;
|
||
|
|
||
|
// run through all pie nodes and find the max text extents of any of them
|
||
|
this->mRoot->GetMaxTextSize(theMaxWidth, theMaxHeight);
|
||
|
|
||
|
// set all sizes to accomodate that max size
|
||
|
//this->mRoot->SetSizeKeepCenter(theMaxWidth, theMaxHeight);
|
||
|
this->mRoot->SetVisibleSize(theMaxWidth, theMaxHeight);
|
||
|
}
|
||
|
|
||
|
void PieNodeList::ResetToDefaults()
|
||
|
{
|
||
|
this->mRoot->ResetToDefaults();
|
||
|
}
|
||
|
|
||
|
void PieNodeList::SetBasePosition(int x, int y, int inPieWidth, int inPieHeight)
|
||
|
{
|
||
|
// Center root in middle of pie menu, take into account image size so the image is centered.
|
||
|
// All children are relative to its parent, so they assume the same image width/height
|
||
|
//int xImage = this->mRoot->getImageWide();
|
||
|
//int yImage = this->mRoot->getImageTall();
|
||
|
//int theTextWidth, theTextHeight;
|
||
|
//this->mRoot->getTextSize(theTextWidth, theTextHeight);
|
||
|
int theWidth, theHeight;
|
||
|
this->mRoot->getSize(theWidth, theHeight);
|
||
|
|
||
|
//this->mRoot->setPos(inPieWidth/2 - xImage/2, inPieHeight/2 - yImage/2);
|
||
|
int theCurrentX, theCurrentY;
|
||
|
this->mRoot->getPos(theCurrentX, theCurrentY);
|
||
|
int theDeltaX = (inPieWidth/2 - theWidth/2) - theCurrentX;
|
||
|
int theDeltaY = (inPieHeight/2 - theHeight/2) - theCurrentY;
|
||
|
//this->mRoot->setPos(inPieWidth/2 - theWidth/2, inPieHeight/2 - theHeight/2);
|
||
|
|
||
|
// Run through child nodes and move them all by this amount
|
||
|
this->mRoot->MoveTree(theDeltaX, theDeltaY);
|
||
|
|
||
|
// Make sure the nodes are always as big as the pie so they are free to
|
||
|
// draw child nodes outside their own extents
|
||
|
//this->mRoot->setSize(inPieWidth, inPieHeight);
|
||
|
}
|
||
|
|
||
|
void PieNodeList::SetConnectorName(const string& inConnectorName)
|
||
|
{
|
||
|
this->mRoot->SetConnectorName(inConnectorName);
|
||
|
}
|
||
|
|
||
|
void PieNodeList::SetConstructionComplete()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
void PieNodeList::setParent(vgui::Panel* inPanel)
|
||
|
{
|
||
|
this->mRoot->setParent(inPanel);
|
||
|
}
|
||
|
|
||
|
void PieNodeList::SetNodeDistance(float inNewXDistance, float inNewYDistance)
|
||
|
{
|
||
|
this->mRoot->SetNodeDistance(inNewXDistance, inNewYDistance);
|
||
|
this->mNodeXDistance = inNewXDistance;
|
||
|
this->mNodeYDistance = inNewYDistance;
|
||
|
}
|
||
|
|
||
|
//bool PieNodeList::SetNodeEnabled(const string& inNodeName, bool inNewState)
|
||
|
//{
|
||
|
// return false;
|
||
|
//}
|
||
|
|
||
|
//void PieNodeList::SetRootVisible(bool inNewVisibility)
|
||
|
//{
|
||
|
// // Set just the root not visibility
|
||
|
//}
|
||
|
//
|
||
|
|
||
|
//void PieNodeList::SetTolerance(int inPercentage)
|
||
|
//{
|
||
|
// // Loop through all nodes
|
||
|
// // Call SetTolerance on each
|
||
|
//}
|
||
|
|
||
|
void PieNodeList::SetFadeState(bool inNewFadeState)
|
||
|
{
|
||
|
if(inNewFadeState)
|
||
|
{
|
||
|
this->mRoot->SetNodeAndAdjacentChildrenFadeState(true);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
this->mRoot->SetNodeAndAllChildrenFadeState(false);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void PieNodeList::SetSizeKeepCenter(int inWidth, int inHeight)
|
||
|
{
|
||
|
this->mRoot->SetSizeKeepCenter(inWidth, inHeight);
|
||
|
}
|
||
|
|
||
|
void PieNodeList::Update(float inTime)
|
||
|
{
|
||
|
this->mRoot->Update(inTime);
|
||
|
}
|
||
|
|
||
|
void PieNodeList::UpdateMenuFromTech(const AvHTechTree& inMenuCosts, int inPurchaseLevel)
|
||
|
{
|
||
|
this->mRoot->UpdateMenuFromTech(inMenuCosts, inPurchaseLevel);
|
||
|
}
|
||
|
|
||
|
void PieNodeList::VidInit()
|
||
|
{
|
||
|
this->mRoot->VidInit();
|
||
|
}
|