|
|
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
|
// |
|
|
// Purpose: |
|
|
// |
|
|
// $NoKeywords: $ |
|
|
// |
|
|
//=============================================================================// |
|
|
//========= Copyright <EFBFBD> 1996-2003, Valve LLC, All rights reserved. ============ |
|
|
// |
|
|
// The copyright to the contents herein is the property of Valve, L.L.C. |
|
|
// The contents may be used and/or copied only with the written permission of |
|
|
// Valve, L.L.C., or in accordance with the terms and conditions stipulated in |
|
|
// the agreement/contract under which the contents have been supplied. |
|
|
// |
|
|
// Purpose: |
|
|
// |
|
|
// $NoKeywords: $ |
|
|
//============================================================================= |
|
|
|
|
|
|
|
|
#include <stdio.h> |
|
|
#define PROTECTED_THINGS_DISABLE |
|
|
|
|
|
#include "utldict.h" |
|
|
|
|
|
#include <vgui/KeyCode.h> |
|
|
#include <vgui/Cursor.h> |
|
|
#include <vgui/MouseCode.h> |
|
|
#include <KeyValues.h> |
|
|
#include <vgui/IInput.h> |
|
|
#include <vgui/ISystem.h> |
|
|
#include <vgui/IVGui.h> |
|
|
#include <vgui/ISurface.h> |
|
|
|
|
|
#include <vgui_controls/BuildGroup.h> |
|
|
#include <vgui_controls/Panel.h> |
|
|
#include <vgui_controls/PHandle.h> |
|
|
#include <vgui_controls/Label.h> |
|
|
#include <vgui_controls/EditablePanel.h> |
|
|
#include <vgui_controls/MessageBox.h> |
|
|
#include "filesystem.h" |
|
|
#include "tier0/icommandline.h" |
|
|
#include "const.h" |
|
|
#include "vprof.h" |
|
|
|
|
|
#if defined( _X360 ) |
|
|
#include "xbox/xbox_win32stubs.h" |
|
|
#endif |
|
|
|
|
|
// memdbgon must be the last include file in a .cpp file!!! |
|
|
#include <tier0/memdbgon.h> |
|
|
|
|
|
ConVar vgui_cache_res_files( "vgui_cache_res_files", "1" ); |
|
|
|
|
|
using namespace vgui; |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
|
// Handle table |
|
|
//----------------------------------------------------------------------------- |
|
|
IMPLEMENT_HANDLES( BuildGroup, 20 ) |
|
|
|
|
|
CUtlDict< KeyValues* > BuildGroup::m_dictCachedResFiles; |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
|
// Purpose: Constructor |
|
|
//----------------------------------------------------------------------------- |
|
|
BuildGroup::BuildGroup(Panel *parentPanel, Panel *contextPanel) |
|
|
{ |
|
|
CONSTRUCT_HANDLE( ); |
|
|
|
|
|
_enabled=false; |
|
|
_snapX=1; |
|
|
_snapY=1; |
|
|
_cursor_sizenwse = dc_sizenwse; |
|
|
_cursor_sizenesw = dc_sizenesw; |
|
|
_cursor_sizewe = dc_sizewe; |
|
|
_cursor_sizens = dc_sizens; |
|
|
_cursor_sizeall = dc_sizeall; |
|
|
_currentPanel=null; |
|
|
_dragging=false; |
|
|
m_pResourceName=NULL; |
|
|
m_pResourcePathID = NULL; |
|
|
m_hBuildDialog=NULL; |
|
|
m_pParentPanel=parentPanel; |
|
|
for (int i=0; i<4; ++i) |
|
|
_rulerNumber[i] = NULL; |
|
|
SetContextPanel(contextPanel); |
|
|
_showRulers = false; |
|
|
|
|
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
|
// Purpose: Destructor |
|
|
//----------------------------------------------------------------------------- |
|
|
BuildGroup::~BuildGroup() |
|
|
{ |
|
|
if (m_hBuildDialog) |
|
|
delete m_hBuildDialog.Get(); |
|
|
m_hBuildDialog = NULL; |
|
|
|
|
|
delete [] m_pResourceName; |
|
|
delete [] m_pResourcePathID; |
|
|
|
|
|
for (int i=0; i <4; ++i) |
|
|
{ |
|
|
if (_rulerNumber[i]) |
|
|
{ |
|
|
delete _rulerNumber[i]; |
|
|
_rulerNumber[i]= NULL; |
|
|
} |
|
|
} |
|
|
|
|
|
DESTRUCT_HANDLE(); |
|
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
|
// Purpose: Toggles build mode on/off |
|
|
// Input : state - new state |
|
|
//----------------------------------------------------------------------------- |
|
|
void BuildGroup::SetEnabled(bool state) |
|
|
{ |
|
|
if(_enabled != state) |
|
|
{ |
|
|
_enabled = state; |
|
|
_currentPanel = NULL; |
|
|
|
|
|
if ( state ) |
|
|
{ |
|
|
ActivateBuildDialog(); |
|
|
} |
|
|
else |
|
|
{ |
|
|
// hide the build dialog |
|
|
if ( m_hBuildDialog ) |
|
|
{ |
|
|
m_hBuildDialog->OnCommand("Close"); |
|
|
} |
|
|
|
|
|
// request focus for our main panel |
|
|
m_pParentPanel->RequestFocus(); |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
|
// Purpose: Check if buildgroup is enabled |
|
|
//----------------------------------------------------------------------------- |
|
|
bool BuildGroup::IsEnabled() |
|
|
{ |
|
|
return _enabled; |
|
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
|
// Purpose: Get the list of panels that are currently selected |
|
|
//----------------------------------------------------------------------------- |
|
|
CUtlVector<PHandle> *BuildGroup::GetControlGroup() |
|
|
{ |
|
|
return &_controlGroup; |
|
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
|
// Purpose: Check if ruler display is activated |
|
|
//----------------------------------------------------------------------------- |
|
|
bool BuildGroup::HasRulersOn() |
|
|
{ |
|
|
return _showRulers; |
|
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
|
// Purpose: Toggle ruler display |
|
|
//----------------------------------------------------------------------------- |
|
|
void BuildGroup::ToggleRulerDisplay() |
|
|
{ |
|
|
_showRulers = !_showRulers; |
|
|
|
|
|
if (_rulerNumber[0] == NULL) // rulers haven't been initialized |
|
|
{ |
|
|
_rulerNumber[0] = new Label(m_pBuildContext, NULL, ""); |
|
|
_rulerNumber[1] = new Label(m_pBuildContext, NULL, ""); |
|
|
_rulerNumber[2] = new Label(m_pBuildContext, NULL, ""); |
|
|
_rulerNumber[3] = new Label(m_pBuildContext, NULL, ""); |
|
|
} |
|
|
SetRulerLabelsVisible(_showRulers); |
|
|
|
|
|
m_pBuildContext->Repaint(); |
|
|
} |
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
|
// Purpose: Tobble visibility of ruler number labels |
|
|
//----------------------------------------------------------------------------- |
|
|
void BuildGroup::SetRulerLabelsVisible(bool state) |
|
|
{ |
|
|
_rulerNumber[0]->SetVisible(state); |
|
|
_rulerNumber[1]->SetVisible(state); |
|
|
_rulerNumber[2]->SetVisible(state); |
|
|
_rulerNumber[3]->SetVisible(state); |
|
|
} |
|
|
|
|
|
void BuildGroup::ApplySchemeSettings( IScheme *pScheme ) |
|
|
{ |
|
|
DrawRulers(); |
|
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
|
// Purpose: Draw Rulers on screen if conditions are right |
|
|
//----------------------------------------------------------------------------- |
|
|
void BuildGroup::DrawRulers() |
|
|
{ |
|
|
// don't draw if visibility is off |
|
|
if (!_showRulers) |
|
|
{ |
|
|
return; |
|
|
} |
|
|
|
|
|
// no drawing if we selected the context panel |
|
|
if (m_pBuildContext == _currentPanel) |
|
|
{ |
|
|
SetRulerLabelsVisible(false); |
|
|
return; |
|
|
} |
|
|
else |
|
|
SetRulerLabelsVisible(true); |
|
|
|
|
|
int x, y, wide, tall; |
|
|
// get base panel's postition |
|
|
m_pBuildContext->GetBounds(x, y, wide, tall); |
|
|
m_pBuildContext->ScreenToLocal(x,y); |
|
|
|
|
|
int cx, cy, cwide, ctall; |
|
|
_currentPanel->GetBounds (cx, cy, cwide, ctall); |
|
|
|
|
|
surface()->PushMakeCurrent(m_pBuildContext->GetVPanel(), false); |
|
|
|
|
|
// draw rulers |
|
|
surface()->DrawSetColor(255, 255, 255, 255); // white color |
|
|
|
|
|
surface()->DrawFilledRect(0, cy, cx, cy+1); //top horiz left |
|
|
surface()->DrawFilledRect(cx+cwide, cy, wide, cy+1); //top horiz right |
|
|
|
|
|
surface()->DrawFilledRect(0, cy+ctall-1, cx, cy+ctall); //bottom horiz left |
|
|
surface()->DrawFilledRect(cx+cwide, cy+ctall-1, wide, cy+ctall); //bottom horiz right |
|
|
|
|
|
surface()->DrawFilledRect(cx,0,cx+1,cy); //top vert left |
|
|
surface()->DrawFilledRect(cx+cwide-1,0, cx+cwide, cy); //top vert right |
|
|
|
|
|
surface()->DrawFilledRect(cx,cy+ctall, cx+1, tall); //bottom vert left |
|
|
surface()->DrawFilledRect(cx+cwide-1, cy+ctall, cx+cwide, tall); //bottom vert right |
|
|
|
|
|
surface()->PopMakeCurrent(m_pBuildContext->GetVPanel()); |
|
|
|
|
|
// now let's put numbers with the rulers |
|
|
char textstring[20]; |
|
|
Q_snprintf (textstring, sizeof( textstring ), "%d", cx); |
|
|
_rulerNumber[0]->SetText(textstring); |
|
|
int twide, ttall; |
|
|
_rulerNumber[0]->GetContentSize(twide,ttall); |
|
|
_rulerNumber[0]->SetSize(twide,ttall); |
|
|
_rulerNumber[0]->SetPos(cx/2-twide/2, cy-ttall+3); |
|
|
|
|
|
Q_snprintf (textstring, sizeof( textstring ), "%d", cy); |
|
|
_rulerNumber[1]->SetText(textstring); |
|
|
_rulerNumber[1]->GetContentSize(twide,ttall); |
|
|
_rulerNumber[1]->SetSize(twide,ttall); |
|
|
_rulerNumber[1]->GetSize(twide,ttall); |
|
|
_rulerNumber[1]->SetPos(cx-twide + 3, cy/2-ttall/2); |
|
|
|
|
|
Q_snprintf (textstring, sizeof( textstring ), "%d", cy); |
|
|
_rulerNumber[2]->SetText(textstring); |
|
|
_rulerNumber[2]->GetContentSize(twide,ttall); |
|
|
_rulerNumber[2]->SetSize(twide,ttall); |
|
|
_rulerNumber[2]->SetPos(cx+cwide+(wide-cx-cwide)/2 - twide/2, cy+ctall-3); |
|
|
|
|
|
Q_snprintf (textstring, sizeof( textstring ), "%d", cy); |
|
|
_rulerNumber[3]->SetText(textstring); |
|
|
_rulerNumber[3]->GetContentSize(twide,ttall); |
|
|
_rulerNumber[3]->SetSize(twide,ttall); |
|
|
_rulerNumber[3]->SetPos(cx+cwide, cy+ctall+(tall-cy-ctall)/2 - ttall/2); |
|
|
|
|
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
|
// Purpose: respond to cursor movments |
|
|
//----------------------------------------------------------------------------- |
|
|
bool BuildGroup::CursorMoved(int x, int y, Panel *panel) |
|
|
{ |
|
|
Assert(panel); |
|
|
|
|
|
if ( !m_hBuildDialog.Get() ) |
|
|
{ |
|
|
if ( panel->GetParent() ) |
|
|
{ |
|
|
EditablePanel *ep = dynamic_cast< EditablePanel * >( panel->GetParent() ); |
|
|
if ( ep ) |
|
|
{ |
|
|
BuildGroup *bg = ep->GetBuildGroup(); |
|
|
if ( bg && bg != this ) |
|
|
{ |
|
|
bg->CursorMoved( x, y, panel ); |
|
|
} |
|
|
} |
|
|
} |
|
|
return false; |
|
|
} |
|
|
|
|
|
// no moving uneditable panels |
|
|
// commented out because this has issues with panels moving |
|
|
// to front and obscuring other panels |
|
|
//if (!panel->IsBuildModeEditable()) |
|
|
// return; |
|
|
|
|
|
if (_dragging) |
|
|
{ |
|
|
input()->GetCursorPos(x, y); |
|
|
|
|
|
if (_dragMouseCode == MOUSE_RIGHT) |
|
|
{ |
|
|
int newW = max( 1, _dragStartPanelSize[ 0 ] + x - _dragStartCursorPos[0] ); |
|
|
int newH = max( 1, _dragStartPanelSize[ 1 ] + y - _dragStartCursorPos[1] ); |
|
|
|
|
|
bool shift = ( input()->IsKeyDown(KEY_LSHIFT) || input()->IsKeyDown(KEY_RSHIFT) ); |
|
|
bool ctrl = ( input()->IsKeyDown(KEY_LCONTROL) || input()->IsKeyDown(KEY_RCONTROL) ); |
|
|
|
|
|
if ( shift ) |
|
|
{ |
|
|
newW = _dragStartPanelSize[ 0 ]; |
|
|
} |
|
|
if ( ctrl ) |
|
|
{ |
|
|
newH = _dragStartPanelSize[ 1 ]; |
|
|
} |
|
|
|
|
|
panel->SetSize( newW, newH ); |
|
|
ApplySnap(panel); |
|
|
} |
|
|
else |
|
|
{ |
|
|
for (int i=0; i < _controlGroup.Count(); ++i) |
|
|
{ |
|
|
// now fix offset of member panels with respect to the one we are dragging |
|
|
Panel *groupMember = _controlGroup[i].Get(); |
|
|
groupMember->SetPos(_dragStartPanelPos[0] + _groupDeltaX[i] +(x-_dragStartCursorPos[0]), _dragStartPanelPos[1] + _groupDeltaY[i] +(y-_dragStartCursorPos[1])); |
|
|
ApplySnap(groupMember); |
|
|
} |
|
|
} |
|
|
|
|
|
// update the build dialog |
|
|
if (m_hBuildDialog) |
|
|
{ |
|
|
KeyValues *keyval = new KeyValues("UpdateControlData"); |
|
|
keyval->SetPtr("panel", GetCurrentPanel()); |
|
|
ivgui()->PostMessage(m_hBuildDialog->GetVPanel(), keyval, NULL); |
|
|
|
|
|
keyval = new KeyValues("EnableSaveButton"); |
|
|
ivgui()->PostMessage(m_hBuildDialog->GetVPanel(), keyval, NULL); |
|
|
} |
|
|
|
|
|
panel->Repaint(); |
|
|
panel->CallParentFunction(new KeyValues("Repaint")); |
|
|
} |
|
|
|
|
|
return true; |
|
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
|
// Purpose: |
|
|
//----------------------------------------------------------------------------- |
|
|
bool BuildGroup::MousePressed(MouseCode code, Panel *panel) |
|
|
{ |
|
|
Assert(panel); |
|
|
|
|
|
if ( !m_hBuildDialog.Get() ) |
|
|
{ |
|
|
if ( panel->GetParent() ) |
|
|
{ |
|
|
EditablePanel *ep = dynamic_cast< EditablePanel * >( panel->GetParent() ); |
|
|
if ( ep ) |
|
|
{ |
|
|
BuildGroup *bg = ep->GetBuildGroup(); |
|
|
if ( bg && bg != this ) |
|
|
{ |
|
|
bg->MousePressed( code, panel ); |
|
|
} |
|
|
} |
|
|
} |
|
|
return false; |
|
|
} |
|
|
|
|
|
// if people click on the base build dialog panel. |
|
|
if (panel == m_hBuildDialog) |
|
|
{ |
|
|
// hide the click menu if its up |
|
|
ivgui()->PostMessage(m_hBuildDialog->GetVPanel(), new KeyValues("HideNewControlMenu"), NULL); |
|
|
return true; |
|
|
} |
|
|
|
|
|
// don't select unnamed items |
|
|
if (strlen(panel->GetName()) < 1) |
|
|
return true; |
|
|
|
|
|
bool shift = ( input()->IsKeyDown(KEY_LSHIFT) || input()->IsKeyDown(KEY_RSHIFT) ); |
|
|
if (!shift) |
|
|
{ |
|
|
_controlGroup.RemoveAll(); |
|
|
} |
|
|
|
|
|
// Show new ctrl menu if they click on the bg (not on a subcontrol) |
|
|
if ( code == MOUSE_RIGHT && panel == GetContextPanel()) |
|
|
{ |
|
|
// trigger a drop down menu to create new controls |
|
|
ivgui()->PostMessage (m_hBuildDialog->GetVPanel(), new KeyValues("ShowNewControlMenu"), NULL); |
|
|
} |
|
|
else |
|
|
{ |
|
|
// don't respond if we click on ruler numbers |
|
|
if (_showRulers) // rulers are visible |
|
|
{ |
|
|
for ( int i=0; i < 4; i++) |
|
|
{ |
|
|
if ( panel == _rulerNumber[i]) |
|
|
return true; |
|
|
} |
|
|
} |
|
|
|
|
|
_dragging = true; |
|
|
_dragMouseCode = code; |
|
|
ivgui()->PostMessage(m_hBuildDialog->GetVPanel(), new KeyValues("HideNewControlMenu"), NULL); |
|
|
|
|
|
int x, y; |
|
|
input()->GetCursorPos(x, y); |
|
|
|
|
|
_dragStartCursorPos[0] = x; |
|
|
_dragStartCursorPos[1] = y; |
|
|
|
|
|
|
|
|
input()->SetMouseCapture(panel->GetVPanel()); |
|
|
|
|
|
_groupDeltaX.RemoveAll(); |
|
|
_groupDeltaY.RemoveAll(); |
|
|
|
|
|
// basepanel is the panel that all the deltas will be calculated from. |
|
|
// it is the last panel we clicked in because if we move the panels as a group |
|
|
// it would be from that one |
|
|
Panel *basePanel = NULL; |
|
|
// find the panel we clicked in, that is the base panel |
|
|
// it might already be in the group |
|
|
for (int i=0; i< _controlGroup.Count(); ++i) |
|
|
{ |
|
|
if (panel == _controlGroup[i].Get()) |
|
|
{ |
|
|
basePanel = panel; |
|
|
break; |
|
|
} |
|
|
} |
|
|
|
|
|
// if its not in the group we just added this panel. get it in the group |
|
|
if (basePanel == NULL) |
|
|
{ |
|
|
PHandle temp; |
|
|
temp = panel; |
|
|
_controlGroup.AddToTail(temp); |
|
|
basePanel = panel; |
|
|
} |
|
|
|
|
|
basePanel->GetPos(x,y); |
|
|
_dragStartPanelPos[0]=x; |
|
|
_dragStartPanelPos[1]=y; |
|
|
|
|
|
basePanel->GetSize( _dragStartPanelSize[ 0 ], _dragStartPanelSize[ 1 ] ); |
|
|
|
|
|
// figure out the deltas of the other panels from the base panel |
|
|
for (int i=0; i<_controlGroup.Count(); ++i) |
|
|
{ |
|
|
int cx, cy; |
|
|
_controlGroup[i].Get()->GetPos(cx, cy); |
|
|
_groupDeltaX.AddToTail(cx - x); |
|
|
_groupDeltaY.AddToTail(cy - y); |
|
|
} |
|
|
|
|
|
// if this panel wasn't already selected update the buildmode dialog controls to show its info |
|
|
if(_currentPanel != panel) |
|
|
{ |
|
|
_currentPanel = panel; |
|
|
|
|
|
if ( m_hBuildDialog ) |
|
|
{ |
|
|
// think this is taken care of by SetActiveControl. |
|
|
//ivgui()->PostMessage(m_hBuildDialog->GetVPanel(), new KeyValues("ApplyDataToControls"), NULL); |
|
|
|
|
|
KeyValues *keyval = new KeyValues("SetActiveControl"); |
|
|
keyval->SetPtr("PanelPtr", GetCurrentPanel()); |
|
|
ivgui()->PostMessage(m_hBuildDialog->GetVPanel(), keyval, NULL); |
|
|
} |
|
|
} |
|
|
|
|
|
// store undo information upon panel selection. |
|
|
ivgui()->PostMessage(m_hBuildDialog->GetVPanel(), new KeyValues("StoreUndo"), NULL); |
|
|
|
|
|
panel->RequestFocus(); |
|
|
} |
|
|
|
|
|
return true; |
|
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
|
// Purpose: |
|
|
//----------------------------------------------------------------------------- |
|
|
bool BuildGroup::MouseReleased(MouseCode code, Panel *panel) |
|
|
{ |
|
|
if ( !m_hBuildDialog.Get() ) |
|
|
{ |
|
|
if ( panel->GetParent() ) |
|
|
{ |
|
|
EditablePanel *ep = dynamic_cast< EditablePanel * >( panel->GetParent() ); |
|
|
if ( ep ) |
|
|
{ |
|
|
BuildGroup *bg = ep->GetBuildGroup(); |
|
|
if ( bg && bg != this ) |
|
|
{ |
|
|
bg->MouseReleased( code, panel ); |
|
|
} |
|
|
} |
|
|
} |
|
|
return false; |
|
|
} |
|
|
|
|
|
Assert(panel); |
|
|
|
|
|
_dragging=false; |
|
|
input()->SetMouseCapture(null); |
|
|
return true; |
|
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
|
// Purpose: |
|
|
//----------------------------------------------------------------------------- |
|
|
bool BuildGroup::MouseDoublePressed(MouseCode code, Panel *panel) |
|
|
{ |
|
|
Assert(panel); |
|
|
return MousePressed( code, panel ); |
|
|
} |
|
|
|
|
|
bool BuildGroup::KeyTyped( wchar_t unichar, Panel *panel ) |
|
|
{ |
|
|
if ( !m_hBuildDialog.Get() ) |
|
|
{ |
|
|
if ( panel->GetParent() ) |
|
|
{ |
|
|
EditablePanel *ep = dynamic_cast< EditablePanel * >( panel->GetParent() ); |
|
|
if ( ep ) |
|
|
{ |
|
|
BuildGroup *bg = ep->GetBuildGroup(); |
|
|
if ( bg && bg != this ) |
|
|
{ |
|
|
bg->KeyTyped( unichar, panel ); |
|
|
} |
|
|
} |
|
|
} |
|
|
return false; |
|
|
} |
|
|
|
|
|
return true; |
|
|
} |
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
|
// Purpose: |
|
|
//----------------------------------------------------------------------------- |
|
|
bool BuildGroup::KeyCodeTyped(KeyCode code, Panel *panel) |
|
|
{ |
|
|
if ( !m_hBuildDialog.Get() ) |
|
|
{ |
|
|
if ( panel->GetParent() ) |
|
|
{ |
|
|
EditablePanel *ep = dynamic_cast< EditablePanel * >( panel->GetParent() ); |
|
|
if ( ep ) |
|
|
{ |
|
|
BuildGroup *bg = ep->GetBuildGroup(); |
|
|
if ( bg && bg != this ) |
|
|
{ |
|
|
bg->KeyCodeTyped( code, panel ); |
|
|
} |
|
|
} |
|
|
} |
|
|
return false; |
|
|
} |
|
|
|
|
|
Assert(panel); |
|
|
|
|
|
int dx=0; |
|
|
int dy=0; |
|
|
|
|
|
bool shift = ( input()->IsKeyDown(KEY_LSHIFT) || input()->IsKeyDown(KEY_RSHIFT) ); |
|
|
bool ctrl = ( input()->IsKeyDown(KEY_LCONTROL) || input()->IsKeyDown(KEY_RCONTROL) ); |
|
|
bool alt = (input()->IsKeyDown(KEY_LALT) || input()->IsKeyDown(KEY_RALT)); |
|
|
|
|
|
|
|
|
if ( ctrl && shift && alt && code == KEY_B) |
|
|
{ |
|
|
// enable build mode |
|
|
EditablePanel *ep = dynamic_cast< EditablePanel * >( panel ); |
|
|
if ( ep ) |
|
|
{ |
|
|
ep->ActivateBuildMode(); |
|
|
} |
|
|
return true; |
|
|
} |
|
|
|
|
|
switch (code) |
|
|
{ |
|
|
case KEY_LEFT: |
|
|
{ |
|
|
dx-=_snapX; |
|
|
break; |
|
|
} |
|
|
case KEY_RIGHT: |
|
|
{ |
|
|
dx+=_snapX; |
|
|
break; |
|
|
} |
|
|
case KEY_UP: |
|
|
{ |
|
|
dy-=_snapY; |
|
|
break; |
|
|
} |
|
|
case KEY_DOWN: |
|
|
{ |
|
|
dy+=_snapY; |
|
|
break; |
|
|
} |
|
|
case KEY_DELETE: |
|
|
{ |
|
|
// delete the panel we have selected |
|
|
ivgui()->PostMessage (m_hBuildDialog->GetVPanel(), new KeyValues ("DeletePanel"), NULL); |
|
|
break; |
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
if (ctrl) |
|
|
{ |
|
|
switch (code) |
|
|
{ |
|
|
case KEY_Z: |
|
|
{ |
|
|
ivgui()->PostMessage(m_hBuildDialog->GetVPanel(), new KeyValues("Undo"), NULL); |
|
|
break; |
|
|
} |
|
|
|
|
|
case KEY_C: |
|
|
{ |
|
|
ivgui()->PostMessage(m_hBuildDialog->GetVPanel(), new KeyValues("Copy"), NULL); |
|
|
break; |
|
|
} |
|
|
case KEY_V: |
|
|
{ |
|
|
ivgui()->PostMessage(m_hBuildDialog->GetVPanel(), new KeyValues("Paste"), NULL); |
|
|
break; |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
if(dx||dy) |
|
|
{ |
|
|
//TODO: make this stuff actually snap |
|
|
|
|
|
int x,y,wide,tall; |
|
|
|
|
|
panel->GetBounds(x,y,wide,tall); |
|
|
|
|
|
if(shift) |
|
|
{ |
|
|
panel->SetSize(wide+dx,tall+dy); |
|
|
} |
|
|
else |
|
|
{ |
|
|
panel->SetPos(x+dx,y+dy); |
|
|
} |
|
|
|
|
|
ApplySnap(panel); |
|
|
|
|
|
panel->Repaint(); |
|
|
if (panel->GetVParent() != 0) |
|
|
{ |
|
|
panel->PostMessage(panel->GetVParent(), new KeyValues("Repaint")); |
|
|
} |
|
|
|
|
|
|
|
|
// update the build dialog |
|
|
if (m_hBuildDialog) |
|
|
{ |
|
|
// post that it's active |
|
|
KeyValues *keyval = new KeyValues("SetActiveControl"); |
|
|
keyval->SetPtr("PanelPtr", GetCurrentPanel()); |
|
|
ivgui()->PostMessage(m_hBuildDialog->GetVPanel(), keyval, NULL); |
|
|
|
|
|
// post that it's been changed |
|
|
ivgui()->PostMessage(m_hBuildDialog->GetVPanel(), new KeyValues("PanelMoved"), NULL); |
|
|
} |
|
|
} |
|
|
|
|
|
// If holding key while dragging, simulate moving cursor so shift/ctrl key changes take effect |
|
|
if ( _dragging && panel != GetContextPanel() ) |
|
|
{ |
|
|
int x, y; |
|
|
input()->GetCursorPos( x, y ); |
|
|
CursorMoved( x, y, panel ); |
|
|
} |
|
|
|
|
|
return true; |
|
|
} |
|
|
|
|
|
bool BuildGroup::KeyCodeReleased(KeyCode code, Panel *panel ) |
|
|
{ |
|
|
if ( !m_hBuildDialog.Get() ) |
|
|
{ |
|
|
if ( panel->GetParent() ) |
|
|
{ |
|
|
EditablePanel *ep = dynamic_cast< EditablePanel * >( panel->GetParent() ); |
|
|
if ( ep ) |
|
|
{ |
|
|
BuildGroup *bg = ep->GetBuildGroup(); |
|
|
if ( bg && bg != this ) |
|
|
{ |
|
|
bg->KeyCodeTyped( code, panel ); |
|
|
} |
|
|
} |
|
|
} |
|
|
return false; |
|
|
} |
|
|
|
|
|
// If holding key while dragging, simulate moving cursor so shift/ctrl key changes take effect |
|
|
if ( _dragging && panel != GetContextPanel() ) |
|
|
{ |
|
|
int x, y; |
|
|
input()->GetCursorPos( x, y ); |
|
|
CursorMoved( x, y, panel ); |
|
|
} |
|
|
|
|
|
return true; |
|
|
} |
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
|
// Purpose: Searches for a BuildModeDialog in the hierarchy |
|
|
//----------------------------------------------------------------------------- |
|
|
Panel *BuildGroup::CreateBuildDialog( void ) |
|
|
{ |
|
|
// request the panel |
|
|
Panel *buildDialog = NULL; |
|
|
KeyValues *data = new KeyValues("BuildDialog"); |
|
|
data->SetPtr("BuildGroupPtr", this); |
|
|
if (m_pBuildContext->RequestInfo(data)) |
|
|
{ |
|
|
buildDialog = (Panel *)data->GetPtr("PanelPtr"); |
|
|
} |
|
|
|
|
|
// initialize the build dialog if found |
|
|
if ( buildDialog ) |
|
|
{ |
|
|
input()->ReleaseAppModalSurface(); |
|
|
} |
|
|
|
|
|
return buildDialog; |
|
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
|
// Purpose: Activates the build mode settings dialog |
|
|
//----------------------------------------------------------------------------- |
|
|
void BuildGroup::ActivateBuildDialog( void ) |
|
|
{ |
|
|
// create the build mode dialog first time through |
|
|
if (!m_hBuildDialog.Get()) |
|
|
{ |
|
|
m_hBuildDialog = CreateBuildDialog(); |
|
|
|
|
|
if (!m_hBuildDialog.Get()) |
|
|
return; |
|
|
} |
|
|
|
|
|
m_hBuildDialog->SetVisible( true ); |
|
|
|
|
|
// send a message to set the initial dialog controls info |
|
|
_currentPanel = m_pParentPanel; |
|
|
KeyValues *keyval = new KeyValues("SetActiveControl"); |
|
|
keyval->SetPtr("PanelPtr", GetCurrentPanel()); |
|
|
ivgui()->PostMessage(m_hBuildDialog->GetVPanel(), keyval, NULL); |
|
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
|
// Purpose: |
|
|
//----------------------------------------------------------------------------- |
|
|
HCursor BuildGroup::GetCursor(Panel *panel) |
|
|
{ |
|
|
Assert(panel); |
|
|
|
|
|
int x,y,wide,tall; |
|
|
input()->GetCursorPos(x,y); |
|
|
panel->ScreenToLocal(x,y); |
|
|
panel->GetSize(wide,tall); |
|
|
|
|
|
if(x < 2) |
|
|
{ |
|
|
if(y < 4) |
|
|
{ |
|
|
return _cursor_sizenwse; |
|
|
} |
|
|
else |
|
|
if(y<(tall-4)) |
|
|
{ |
|
|
return _cursor_sizewe; |
|
|
} |
|
|
else |
|
|
{ |
|
|
return _cursor_sizenesw; |
|
|
} |
|
|
} |
|
|
|
|
|
return _cursor_sizeall; |
|
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
|
// Purpose: |
|
|
//----------------------------------------------------------------------------- |
|
|
void BuildGroup::ApplySnap(Panel *panel) |
|
|
{ |
|
|
Assert(panel); |
|
|
|
|
|
int x,y,wide,tall; |
|
|
panel->GetBounds(x,y,wide,tall); |
|
|
|
|
|
x=(x/_snapX)*_snapX; |
|
|
y=(y/_snapY)*_snapY; |
|
|
panel->SetPos(x,y); |
|
|
|
|
|
int xx,yy; |
|
|
xx=x+wide; |
|
|
yy=y+tall; |
|
|
|
|
|
xx=(xx/_snapX)*_snapX; |
|
|
yy=(yy/_snapY)*_snapY; |
|
|
panel->SetSize(xx-x,yy-y); |
|
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
|
// Purpose: Return the currently selected panel |
|
|
//----------------------------------------------------------------------------- |
|
|
Panel *BuildGroup::GetCurrentPanel() |
|
|
{ |
|
|
return _currentPanel; |
|
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
|
// Purpose: Add panel the list of panels that are in the build group |
|
|
//----------------------------------------------------------------------------- |
|
|
void BuildGroup::PanelAdded(Panel *panel) |
|
|
{ |
|
|
Assert(panel); |
|
|
|
|
|
PHandle temp; |
|
|
temp = panel; |
|
|
int c = _panelDar.Count(); |
|
|
for ( int i = 0; i < c; ++i ) |
|
|
{ |
|
|
if ( _panelDar[ i ] == temp ) |
|
|
{ |
|
|
return; |
|
|
} |
|
|
} |
|
|
_panelDar.AddToTail(temp); |
|
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
|
// Purpose: loads the control settings from file |
|
|
//----------------------------------------------------------------------------- |
|
|
void BuildGroup::LoadControlSettings(const char *controlResourceName, const char *pathID, KeyValues *pPreloadedKeyValues, KeyValues *pConditions) |
|
|
{ |
|
|
// make sure the file is registered |
|
|
RegisterControlSettingsFile(controlResourceName, pathID); |
|
|
|
|
|
// Use the keyvalues they passed in or load them. |
|
|
KeyValues *rDat = pPreloadedKeyValues; |
|
|
|
|
|
bool bUsePrecaching = vgui_cache_res_files.GetBool(); |
|
|
bool bUsingPrecachedSourceKeys = false; |
|
|
bool bShouldCacheKeys = true; |
|
|
bool bDeleteKeys = false; |
|
|
|
|
|
while ( !rDat ) |
|
|
{ |
|
|
if ( bUsePrecaching ) |
|
|
{ |
|
|
int nIndex = m_dictCachedResFiles.Find( controlResourceName ); |
|
|
if ( nIndex != m_dictCachedResFiles.InvalidIndex() ) |
|
|
{ |
|
|
rDat = m_dictCachedResFiles[nIndex]; |
|
|
bUsingPrecachedSourceKeys = true; |
|
|
bDeleteKeys = false; |
|
|
bShouldCacheKeys = false; |
|
|
break; |
|
|
} |
|
|
} |
|
|
|
|
|
// load the resource data from the file |
|
|
rDat = new KeyValues( controlResourceName ); |
|
|
|
|
|
// check the skins directory first, if an explicit pathID hasn't been set |
|
|
bool bSuccess = false; |
|
|
if ( !pathID ) |
|
|
{ |
|
|
bSuccess = rDat->LoadFromFile( g_pFullFileSystem, controlResourceName, "SKIN" ); |
|
|
} |
|
|
|
|
|
if ( !V_stricmp( CommandLine()->ParmValue( "-game", "hl2" ), "tf" ) ) |
|
|
{ |
|
|
if ( !bSuccess ) |
|
|
{ |
|
|
bSuccess = rDat->LoadFromFile( g_pFullFileSystem, controlResourceName, "custom_mod" ); |
|
|
} |
|
|
if ( !bSuccess ) |
|
|
{ |
|
|
bSuccess = rDat->LoadFromFile( g_pFullFileSystem, controlResourceName, "vgui" ); |
|
|
} |
|
|
if ( !bSuccess ) |
|
|
{ |
|
|
bSuccess = rDat->LoadFromFile( g_pFullFileSystem, controlResourceName, "BSP" ); |
|
|
} |
|
|
// only allow to load loose files when using insecure mode |
|
|
if ( !bSuccess && CommandLine()->FindParm( "-insecure" ) ) |
|
|
{ |
|
|
bSuccess = rDat->LoadFromFile( g_pFullFileSystem, controlResourceName, pathID ); |
|
|
} |
|
|
} |
|
|
else |
|
|
{ |
|
|
if ( !bSuccess ) |
|
|
{ |
|
|
bSuccess = rDat->LoadFromFile( g_pFullFileSystem, controlResourceName, pathID ); |
|
|
} |
|
|
} |
|
|
|
|
|
if ( bSuccess ) |
|
|
{ |
|
|
if ( IsX360() ) |
|
|
{ |
|
|
rDat->ProcessResolutionKeys( surface()->GetResolutionKey() ); |
|
|
} |
|
|
if ( IsPC() ) |
|
|
{ |
|
|
ConVarRef cl_hud_minmode( "cl_hud_minmode", true ); |
|
|
if ( cl_hud_minmode.IsValid() && cl_hud_minmode.GetBool() ) |
|
|
{ |
|
|
rDat->ProcessResolutionKeys( "_minmode" ); |
|
|
} |
|
|
} |
|
|
bDeleteKeys = true; |
|
|
bShouldCacheKeys = true; |
|
|
} |
|
|
else |
|
|
{ |
|
|
Warning( "Failed to load %s\n", controlResourceName ); |
|
|
} |
|
|
break; |
|
|
} |
|
|
|
|
|
if ( pConditions && pConditions->GetFirstSubKey() ) |
|
|
{ |
|
|
if ( bUsingPrecachedSourceKeys ) |
|
|
{ |
|
|
// ProcessConditionalKeys modifies the KVs in place. We dont want |
|
|
// that to happen to our cached keys |
|
|
rDat = rDat->MakeCopy(); |
|
|
bDeleteKeys = true; |
|
|
} |
|
|
|
|
|
ProcessConditionalKeys(rDat, pConditions); |
|
|
bShouldCacheKeys = false; |
|
|
} |
|
|
|
|
|
// save off the resource name |
|
|
delete [] m_pResourceName; |
|
|
m_pResourceName = new char[strlen(controlResourceName) + 1]; |
|
|
strcpy(m_pResourceName, controlResourceName); |
|
|
|
|
|
if (pathID) |
|
|
{ |
|
|
delete [] m_pResourcePathID; |
|
|
m_pResourcePathID = new char[strlen(pathID) + 1]; |
|
|
strcpy(m_pResourcePathID, pathID); |
|
|
} |
|
|
|
|
|
// delete any controls not in both files |
|
|
DeleteAllControlsCreatedByControlSettingsFile(); |
|
|
|
|
|
// loop through the resource data sticking info into controls |
|
|
ApplySettings(rDat); |
|
|
|
|
|
if (m_pParentPanel) |
|
|
{ |
|
|
m_pParentPanel->InvalidateLayout(); |
|
|
m_pParentPanel->Repaint(); |
|
|
} |
|
|
|
|
|
if ( bShouldCacheKeys && bUsePrecaching ) |
|
|
{ |
|
|
Assert( m_dictCachedResFiles.Find( controlResourceName ) == m_dictCachedResFiles.InvalidIndex() ); |
|
|
m_dictCachedResFiles.Insert( controlResourceName, rDat ); |
|
|
} |
|
|
else if ( bDeleteKeys ) |
|
|
{ |
|
|
Assert( m_dictCachedResFiles.Find( controlResourceName ) != m_dictCachedResFiles.InvalidIndex() || pConditions || pPreloadedKeyValues ); |
|
|
rDat->deleteThis(); |
|
|
} |
|
|
} |
|
|
|
|
|
void BuildGroup::ProcessConditionalKeys( KeyValues *pData, KeyValues *pConditions ) |
|
|
{ |
|
|
// for each condition, look for it in keys |
|
|
// if its a positive condition, promote all of its children, replacing values |
|
|
|
|
|
if ( pData ) |
|
|
{ |
|
|
KeyValues *pSubKey = pData->GetFirstSubKey(); |
|
|
if ( !pSubKey ) |
|
|
{ |
|
|
// not a block |
|
|
return; |
|
|
} |
|
|
|
|
|
for ( ; pSubKey != NULL; pSubKey = pSubKey->GetNextKey() ) |
|
|
{ |
|
|
// recursively descend each sub block |
|
|
ProcessConditionalKeys( pSubKey, pConditions ); |
|
|
|
|
|
KeyValues *pCondition = pConditions->GetFirstSubKey(); |
|
|
for ( ; pCondition != NULL; pCondition = pCondition->GetNextKey() ) |
|
|
{ |
|
|
// if we match any conditions in this sub block, copy up |
|
|
KeyValues *pConditionBlock = pSubKey->FindKey( pCondition->GetName() ); |
|
|
if ( pConditionBlock ) |
|
|
{ |
|
|
KeyValues *pOverridingKey; |
|
|
for ( pOverridingKey = pConditionBlock->GetFirstSubKey(); pOverridingKey != NULL; pOverridingKey = pOverridingKey->GetNextKey() ) |
|
|
{ |
|
|
KeyValues *pExistingKey = pSubKey->FindKey( pOverridingKey->GetName() ); |
|
|
if ( pExistingKey ) |
|
|
{ |
|
|
pExistingKey->SetStringValue( pOverridingKey->GetString() ); |
|
|
} |
|
|
else |
|
|
{ |
|
|
KeyValues *copy = pOverridingKey->MakeCopy(); |
|
|
pSubKey->AddSubKey( copy ); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
|
// Purpose: registers that a control settings file may be loaded |
|
|
// use when the dialog may have multiple states and the editor will need to be able to switch between them |
|
|
//----------------------------------------------------------------------------- |
|
|
void BuildGroup::RegisterControlSettingsFile(const char *controlResourceName, const char *pathID) |
|
|
{ |
|
|
// add the file into a list for build mode |
|
|
CUtlSymbol sym(controlResourceName); |
|
|
if (!m_RegisteredControlSettingsFiles.IsValidIndex(m_RegisteredControlSettingsFiles.Find(sym))) |
|
|
{ |
|
|
m_RegisteredControlSettingsFiles.AddToTail(sym); |
|
|
} |
|
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
|
// Purpose: data accessor / iterator |
|
|
//----------------------------------------------------------------------------- |
|
|
int BuildGroup::GetRegisteredControlSettingsFileCount() |
|
|
{ |
|
|
return m_RegisteredControlSettingsFiles.Count(); |
|
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
|
// Purpose: data accessor |
|
|
//----------------------------------------------------------------------------- |
|
|
const char *BuildGroup::GetRegisteredControlSettingsFileByIndex(int index) |
|
|
{ |
|
|
return m_RegisteredControlSettingsFiles[index].String(); |
|
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
|
// Purpose: reloads the control settings from file |
|
|
//----------------------------------------------------------------------------- |
|
|
void BuildGroup::ReloadControlSettings() |
|
|
{ |
|
|
delete m_hBuildDialog.Get(); |
|
|
m_hBuildDialog = NULL; |
|
|
|
|
|
// loop though objects in the current control group and remove them all |
|
|
// the 0th panel is always the contextPanel which is not deletable |
|
|
for( int i = 1; i < _panelDar.Count(); i++ ) |
|
|
{ |
|
|
if (!_panelDar[i].Get()) // this can happen if we had two of the same handle in the list |
|
|
{ |
|
|
_panelDar.Remove(i); |
|
|
--i; |
|
|
continue; |
|
|
} |
|
|
|
|
|
// only delete deletable panels, as the only deletable panels |
|
|
// are the ones created using the resource file |
|
|
if ( _panelDar[i].Get()->IsBuildModeDeletable()) |
|
|
{ |
|
|
delete _panelDar[i].Get(); |
|
|
_panelDar.Remove(i); |
|
|
--i; |
|
|
} |
|
|
} |
|
|
|
|
|
if (m_pResourceName) |
|
|
{ |
|
|
EditablePanel *edit = dynamic_cast<EditablePanel *>(m_pParentPanel); |
|
|
if (edit) |
|
|
{ |
|
|
edit->LoadControlSettings(m_pResourceName, m_pResourcePathID); |
|
|
} |
|
|
else |
|
|
{ |
|
|
LoadControlSettings(m_pResourceName, m_pResourcePathID); |
|
|
} |
|
|
} |
|
|
|
|
|
_controlGroup.RemoveAll(); |
|
|
|
|
|
ActivateBuildDialog(); |
|
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
|
// Purpose: changes which control settings are currently loaded |
|
|
//----------------------------------------------------------------------------- |
|
|
void BuildGroup::ChangeControlSettingsFile(const char *controlResourceName) |
|
|
{ |
|
|
// clear any current state |
|
|
_controlGroup.RemoveAll(); |
|
|
_currentPanel = m_pParentPanel; |
|
|
|
|
|
// load the new state, via the dialog if possible |
|
|
EditablePanel *edit = dynamic_cast<EditablePanel *>(m_pParentPanel); |
|
|
if (edit) |
|
|
{ |
|
|
edit->LoadControlSettings(controlResourceName, m_pResourcePathID); |
|
|
} |
|
|
else |
|
|
{ |
|
|
LoadControlSettings(controlResourceName, m_pResourcePathID); |
|
|
} |
|
|
|
|
|
// force it to update |
|
|
KeyValues *keyval = new KeyValues("SetActiveControl"); |
|
|
keyval->SetPtr("PanelPtr", GetCurrentPanel()); |
|
|
ivgui()->PostMessage(m_hBuildDialog->GetVPanel(), keyval, NULL); |
|
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
|
// Purpose: saves control settings to file |
|
|
//----------------------------------------------------------------------------- |
|
|
bool BuildGroup::SaveControlSettings( void ) |
|
|
{ |
|
|
bool bSuccess = false; |
|
|
if ( m_pResourceName ) |
|
|
{ |
|
|
KeyValues *rDat = new KeyValues( m_pResourceName ); |
|
|
|
|
|
// get the data from our controls |
|
|
GetSettings( rDat ); |
|
|
|
|
|
char fullpath[ 512 ]; |
|
|
g_pFullFileSystem->RelativePathToFullPath( m_pResourceName, m_pResourcePathID, fullpath, sizeof( fullpath ) ); |
|
|
|
|
|
// save the data out to a file |
|
|
bSuccess = rDat->SaveToFile( g_pFullFileSystem, fullpath, NULL ); |
|
|
if (!bSuccess) |
|
|
{ |
|
|
MessageBox *dlg = new MessageBox("BuildMode - Error saving file", "Error: Could not save changes. File is most likely read only."); |
|
|
dlg->DoModal(); |
|
|
} |
|
|
|
|
|
rDat->deleteThis(); |
|
|
} |
|
|
|
|
|
return bSuccess; |
|
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
|
// Purpose: Deletes all the controls not created by the code |
|
|
//----------------------------------------------------------------------------- |
|
|
void BuildGroup::DeleteAllControlsCreatedByControlSettingsFile() |
|
|
{ |
|
|
// loop though objects in the current control group and remove them all |
|
|
// the 0th panel is always the contextPanel which is not deletable |
|
|
for ( int i = 1; i < _panelDar.Count(); i++ ) |
|
|
{ |
|
|
if (!_panelDar[i].Get()) // this can happen if we had two of the same handle in the list |
|
|
{ |
|
|
_panelDar.Remove(i); |
|
|
--i; |
|
|
continue; |
|
|
} |
|
|
|
|
|
// only delete deletable panels, as the only deletable panels |
|
|
// are the ones created using the resource file |
|
|
if ( _panelDar[i].Get()->IsBuildModeDeletable()) |
|
|
{ |
|
|
delete _panelDar[i].Get(); |
|
|
_panelDar.Remove(i); |
|
|
--i; |
|
|
} |
|
|
} |
|
|
|
|
|
_currentPanel = m_pBuildContext; |
|
|
_currentPanel->InvalidateLayout(); |
|
|
m_pBuildContext->Repaint(); |
|
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
|
// Purpose: serializes settings from a resource data container |
|
|
//----------------------------------------------------------------------------- |
|
|
void BuildGroup::ApplySettings( KeyValues *resourceData ) |
|
|
{ |
|
|
tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "%s", __FUNCTION__ ); |
|
|
|
|
|
// loop through all the keys, applying them wherever |
|
|
for (KeyValues *controlKeys = resourceData->GetFirstSubKey(); controlKeys != NULL; controlKeys = controlKeys->GetNextKey()) |
|
|
{ |
|
|
bool bFound = false; |
|
|
|
|
|
// Skip keys that are atomic.. |
|
|
if (controlKeys->GetDataType() != KeyValues::TYPE_NONE) |
|
|
continue; |
|
|
|
|
|
char const *keyName = controlKeys->GetName(); |
|
|
|
|
|
// check to see if any buildgroup panels have this name |
|
|
for ( int i = 0; i < _panelDar.Count(); i++ ) |
|
|
{ |
|
|
Panel *panel = _panelDar[i].Get(); |
|
|
|
|
|
if (!panel) // this can happen if we had two of the same handle in the list |
|
|
{ |
|
|
_panelDar.Remove(i); |
|
|
--i; |
|
|
continue; |
|
|
} |
|
|
|
|
|
|
|
|
Assert (panel); |
|
|
|
|
|
// make the control name match CASE INSENSITIVE! |
|
|
char const *panelName = panel->GetName(); |
|
|
|
|
|
if (!Q_stricmp(panelName, keyName)) |
|
|
{ |
|
|
// apply the settings |
|
|
panel->ApplySettings(controlKeys); |
|
|
bFound = true; |
|
|
break; |
|
|
} |
|
|
} |
|
|
|
|
|
if ( !bFound ) |
|
|
{ |
|
|
// the key was not found in the registered list, check to see if we should create it |
|
|
if ( keyName /*controlKeys->GetInt("AlwaysCreate", false)*/ ) |
|
|
{ |
|
|
// create the control even though it wasn't registered |
|
|
NewControl( controlKeys ); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
|
// Purpose: Create a new control in the context panel |
|
|
// Input: name: class name of control to create |
|
|
// controlKeys: keyvalues of settings for the panel. |
|
|
// name OR controlKeys should be set, not both. |
|
|
// x,y position relative to base panel |
|
|
// Output: Panel *newPanel, NULL if failed to create new control. |
|
|
//----------------------------------------------------------------------------- |
|
|
Panel *BuildGroup::NewControl( const char *name, int x, int y) |
|
|
{ |
|
|
Assert (name); |
|
|
|
|
|
Panel *newPanel = NULL; |
|
|
// returns NULL on failure |
|
|
newPanel = static_cast<EditablePanel *>(m_pParentPanel)->CreateControlByName(name); |
|
|
|
|
|
if (newPanel) |
|
|
{ |
|
|
// panel successfully created |
|
|
newPanel->SetParent(m_pParentPanel); |
|
|
newPanel->SetBuildGroup(this); |
|
|
newPanel->SetPos(x, y); |
|
|
|
|
|
char newFieldName[255]; |
|
|
GetNewFieldName(newFieldName, sizeof(newFieldName), newPanel); |
|
|
newPanel->SetName(newFieldName); |
|
|
|
|
|
newPanel->AddActionSignalTarget(m_pParentPanel); |
|
|
newPanel->SetBuildModeEditable(true); |
|
|
newPanel->SetBuildModeDeletable(true); |
|
|
|
|
|
// make sure it gets freed |
|
|
newPanel->SetAutoDelete(true); |
|
|
} |
|
|
|
|
|
return newPanel; |
|
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
|
// Purpose: Create a new control in the context panel |
|
|
// Input: controlKeys: keyvalues of settings for the panel only works when applying initial settings. |
|
|
// Output: Panel *newPanel, NULL if failed to create new control. |
|
|
//----------------------------------------------------------------------------- |
|
|
Panel *BuildGroup::NewControl( KeyValues *controlKeys, int x, int y) |
|
|
{ |
|
|
Assert (controlKeys); |
|
|
|
|
|
Panel *newPanel = NULL; |
|
|
if (controlKeys) |
|
|
{ |
|
|
// Warning( "Creating new control \"%s\" of type \"%s\"\n", controlKeys->GetString( "fieldName" ), controlKeys->GetString( "ControlName" ) ); |
|
|
KeyValues *keyVal = new KeyValues("ControlFactory", "ControlName", controlKeys->GetString("ControlName")); |
|
|
m_pBuildContext->RequestInfo(keyVal); |
|
|
// returns NULL on failure |
|
|
newPanel = (Panel *)keyVal->GetPtr("PanelPtr"); |
|
|
keyVal->deleteThis(); |
|
|
} |
|
|
else |
|
|
{ |
|
|
return NULL; |
|
|
} |
|
|
|
|
|
if (newPanel) |
|
|
{ |
|
|
// panel successfully created |
|
|
newPanel->SetParent(m_pParentPanel); |
|
|
newPanel->SetBuildGroup(this); |
|
|
newPanel->SetPos(x, y); |
|
|
|
|
|
newPanel->SetName(controlKeys->GetName()); // name before applysettings :) |
|
|
newPanel->ApplySettings(controlKeys); |
|
|
|
|
|
newPanel->AddActionSignalTarget(m_pParentPanel); |
|
|
newPanel->SetBuildModeEditable(true); |
|
|
newPanel->SetBuildModeDeletable(true); |
|
|
|
|
|
// make sure it gets freed |
|
|
newPanel->SetAutoDelete(true); |
|
|
} |
|
|
|
|
|
return newPanel; |
|
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
|
// Purpose: Get a new unique fieldname for a new control |
|
|
//----------------------------------------------------------------------------- |
|
|
void BuildGroup::GetNewFieldName(char *newFieldName, int newFieldNameSize, Panel *newPanel) |
|
|
{ |
|
|
int fieldNameNumber=1; |
|
|
char defaultName[25]; |
|
|
|
|
|
Q_strncpy( defaultName, newPanel->GetClassName(), sizeof( defaultName ) ); |
|
|
|
|
|
while (1) |
|
|
{ |
|
|
Q_snprintf (newFieldName, newFieldNameSize, "%s%d", defaultName, fieldNameNumber); |
|
|
if ( FieldNameTaken(newFieldName) == NULL) |
|
|
break; |
|
|
++fieldNameNumber; |
|
|
} |
|
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
|
// Purpose: check to see if any buildgroup panels have this fieldname |
|
|
// Input : fieldName, name to check |
|
|
// Output : ptr to a panel that has the name if it is taken |
|
|
//----------------------------------------------------------------------------- |
|
|
Panel *BuildGroup::FieldNameTaken(const char *fieldName) |
|
|
{ |
|
|
for ( int i = 0; i < _panelDar.Count(); i++ ) |
|
|
{ |
|
|
Panel *panel = _panelDar[i].Get(); |
|
|
if ( !panel ) |
|
|
continue; |
|
|
|
|
|
if (!stricmp(panel->GetName(), fieldName) ) |
|
|
{ |
|
|
return panel; |
|
|
} |
|
|
} |
|
|
return NULL; |
|
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
|
// Purpose: serializes settings to a resource data container |
|
|
//----------------------------------------------------------------------------- |
|
|
void BuildGroup::GetSettings( KeyValues *resourceData ) |
|
|
{ |
|
|
// loop through all the objects getting their settings |
|
|
for( int i = 0; i < _panelDar.Count(); i++ ) |
|
|
{ |
|
|
Panel *panel = _panelDar[i].Get(); |
|
|
if (!panel) |
|
|
continue; |
|
|
|
|
|
bool isRuler = false; |
|
|
// do not get setting for ruler labels. |
|
|
if (_showRulers) // rulers are visible |
|
|
{ |
|
|
for (int j = 0; j < 4; j++) |
|
|
{ |
|
|
if (panel == _rulerNumber[j]) |
|
|
{ |
|
|
isRuler = true; |
|
|
break; |
|
|
} |
|
|
} |
|
|
if (isRuler) |
|
|
{ |
|
|
isRuler = false; |
|
|
continue; |
|
|
} |
|
|
} |
|
|
|
|
|
// Don't save the setting of the buildmodedialog |
|
|
if (!stricmp(panel->GetName(), "BuildDialog")) |
|
|
continue; |
|
|
|
|
|
// get the keys section from the data file |
|
|
if (panel->GetName() && *panel->GetName()) |
|
|
{ |
|
|
KeyValues *datKey = resourceData->FindKey(panel->GetName(), true); |
|
|
|
|
|
// get the settings |
|
|
panel->GetSettings(datKey); |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
|
// Purpose: loop though objects in the current control group and remove them all |
|
|
//----------------------------------------------------------------------------- |
|
|
void BuildGroup::RemoveSettings() |
|
|
{ |
|
|
// loop though objects in the current control group and remove them all |
|
|
int i; |
|
|
for( i = 0; i < _controlGroup.Count(); i++ ) |
|
|
{ |
|
|
// only delete delatable panels |
|
|
if ( _controlGroup[i].Get()->IsBuildModeDeletable()) |
|
|
{ |
|
|
delete _controlGroup[i].Get(); |
|
|
_controlGroup.Remove(i); |
|
|
--i; |
|
|
} |
|
|
} |
|
|
|
|
|
// remove deleted panels from the handle list |
|
|
for( i = 0; i < _panelDar.Count(); i++ ) |
|
|
{ |
|
|
if ( !_panelDar[i].Get() ) |
|
|
{ |
|
|
_panelDar.Remove(i); |
|
|
--i; |
|
|
} |
|
|
} |
|
|
|
|
|
_currentPanel = m_pBuildContext; |
|
|
_currentPanel->InvalidateLayout(); |
|
|
m_pBuildContext->Repaint(); |
|
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
|
// Purpose: sets the panel from which the build group gets all it's object creation info |
|
|
//----------------------------------------------------------------------------- |
|
|
void BuildGroup::SetContextPanel(Panel *contextPanel) |
|
|
{ |
|
|
m_pBuildContext = contextPanel; |
|
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
|
// Purpose: gets the panel from which the build group gets all it's object creation info |
|
|
//----------------------------------------------------------------------------- |
|
|
Panel *BuildGroup::GetContextPanel() |
|
|
{ |
|
|
return m_pBuildContext; |
|
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
|
// Purpose: get the list of panels in the buildgroup |
|
|
//----------------------------------------------------------------------------- |
|
|
CUtlVector<PHandle> *BuildGroup::GetPanelList() |
|
|
{ |
|
|
return &_panelDar; |
|
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
|
// Purpose: dialog variables |
|
|
//----------------------------------------------------------------------------- |
|
|
KeyValues *BuildGroup::GetDialogVariables() |
|
|
{ |
|
|
EditablePanel *edit = dynamic_cast<EditablePanel *>(m_pParentPanel); |
|
|
if (edit) |
|
|
{ |
|
|
return edit->GetDialogVariables(); |
|
|
} |
|
|
|
|
|
return NULL; |
|
|
} |
|
|
|
|
|
bool BuildGroup::PrecacheResFile( const char* pszResFileName ) |
|
|
{ |
|
|
KeyValues *pkvResFile = new KeyValues( pszResFileName ); |
|
|
if ( pkvResFile->LoadFromFile( g_pFullFileSystem, pszResFileName, "GAME" ) ) |
|
|
{ |
|
|
Assert( m_dictCachedResFiles.Find( pszResFileName ) == m_dictCachedResFiles.InvalidIndex() ); |
|
|
m_dictCachedResFiles.Insert( pszResFileName, pkvResFile ); |
|
|
return true; |
|
|
} |
|
|
|
|
|
return false; |
|
|
} |
|
|
|
|
|
void BuildGroup::ClearResFileCache() |
|
|
{ |
|
|
int nIndex = m_dictCachedResFiles.First(); |
|
|
while( m_dictCachedResFiles.IsValidIndex( nIndex ) ) |
|
|
{ |
|
|
m_dictCachedResFiles[ nIndex ]->deleteThis(); |
|
|
nIndex = m_dictCachedResFiles.Next( nIndex ); |
|
|
} |
|
|
m_dictCachedResFiles.Purge(); |
|
|
}
|
|
|
|