upload "kind" alien swarm

This commit is contained in:
nillerusr
2023-10-03 17:23:56 +03:00
parent b7bd94c52e
commit 7d3c0d8b5a
4229 changed files with 462900 additions and 495155 deletions
@@ -0,0 +1,156 @@
#include "kv_combo_leaf_panel.h"
#include <vgui_controls/TextEntry.h>
#include <vgui_controls/Button.h>
#include <vgui_controls/ComboBox.h>
#include "KeyValues.h"
#include "kv_editor.h"
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
using namespace vgui;
DECLARE_BUILD_FACTORY( CKV_Combo_Leaf_Panel )
//-----------------------------------------------------------------------------
// Constructor
//-----------------------------------------------------------------------------
CKV_Combo_Leaf_Panel::CKV_Combo_Leaf_Panel( Panel *parent, const char *name ) : BaseClass( parent, name )
{
m_bIntegerChoice = false;
m_pLabel = new vgui::Label( this, "Label", "" );
m_pLabel->SetMouseInputEnabled( false );
m_pCombo = new vgui::ComboBox( this, "Combo", 8, false );
m_pCombo->SetAutoLocalize( false );
m_pDeleteButton = new vgui::Button( this, "DeleteButton", "X", this, "Delete" );
}
void CKV_Combo_Leaf_Panel::PerformLayout()
{
BaseClass::PerformLayout();
m_pLabel->SetBounds( 0, 0, 100, 20 );
m_pLabel->SizeToContents();
m_pLabel->InvalidateLayout( true );
int iLabelSpace = MAX( m_pLabel->GetWide() + 5, 100 );
int iExtraHeight = 0;
int iTextEntryX = iLabelSpace;
if ( m_pFileSpecNode && m_pFileSpecNode->FindKey( "TextEntryNewLine" ) )
{
iExtraHeight = m_pLabel->GetTall();
iTextEntryX = 0;
}
if ( m_pFileSpecNode && m_pFileSpecNode->FindKey( "Tall" ) )
{
m_pCombo->SetBounds( iTextEntryX, iExtraHeight, 390 - iTextEntryX, m_pFileSpecNode->GetInt( "Tall" ) );
}
else
{
m_pCombo->SetBounds( iTextEntryX, iExtraHeight, 390 - iTextEntryX, 20 );
}
SetSize( 420, m_pCombo->GetTall() + iExtraHeight );
int iDeleteWidth = 20;
m_pDeleteButton->SetBounds( GetWide() - (iDeleteWidth + 5), 2, iDeleteWidth, 16 );
}
void CKV_Combo_Leaf_Panel::ApplySchemeSettings(vgui::IScheme *pScheme)
{
BaseClass::ApplySchemeSettings( pScheme );
m_pLabel->SetPaintBackgroundEnabled( false );
SetPaintBackgroundEnabled( false );
}
void CKV_Combo_Leaf_Panel::UpdatePanel()
{
if ( m_pFileSpecNode )
{
m_pDeleteButton->SetVisible( !!m_pFileSpecNode->FindKey( "Deletable" ) );
m_bIntegerChoice = m_pFileSpecNode->GetBool( "IntegerChoice" );
m_pCombo->RemoveAll();
int iChoices = 0;
const char *szCurrentChoice = m_pKey ? m_pKey->GetString() : "0";
int iCurrentChoice = atoi( szCurrentChoice );
for ( KeyValues *pKey = m_pFileSpecNode->GetFirstSubKey(); pKey; pKey = pKey->GetNextKey() )
{
if ( !Q_stricmp( pKey->GetName(), "Choice" ) )
{
const char* szValue = pKey->GetString();
int iIndex = m_pCombo->AddItem( szValue, NULL );
if ( m_bIntegerChoice && iCurrentChoice == iChoices )
{
m_pCombo->ActivateItem( iIndex );
}
else if ( !m_bIntegerChoice && !Q_stricmp( szValue, pKey->GetString() ) )
{
m_pCombo->ActivateItem( iIndex );
}
iChoices++;
}
}
}
if ( !m_pKey )
{
m_pLabel->SetText( "INVALID KEY" );
m_pCombo->SetText( "INVALID KEY" );
return;
}
if ( m_pFileSpecNode && m_pFileSpecNode->FindKey( "FriendlyName" ) )
{
m_pLabel->SetText( m_pFileSpecNode->GetString( "FriendlyName" ) );
}
else
{
m_pLabel->SetText( m_pKey->GetName() );
}
//m_pCombo->SetText( m_pKey->GetString() );
if ( m_pFileSpecNode && m_pFileSpecNode->GetInt( "ReadOnly", 0 ) == 1 )
{
m_pCombo->SetEditable( false );
m_pCombo->SetEnabled( false );
}
}
// update our key when the text entry changes
void CKV_Combo_Leaf_Panel::OnTextChanged( vgui::Panel* pTextEntry )
{
if ( pTextEntry != m_pCombo )
return;
if ( !m_pKey )
{
return;
}
if ( m_bIntegerChoice )
{
int iChoice = m_pCombo->GetActiveItem();
m_pKey->SetInt( NULL, iChoice );
}
else
{
char buf[ 2048 ];
m_pCombo->GetText( buf, 2048 );
m_pKey->SetStringValue( buf );
}
PostActionSignal( new KeyValues( "command", "command", "KeyValuesChanged" ) );
}
void CKV_Combo_Leaf_Panel::OnCommand( const char *command )
{
if ( !Q_stricmp( command, "Delete" ) && m_pKeyParent )
{
m_pKeyParent->RemoveSubKey( m_pKey );
m_pKey->deleteThis();
m_pEditor->OnKeyDeleted();
return;
}
BaseClass::OnCommand( command );
}
@@ -0,0 +1,37 @@
#ifndef _INCLUDED_KV_COMBO_LEAF_PANEL_H
#define _INCLUDED_KV_COMBO_LEAF_PANEL_H
#ifdef _WIN32
#pragma once
#endif
#include "kv_editor_base_panel.h"
namespace vgui
{
class TextEntry;
class Label;
class ComboBox;
};
// a vgui panel for showing a generic leaf
class CKV_Combo_Leaf_Panel : public CKV_Editor_Base_Panel
{
DECLARE_CLASS_SIMPLE( CKV_Combo_Leaf_Panel, CKV_Editor_Base_Panel );
public:
CKV_Combo_Leaf_Panel( Panel *parent, const char *name);
virtual void PerformLayout();
virtual void UpdatePanel();
virtual void ApplySchemeSettings(vgui::IScheme *pScheme);
virtual void OnCommand( const char *command );
MESSAGE_FUNC_PTR( OnTextChanged, "TextChanged", panel );
vgui::ComboBox *m_pCombo;
vgui::Label *m_pLabel;
vgui::Button* m_pDeleteButton;
bool m_bIntegerChoice; // if set to true, this combo box represents an enum or some choice of integers, rather than a list of strings
};
#endif // _INCLUDED_KV_COMBO_LEAF_PANEL_H
@@ -0,0 +1,375 @@
#include "kv_editor.h"
#include "kv_editor_base_panel.h"
#include "kv_fit_children_panel.h"
#include "ScrollingWindow.h"
#include "filesystem.h"
#include <vgui/ILocalize.h>
#include <vgui_controls/MenuBar.h>
#include <vgui_controls/MenuButton.h>
#include <vgui_controls/Menu.h>
#include "vgui/ISurface.h"
#include <vgui_controls/FileOpenDialog.h>
#include <vgui_controls/MessageBox.h>
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
using namespace vgui;
//bool g_bAddedKVEditorLocalization = false;
//-----------------------------------------------------------------------------
// Constructor
//-----------------------------------------------------------------------------
CKV_Editor::CKV_Editor( Panel *parent, const char *name ) : BaseClass( parent, name )
{
//if ( !g_bAddedKVEditorLocalization )
//{
//g_pVGuiLocalize->AddFile( "resource/kv_editor_english.txt" );
//g_bAddedKVEditorLocalization = true;
//}
m_pKeys = NULL;
m_pFileSpec = NULL;
m_bRequireFileSpec = true;
m_bShowSiblings = true;
m_pScrollingWindow = new CScrollingWindow( this, "ScrollingWindow" );
m_pContainer = new CKV_Fit_Children_Panel( this, "Container" );
m_pScrollingWindow->SetChildPanel( m_pContainer );
m_pScrollingWindow->InvalidateLayout( true );
m_szFileDirectory[0] = 0;
m_szFileFilter[0] = 0;
m_szFileFilterName[0] = 0;
}
//-----------------------------------------------------------------------------
// Destructor
//-----------------------------------------------------------------------------
CKV_Editor::~CKV_Editor()
{
}
void CKV_Editor::PerformLayout()
{
BaseClass::PerformLayout();
m_pScrollingWindow->SetBounds( 0, 0, GetWide(), GetTall() );
//m_pContainer->SetPos( 30, 30 );
}
void CKV_Editor::ApplySchemeSettings(vgui::IScheme *pScheme)
{
BaseClass::ApplySchemeSettings(pScheme);
m_pContainer->SetBgColor( Color( 0, 0, 0, 255 ) );
}
CKV_Editor_Base_Panel* CKV_Editor::FindPanel( KeyValues *pKey )
{
if ( !pKey )
return NULL;
for ( int i = 0; i < m_Panels.Count(); i++ )
{
if ( m_Panels[i]->GetKey() == pKey )
{
return m_Panels[i];
}
}
return NULL;
}
void CKV_Editor::DeleteAllPanels()
{
for ( int i = 0; i < m_Panels.Count(); i++ )
{
m_Panels[i]->SetVisible( false );
m_Panels[i]->MarkForDeletion();
CKV_Fit_Children_Panel *pFit = dynamic_cast< CKV_Fit_Children_Panel* >( m_Panels[i]->GetParent() );
if ( pFit )
{
pFit->RemoveAutoPositionPanel( m_Panels[i] );
}
}
m_Panels.Purge();
}
CKV_Editor_Base_Panel* CKV_Editor::CreatePanel( const char *szClassName, CKV_Editor_Base_Panel *pParent, KeyValues *pFileSpecNode, KeyValues *pKey )
{
CKV_Editor_Base_Panel *pPanel = dynamic_cast<CKV_Editor_Base_Panel *>( CreateControlByName( szClassName ) );
if ( pPanel )
{
pPanel->SetParent( pParent );
pPanel->SetAllowDeletion( m_bAllowDeletion );
pPanel->SetFileSpecNode( pFileSpecNode );
pPanel->SetEditor( this );
pPanel->SetName( pKey->GetName() );
pPanel->SetKey( pKey );
pPanel->SetKeyParent( FindParentForKey( pKey ) );
pPanel->SetSortOrder( pFileSpecNode->GetFloat( "SortOrder" ) );
pPanel->AddActionSignalTarget( this );
CKV_Fit_Children_Panel *pFit = dynamic_cast< CKV_Fit_Children_Panel* >( pParent );
if ( pFit )
{
pFit->AddAutoPositionPanel( pPanel );
}
m_Panels.AddToTail( pPanel );
}
else
{
Warning( "Failed to create panel %s\n", szClassName );
}
return pPanel;
}
// creates panels for target key, all its siblings and all its children
void CKV_Editor::UpdatePanels( KeyValues *pKV, CKV_Editor_Base_Panel *pParentPanel, bool bIncludeSiblings )
{
Assert( pParentPanel );
// go through each key, making sure it has a panel
for ( KeyValues *pKey = pKV; pKey != NULL; pKey = pKey->GetNextKey() )
{
CKV_Editor_Base_Panel *pPanel = FindPanel( pKey );
KeyValues *pFileSpecNode = FindFileSpecNodeForKey( pKey );
if ( !pFileSpecNode && m_bRequireFileSpec )
{
Warning( "Key %s:%s has no FileSpecNode!\n", pKey->GetName(), pKey->GetString() );
return;
}
const char *szClassName = "CKV_Node_Panel";
if ( !pFileSpecNode )
{
//Warning( "Failed to FindFileSpecNodeForKey for key %s\n", pKey->GetName() );
bool bHasChildren = ( pKey->GetFirstSubKey() != NULL );
if ( bHasChildren )
{
szClassName = "CKV_Node_Panel";
}
else
{
szClassName = "CKV_Leaf_Panel";
}
}
else
{
szClassName = pFileSpecNode->GetString( "Panel", "CKV_Node_Panel" );
}
if ( !pPanel )
{
// create a panel of the appropriate type (as a child of pParentPanel)
pPanel = CreatePanel( szClassName, pParentPanel, pFileSpecNode, pKey );
}
else
{
// make sure the panel is the right type.
if ( Q_stricmp( pPanel->GetClassName(), szClassName ) )
{
// destroy and recreate if not (as a child of pParentPanel)
pPanel->SetVisible( false );
pPanel->MarkForDeletion();
CKV_Fit_Children_Panel *pFit = dynamic_cast< CKV_Fit_Children_Panel* >( pPanel->GetParent() );
if ( pFit )
{
pFit->RemoveAutoPositionPanel( pPanel );
}
pPanel = CreatePanel( szClassName, pParentPanel, pFileSpecNode, pKey );
}
else
{
pPanel->SetKey( pKey );
pPanel->SetKeyParent( FindParentForKey( pKey ) );
}
}
// if key has children
if ( pKey->GetFirstSubKey() )
{
UpdatePanels( pKey->GetFirstSubKey(), pPanel, true );
}
if ( !bIncludeSiblings )
break;
}
m_pContainer->InvalidateLayout( true );
}
KeyValues* CKV_Editor::FindParentForKey( KeyValues *pSearchChild )
{
for ( KeyValues *pKey = m_pKeys; pKey != NULL; pKey = pKey->GetNextKey() )
{
if ( pKey == pSearchChild )
return NULL;
KeyValues *pResult = FindParentForKey( pKey, pSearchChild );
if ( pResult )
return pResult;
}
return NULL;
}
KeyValues* CKV_Editor::FindParentForKey( KeyValues *pRoot, KeyValues *pSearchChild )
{
// see if pKV or any of our direct children are the search key
for ( KeyValues *pKey = pRoot->GetFirstSubKey(); pKey != NULL; pKey = pKey->GetNextKey() )
{
if ( pKey == pSearchChild )
return pRoot;
}
// if not, then ask each of our children to search deeper
for ( KeyValues *pKey = pRoot->GetFirstSubKey(); pKey != NULL; pKey = pKey->GetNextKey() )
{
KeyValues *pResult = FindParentForKey( pKey, pSearchChild );
if ( pResult )
return pResult;
}
return NULL;
}
KeyValues* CKV_Editor::FindFileSpecNodeForKey( KeyValues *pKey )
{
if ( !m_pFileSpec )
return NULL;
// build a list of panels from us up to the parent
CUtlVector<KeyValues*> chain;
KeyValues *pSearchKey = pKey;
while ( pSearchKey )
{
chain.AddToHead( pSearchKey );
pSearchKey = FindParentForKey( pSearchKey );
}
int iChainDepth = chain.Count();
int iCurrentDepth = 0;
KeyValues *pKeySpec = m_pFileSpec;
while ( pKeySpec )
{
const char *szNodeName = "_unnamed_node";
if ( !Q_stricmp( pKeySpec->GetName(), "_Node" ) || !Q_stricmp( pKeySpec->GetName(), "_Leaf" ) )
{
szNodeName = pKeySpec->GetString( "Name", "_unnamed_node" );
}
//const char *szChainName = chain[iCurrentDepth]->GetName();
if ( !Q_stricmp( szNodeName, chain[iCurrentDepth]->GetName() )
|| !Q_stricmp( szNodeName, "*" ) ) // at any level there can be a keyspec node with name "*" which will match any key
{
iCurrentDepth++;
if ( iCurrentDepth >= iChainDepth ) // found appropriate file spec node that describes this key
{
return pKeySpec;
}
// Go down a level
pKeySpec = pKeySpec->GetFirstSubKey();
}
else
{
// Check the next key in the mission spec
pKeySpec = pKeySpec->GetNextKey();
}
}
return NULL;
}
void CKV_Editor::SetFileSpec( const char *szFilename, const char *szPathID )
{
KeyValues *pKeys = new KeyValues( "FileSpec" );
if ( !pKeys->LoadFromFile( g_pFullFileSystem, szFilename, szPathID ) )
{
Warning( "Failed to load file spec %s\n", szFilename );
return;
}
SetFileSpec( pKeys );
}
void CKV_Editor::SetFileSpec( KeyValues *pKeys )
{
m_pFileSpec = pKeys;
DeleteAllPanels();
UpdatePanels( m_pKeys, m_pContainer, m_bShowSiblings );
}
void CKV_Editor::SetFileFilter( const char *szFilter, const char *szFilterName )
{
Q_snprintf( m_szFileFilter, sizeof( m_szFileFilter ), szFilter );
Q_snprintf( m_szFileFilterName, sizeof( m_szFileFilterName ), szFilterName );
}
void CKV_Editor::SetFileDirectory( const char *szDirName )
{
Q_snprintf( m_szFileDirectory, sizeof( m_szFileDirectory ), szDirName );
}
void CKV_Editor::SetKeys( KeyValues *pKeys )
{
m_pKeys = pKeys;
DeleteAllPanels();
UpdatePanels( m_pKeys, m_pContainer, m_bShowSiblings );
PostActionSignal( new KeyValues( "command", "command", "KeyValuesChanged" ) );
}
void CKV_Editor::OnKeyDeleted()
{
DeleteAllPanels();
UpdatePanels( m_pKeys, m_pContainer, m_bShowSiblings );
PostActionSignal( new KeyValues( "command", "command", "KeyValuesChanged" ) );
}
void CKV_Editor::OnKeyAdded()
{
DeleteAllPanels();
UpdatePanels( m_pKeys, m_pContainer, m_bShowSiblings );
PostActionSignal( new KeyValues( "command", "command", "KeyValuesChanged" ) );
}
void CKV_Editor::AddToKey( KeyValues *pFileSpecNode, KeyValues *pKey, const char *szNewKeyName )
{
// go through all _Node or _Leaf children of our filespec node
for ( KeyValues *pSubKey = pFileSpecNode->GetFirstSubKey(); pSubKey; pSubKey = pSubKey->GetNextKey() )
{
bool bNode = !Q_stricmp( pSubKey->GetName(), "_Node" );
bool bLeaf = !Q_stricmp( pSubKey->GetName(), "_Leaf" );
if ( !bLeaf && !bNode )
continue;
if ( szNewKeyName && Q_stricmp( pSubKey->GetString( "Name" ), szNewKeyName ) )
continue;
if ( !szNewKeyName && pSubKey->GetInt( "Autocreate" ) != 1 )
continue;
if ( bLeaf )
{
bool bAlreadyExists = !!pKey->FindKey( pSubKey->GetString( "Name" ) );
bool bUnique = pSubKey->GetInt( "Unique" ) == 1;
if ( !bUnique || !bAlreadyExists )
{
KeyValues *pNewKey = new KeyValues( pSubKey->GetString( "Name" ) );
Msg( "Added leaf %s\n", pSubKey->GetString( "Name" ) );
pNewKey->SetStringValue( pSubKey->GetString( "DefaultValue", "" ) );
pKey->AddSubKey( pNewKey );
}
}
else
{
KeyValues *pNewKey = new KeyValues( pSubKey->GetString( "Name" ) );
Msg( "Added node %s\n", pSubKey->GetString( "Name" ) );
pKey->AddSubKey( pNewKey );
// recursively create child _nodes and any _leafs they have
KeyValues *pNewSpec = FindFileSpecNodeForKey( pNewKey );
if ( pNewSpec )
{
AddToKey( pNewSpec, pNewKey, NULL );
}
}
}
OnKeyAdded();
}
@@ -0,0 +1,99 @@
#ifndef _INCLUDED_KV_EDITOR_H
#define _INCLUDED_KV_EDITOR_H
#ifdef _WIN32
#pragma once
#endif
#include <vgui_controls/EditablePanel.h>
#include <vgui_controls/ImageList.h>
#include <vgui_controls/SectionedListPanel.h>
#include <vgui_controls/PHandle.h>
#include <FileSystem.h>
#include "vgui/mousecode.h"
#include "vgui/IScheme.h"
#include "ConfigManager.h"
class CScrollingWindow;
class CKV_Editor_Base_Panel;
class CKV_Fit_Children_Panel;
namespace vgui
{
class PanelListPanel;
class ImagePanel;
class MenuBar;
class CheckButton;
class Button;
class Menu;
};
using namespace vgui;
//-----------------------------------------------------------------------------
// Purpose: Main panel for visualizing and editing keyvalues
//-----------------------------------------------------------------------------
class CKV_Editor : public vgui::EditablePanel
{
DECLARE_CLASS_SIMPLE( CKV_Editor, vgui::EditablePanel );
public:
CKV_Editor( Panel *parent, const char *name );
virtual ~CKV_Editor();
virtual void PerformLayout();
virtual void ApplySchemeSettings(vgui::IScheme *pScheme);
virtual void SetFileSpec( const char *szFilename, const char *szPathID );
virtual void SetFileSpec( KeyValues *pKeys );
KeyValues* GetFileSpec() { return m_pFileSpec; }
virtual void SetKeys( KeyValues *pKeys );
KeyValues* GetKeys() { return m_pKeys; }
void SetShowSiblingKeys( bool bShowSiblings ) { m_bShowSiblings = bShowSiblings; }
void SetFileFilter( const char *szFilter, const char *szFilterName );
void SetFileDirectory( const char *szDirName );
const char* GetFileFilter() { return m_szFileFilter; }
const char* GetFileFilterName() { return m_szFileFilterName; }
const char* GetFileDirectory() { return m_szFileDirectory; }
virtual void AddToKey( KeyValues *pFileSpecNode, KeyValues *pKey, const char *szNewKeyName );
virtual void OnKeyDeleted();
virtual void OnKeyAdded();
void SetRequiresFileSpec( bool bRequiresFileSpec ) { m_bRequireFileSpec = bRequiresFileSpec; }
protected:
// the keyvalues we're currently editing
KeyValues *m_pKeys;
// kv view
CScrollingWindow* m_pScrollingWindow;
char m_szFileDirectory[MAX_PATH];
char m_szFileFilter[32];
char m_szFileFilterName[32];
void DeleteAllPanels();
void UpdatePanels( KeyValues *pKV, CKV_Editor_Base_Panel *pParentPanel, bool bIncludeSiblings );
CKV_Editor_Base_Panel* FindPanel( KeyValues *pKey );
CKV_Editor_Base_Panel* CreatePanel( const char *szClassName, CKV_Editor_Base_Panel *pParent, KeyValues *pFileSpecNode, KeyValues *pKey );
//const char* FindPanelClassForKey( KeyValues *pKey ); // finds the panel class a particular key is meant to have
KeyValues* FindParentForKey( KeyValues *pSearchChild ); // searches m_pKeys for the parent
KeyValues* FindParentForKey( KeyValues *pRoot, KeyValues *pSearchChild ); // searches pRoot for the parent
KeyValues* FindFileSpecNodeForKey( KeyValues *pKey );
CKV_Fit_Children_Panel *m_pContainer;
CUtlVector< CKV_Editor_Base_Panel* > m_Panels;
// keyvalues describing the file format of the KeyValues we're editing
KeyValues* FindFileSpecNodeForKey( KeyValues *pKey, const char *szPathID );
KeyValues *m_pFileSpec;
bool m_bRequireFileSpec;
bool m_bShowSiblings;
bool m_bAllowDeletion;
};
#endif // _INCLUDED_KV_EDITOR_H
@@ -0,0 +1,49 @@
#include "kv_editor_base_panel.h"
#include "KeyValues.h"
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
using namespace vgui;
//-----------------------------------------------------------------------------
// Constructor
//-----------------------------------------------------------------------------
CKV_Editor_Base_Panel::CKV_Editor_Base_Panel( Panel *parent, const char *name ) : BaseClass( parent, name )
{
m_pKey = NULL;
m_pKeyParent = NULL;
m_flSortOrder = 0;
m_pFileSpecNode = NULL;
m_pEditor = NULL;
m_bAllowDeletion = true;
}
void CKV_Editor_Base_Panel::PerformLayout()
{
BaseClass::PerformLayout();
}
void CKV_Editor_Base_Panel::SetKey( KeyValues *pKey )
{
if ( pKey == m_pKey )
return;
m_pKey = pKey;
UpdatePanel();
}
void CKV_Editor_Base_Panel::SetKeyParent( KeyValues *pKey )
{
if ( pKey == m_pKeyParent )
return;
m_pKeyParent = pKey;
}
void CKV_Editor_Base_Panel::SetFileSpecNode( KeyValues *pKey )
{
m_pFileSpecNode = pKey;
ApplySettings( pKey );
}
@@ -0,0 +1,43 @@
#ifndef _INCLUDED_KV_EDITOR_PANEL_H
#define _INCLUDED_KV_EDITOR_PANEL_H
#ifdef _WIN32
#pragma once
#endif
#include <vgui_controls/EditablePanel.h>
class CKV_Editor;
// a vgui panel that resizes to fit its children, with some border
class CKV_Editor_Base_Panel : public vgui::EditablePanel
{
DECLARE_CLASS_SIMPLE( CKV_Editor_Base_Panel, vgui::EditablePanel );
public:
CKV_Editor_Base_Panel( Panel *parent, const char *name);
virtual void PerformLayout();
virtual void UpdatePanel() { }
void SetKey( KeyValues *pKey );
KeyValues* GetKey() { return m_pKey; }
void SetKeyParent( KeyValues *pKey );
void SetFileSpecNode( KeyValues *pKey );
void SetEditor( CKV_Editor *pEditor ) { m_pEditor = pEditor; }
void SetAllowDeletion( bool bCanDelete ) { m_bAllowDeletion = bCanDelete; }
float GetSortOrder() const { return m_flSortOrder; }
void SetSortOrder( float flSortOrder ) { m_flSortOrder = flSortOrder; }
protected:
KeyValues *m_pKey;
KeyValues *m_pKeyParent;
KeyValues *m_pFileSpecNode;
CKV_Editor *m_pEditor;
float m_flSortOrder;
bool m_bAllowDeletion;
};
#endif // _INCLUDED_KV_EDITOR_PANEL_H
@@ -0,0 +1,199 @@
#include "kv_editor.h"
#include "kv_editor_frame.h"
#include "kv_editor_base_panel.h"
#include "kv_fit_children_panel.h"
#include "ScrollingWindow.h"
#include "filesystem.h"
#include <vgui/ILocalize.h>
#include <vgui_controls/MenuBar.h>
#include <vgui_controls/MenuButton.h>
#include <vgui_controls/Menu.h>
#include "vgui/ISurface.h"
#include <vgui_controls/FileOpenDialog.h>
#include <vgui_controls/MessageBox.h>
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
using namespace vgui;
extern char g_gamedir[1024];
//-----------------------------------------------------------------------------
// Constructor
//-----------------------------------------------------------------------------
CKV_Editor_Frame::CKV_Editor_Frame( Panel *parent, const char *name ) : BaseClass( parent, name )
{
vgui::HScheme scheme = vgui::scheme()->LoadSchemeFromFile( "tilegen_scheme.res", NULL );
SetScheme( scheme );
m_pEditor = new CKV_Editor( this, "KVEditor" );
m_pEditor->SetFileFilter( "*.txt", "KeyValues files (*.txt)" );
m_szLastFileName[0] = '\0';
SetSize( 384, 420 );
SetMinimumSize( 384, 420 );
// setup the menu
m_pMenuBar = new MenuBar( this, "KV_Editor_MenuBar" );
MenuButton *pFileMenuButton = new MenuButton( this, "KV_Editor_FileMenuButton", "&File" );
m_pFileMenu = new Menu( pFileMenuButton, "KV_Editor_FileMenu" );
//m_pFileMenu->AddMenuItem( "&New", "NewKeys", this );
m_pFileMenu->AddMenuItem( "&Open...", "OpenKeys", this );
m_pFileMenu->AddMenuItem( "&Save", "SaveKeys", this );
m_pFileMenu->AddMenuItem( "&Save As...", "SaveKeysAs", this );
pFileMenuButton->SetMenu( m_pFileMenu );
m_pMenuBar->AddButton( pFileMenuButton );
// disable keyboard input on the menu, otherwise once you click there, this dialog never gets key input again (is there a better way to do this and maintain keyboard shortcuts for the menu?)
pFileMenuButton->SetKeyBoardInputEnabled( false );
m_pFileMenu->SetKeyBoardInputEnabled( false );
SetSizeable( true );
SetMinimizeButtonVisible( false );
SetMaximizeButtonVisible( false );
SetMenuButtonVisible( false );
m_bFirstPerformLayout = true;
SetTitle( "KeyValues Editor", true );
// temp for mission editor
//Q_snprintf( m_szFileDirectory, sizeof( m_szFileDirectory ), "infested/tilegen/missions" );
char keys_dir[1024];
Q_snprintf( keys_dir, sizeof( keys_dir ), "%s\\tilegen\\missions", g_gamedir );
m_pEditor->SetFileDirectory( keys_dir );
m_pEditor->SetFileSpec( "tilegen/mission_editor_spec.txt", "GAME" );
}
//-----------------------------------------------------------------------------
// Destructor
//-----------------------------------------------------------------------------
CKV_Editor_Frame::~CKV_Editor_Frame()
{
}
//-----------------------------------------------------------------------------
// Purpose: Kills the whole app on close
//-----------------------------------------------------------------------------
void CKV_Editor_Frame::OnClose( void )
{
BaseClass::OnClose();
}
//-----------------------------------------------------------------------------
// Purpose: Parse commands coming in from the VGUI dialog
//-----------------------------------------------------------------------------
void CKV_Editor_Frame::OnCommand( const char *command )
{
if ( Q_stricmp( command, "OpenKeys" ) == 0 )
{
DoFileOpen();
return;
}
else if ( Q_stricmp( command, "SaveKeys" ) == 0 )
{
if ( Q_strlen( m_szLastFileName ) <= 0 )
{
DoFileSaveAs();
}
else if ( m_pEditor->GetKeys() )
{
m_pEditor->GetKeys()->SaveToFile( g_pFullFileSystem, m_szLastFileName, "GAME" );
}
return;
}
else if ( Q_stricmp( command, "SaveKeysAs" ) == 0 )
{
DoFileSaveAs();
return;
}
}
void CKV_Editor_Frame::PerformLayout()
{
BaseClass::PerformLayout();
if ( m_bFirstPerformLayout )
{
int screenWide, screenTall;
surface()->GetScreenSize(screenWide, screenTall);
m_bFirstPerformLayout = false;
int inset_x = screenWide * 0.15f;
int inset_y = screenWide * 0.04f;
SetBounds( inset_x, inset_y, screenWide - inset_x * 3, screenTall - inset_y * 2 );
}
m_pMenuBar->SetBounds( 20, 35, GetWide() - 40, 25 );
m_pEditor->SetBounds( 20, 65, GetWide() - 40, GetTall() - 85 );
}
void CKV_Editor_Frame::ApplySchemeSettings(vgui::IScheme *pScheme)
{
BaseClass::ApplySchemeSettings(pScheme);
}
void CKV_Editor_Frame::DoFileOpen()
{
m_FileSelectType = KV_FST_LAYOUT_OPEN;
// Pop up the dialog
FileOpenDialog *pFileDialog = new FileOpenDialog( NULL, "Open....", true );
pFileDialog->SetStartDirectory( m_pEditor->GetFileDirectory() );
pFileDialog->AddFilter( m_pEditor->GetFileFilter(), m_pEditor->GetFileFilterName(), true );
pFileDialog->AddActionSignalTarget( this );
pFileDialog->DoModal( false );
}
void CKV_Editor_Frame::DoFileSaveAs()
{
m_FileSelectType = KV_FST_LAYOUT_SAVE_AS;
// Pop up the dialog
FileOpenDialog *pFileDialog = new FileOpenDialog (NULL, "Save Map Layout", false);
pFileDialog->SetStartDirectory( m_pEditor->GetFileDirectory() );
pFileDialog->AddFilter( m_pEditor->GetFileFilter(), m_pEditor->GetFileFilterName(), true );
pFileDialog->AddActionSignalTarget(this);
pFileDialog->DoModal(true);
}
void CKV_Editor_Frame::OnFileSelected( const char *fullpath )
{
if ( m_FileSelectType == KV_FST_LAYOUT_SAVE_AS )
{
if ( m_pEditor->GetKeys() )
{
Q_snprintf( m_szLastFileName, sizeof( m_szLastFileName ), "%s", fullpath );
m_pEditor->GetKeys()->SaveToFile( g_pFullFileSystem, fullpath, "GAME" );
}
}
else if ( m_FileSelectType == KV_FST_LAYOUT_OPEN )
{
if ( m_pEditor->GetKeys() )
{
m_pEditor->GetKeys()->deleteThis();
}
KeyValues *pKeys = new KeyValues( "Keys" );
// load in the new one
if ( !pKeys->LoadFromFile( g_pFullFileSystem, fullpath ) )
{
MessageBox *pMessage = new MessageBox ("Error", "Error loading KeyValues", this);
pMessage->DoModal();
return;
}
m_pEditor->SetKeys( pKeys );
}
}
MessageMapItem_t CKV_Editor_Frame::m_MessageMap[] =
{
MAP_MESSAGE_CONSTCHARPTR(CKV_Editor_Frame, "FileSelected", OnFileSelected, "fullpath"),
};
IMPLEMENT_PANELMAP(CKV_Editor_Frame, Frame);
@@ -0,0 +1,77 @@
#ifndef _INCLUDED_KV_EDITOR_FRAME_H
#define _INCLUDED_KV_EDITOR_FRAME_H
#ifdef _WIN32
#pragma once
#endif
#include <vgui_controls/Frame.h>
#include <vgui_controls/ImageList.h>
#include <vgui_controls/SectionedListPanel.h>
#include <vgui_controls/PHandle.h>
#include <FileSystem.h>
#include "vgui/mousecode.h"
#include "vgui/IScheme.h"
#include "ConfigManager.h"
class CScrollingWindow;
class CKV_Editor_Base_Panel;
class CKV_Fit_Children_Panel;
class CKV_Editor;
namespace vgui
{
class PanelListPanel;
class ImagePanel;
class MenuBar;
class CheckButton;
class Button;
class Menu;
};
using namespace vgui;
enum KV_FileSelectType
{
KV_FST_LAYOUT_OPEN,
KV_FST_LAYOUT_SAVE_AS
};
//-----------------------------------------------------------------------------
// Purpose: Main dialog for visualizing and editing keyvalues
//-----------------------------------------------------------------------------
class CKV_Editor_Frame : public Frame
{
DECLARE_CLASS_SIMPLE( CKV_Editor_Frame, Frame );
public:
CKV_Editor_Frame( Panel *parent, const char *name );
virtual ~CKV_Editor_Frame();
virtual void PerformLayout();
virtual void ApplySchemeSettings(vgui::IScheme *pScheme);
// main menu bar
MenuBar *m_pMenuBar;
vgui::Menu *m_pFileMenu;
vgui::Menu *m_pToolsMenu;
// panel for editing keyvalues
CKV_Editor* m_pEditor;
DECLARE_PANELMAP();
void DoFileSaveAs();
void DoFileOpen();
void OnFileSelected(const char *fullpath);
KV_FileSelectType m_FileSelectType;
protected:
virtual void OnClose();
virtual void OnCommand( const char *command );
char m_szLastFileName[MAX_PATH];
bool m_bFirstPerformLayout;
};
#endif // _INCLUDED_KV_EDITOR_FRAME_H
@@ -0,0 +1,92 @@
#include "kv_fit_children_panel.h"
#include "KeyValues.h"
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
using namespace vgui;
//-----------------------------------------------------------------------------
// Constructor
//-----------------------------------------------------------------------------
CKV_Fit_Children_Panel::CKV_Fit_Children_Panel( Panel *parent, const char *name ) :
BaseClass( parent, name ),
m_iAutoPositionStartY( 5 ),
m_iBorder( 5 ),
m_iSpacing( 1 )
{
}
bool FitChildrenLessFunc::Less( CKV_Editor_Base_Panel* const &src1, CKV_Editor_Base_Panel* const &src2, void *pCtx )
{
const CKV_Editor_Base_Panel *pEditorPanel1 = dynamic_cast<const CKV_Editor_Base_Panel*>( src1 );
const CKV_Editor_Base_Panel *pEditorPanel2 = dynamic_cast<const CKV_Editor_Base_Panel*>( src2 );
if ( pEditorPanel1 && pEditorPanel2 )
{
return pEditorPanel1->GetSortOrder() < pEditorPanel2->GetSortOrder();
}
return src1->GetZPos() < src2->GetZPos();
}
void CKV_Fit_Children_Panel::PerformLayout()
{
BaseClass::PerformLayout();
if ( m_pFileSpecNode )
{
m_iAutoPositionStartY = m_pFileSpecNode->GetInt( "AutoPositionStartY", m_iAutoPositionStartY );
m_iBorder = m_pFileSpecNode->GetInt( "Border", m_iBorder );
m_iSpacing = m_pFileSpecNode->GetInt( "Spacing", m_iSpacing );
}
// make sure all children are laid out and find the extents of them
// lay out children in a vertical list
int cursor_y = m_iAutoPositionStartY;
int wide = 0, tall = cursor_y;
for ( int i = 0; i < m_AutoPositionPanels.Count(); i++ )
{
vgui::Panel *pPanel = m_AutoPositionPanels[i];
bool bNode = IsNodePanel( pPanel );
if ( bNode ) // extra gap before node panel
{
cursor_y += m_iSpacing * 2;
}
pPanel->SetPos( m_iBorder, cursor_y );
pPanel->InvalidateLayout( true );
int x, y;
pPanel->GetPos( x, y );
x += pPanel->GetWide();
y += pPanel->GetTall();
cursor_y += pPanel->GetTall() + m_iSpacing;
if ( bNode ) // extra gap after node panel
{
cursor_y += m_iSpacing * 2;
}
wide = MAX( wide, x );
tall = MAX( tall, y );
}
SetSize( wide + m_iBorder, tall + m_iBorder );
}
bool CKV_Fit_Children_Panel::IsNodePanel( vgui::Panel *pPanel )
{
return ( dynamic_cast< CKV_Fit_Children_Panel* > ( pPanel ) != NULL );
}
void CKV_Fit_Children_Panel::AddAutoPositionPanel( CKV_Editor_Base_Panel *pPanel )
{
m_AutoPositionPanels.Insert( pPanel );
}
void CKV_Fit_Children_Panel::RemoveAutoPositionPanel( CKV_Editor_Base_Panel *pPanel )
{
m_AutoPositionPanels.Remove( pPanel );
}
void CKV_Fit_Children_Panel::ClearAutoPositionPanels()
{
m_AutoPositionPanels.RemoveAll();
}
@@ -0,0 +1,40 @@
#ifndef _INCLUDED_KV_FIT_CHILDREN_PANEL_H
#define _INCLUDED_KV_FIT_CHILDREN_PANEL_H
#ifdef _WIN32
#pragma once
#endif
#include "kv_editor_base_panel.h"
class FitChildrenLessFunc
{
public:
bool Less( CKV_Editor_Base_Panel* const &pRoomTemplateLHS, CKV_Editor_Base_Panel* const &pRoomTemplateRHS, void *pCtx );
};
// a vgui panel that resizes to fit designated children, with some border
class CKV_Fit_Children_Panel : public CKV_Editor_Base_Panel
{
DECLARE_CLASS_SIMPLE( CKV_Fit_Children_Panel, CKV_Editor_Base_Panel );
public:
CKV_Fit_Children_Panel( Panel *parent, const char *name);
virtual void PerformLayout();
void AddAutoPositionPanel( CKV_Editor_Base_Panel *pPanel );
void RemoveAutoPositionPanel( CKV_Editor_Base_Panel *pPanel );
void ClearAutoPositionPanels();
bool IsNodePanel( vgui::Panel *pPanel );
// list of panels we should position in a list inside us
CUtlSortVector<CKV_Editor_Base_Panel*, FitChildrenLessFunc> m_AutoPositionPanels;
int m_iAutoPositionStartY;
CPanelAnimationVarAliasType( int, m_iBorder, "border", "5", "proportional_int" );
CPanelAnimationVarAliasType( int, m_iSpacing, "spacing", "1", "proportional_int" );
};
#endif // _INCLUDED_KV_FIT_CHILDREN_PANEL_H
@@ -0,0 +1,124 @@
#include "kv_leaf_panel.h"
#include <vgui_controls/TextEntry.h>
#include <vgui_controls/Button.h>
#include "KeyValues.h"
#include "kv_editor.h"
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
using namespace vgui;
DECLARE_BUILD_FACTORY( CKV_Leaf_Panel )
//-----------------------------------------------------------------------------
// Constructor
//-----------------------------------------------------------------------------
CKV_Leaf_Panel::CKV_Leaf_Panel( Panel *parent, const char *name ) : BaseClass( parent, name )
{
m_pLabel = new vgui::Label( this, "Label", "" );
m_pLabel->SetMouseInputEnabled( false );
m_pTextEntry = new vgui::TextEntry( this, "TextEntry" );
m_pTextEntry->SetAutoLocalize( false );
m_pDeleteButton = new vgui::Button( this, "DeleteButton", "X", this, "Delete" );
}
void CKV_Leaf_Panel::PerformLayout()
{
BaseClass::PerformLayout();
m_pLabel->SetBounds( 0, 0, 100, 20 );
m_pLabel->SizeToContents();
m_pLabel->InvalidateLayout( true );
int iLabelSpace = MAX( m_pLabel->GetWide() + 5, 100 );
int iExtraHeight = 0;
int iTextEntryX = iLabelSpace;
if ( m_pFileSpecNode && m_pFileSpecNode->FindKey( "TextEntryNewLine" ) )
{
iExtraHeight = m_pLabel->GetTall();
iTextEntryX = 0;
}
if ( m_pFileSpecNode && m_pFileSpecNode->FindKey( "Tall" ) )
{
m_pTextEntry->SetBounds( iTextEntryX, iExtraHeight, 390 - iTextEntryX, m_pFileSpecNode->GetInt( "Tall" ) );
}
else
{
m_pTextEntry->SetBounds( iTextEntryX, iExtraHeight, 390 - iTextEntryX, 20 );
}
SetSize( 420, m_pTextEntry->GetTall() + iExtraHeight );
int iDeleteWidth = 20;
m_pDeleteButton->SetBounds( GetWide() - (iDeleteWidth + 5), 2, iDeleteWidth, 16 );
}
void CKV_Leaf_Panel::ApplySchemeSettings(vgui::IScheme *pScheme)
{
BaseClass::ApplySchemeSettings( pScheme );
m_pLabel->SetPaintBackgroundEnabled( false );
SetPaintBackgroundEnabled( false );
m_pDeleteButton->SetVisible( m_bAllowDeletion );
}
void CKV_Leaf_Panel::UpdatePanel()
{
if ( m_pFileSpecNode )
{
m_pDeleteButton->SetVisible( !!m_pFileSpecNode->FindKey( "Deletable" ) );
}
if ( !m_pKey )
{
m_pLabel->SetText( "INVALID KEY" );
m_pTextEntry->SetText( "INVALID KEY" );
return;
}
if ( m_pFileSpecNode && m_pFileSpecNode->FindKey( "FriendlyName" ) )
{
m_pLabel->SetText( m_pFileSpecNode->GetString( "FriendlyName" ) );
}
else
{
m_pLabel->SetText( m_pKey->GetName() );
}
m_pTextEntry->SetText( m_pKey->GetString() );
if ( m_pFileSpecNode->GetInt( "ReadOnly", 0 ) == 1 )
{
m_pTextEntry->SetEditable( false );
m_pTextEntry->SetEnabled( false );
}
}
// update our key when the text entry changes
void CKV_Leaf_Panel::TextEntryChanged( vgui::Panel* pTextEntry )
{
if ( pTextEntry != m_pTextEntry )
return;
if ( !m_pKey )
{
return;
}
char buf[ 2048 ];
m_pTextEntry->GetText( buf, 2048 );
m_pKey->SetStringValue( buf );
PostActionSignal( new KeyValues( "command", "command", "KeyValuesChanged" ) );
}
void CKV_Leaf_Panel::OnCommand( const char *command )
{
if ( !Q_stricmp( command, "Delete" ) && m_pKeyParent && m_bAllowDeletion )
{
m_pKeyParent->RemoveSubKey( m_pKey );
m_pKey->deleteThis();
m_pEditor->OnKeyDeleted();
return;
}
BaseClass::OnCommand( command );
}
@@ -0,0 +1,35 @@
#ifndef _INCLUDED_KV_LEAF_PANEL_H
#define _INCLUDED_KV_LEAF_PANEL_H
#ifdef _WIN32
#pragma once
#endif
#include "kv_editor_base_panel.h"
namespace vgui
{
class TextEntry;
class Label;
};
// a vgui panel for showing a generic leaf
class CKV_Leaf_Panel : public CKV_Editor_Base_Panel
{
DECLARE_CLASS_SIMPLE( CKV_Leaf_Panel, CKV_Editor_Base_Panel );
public:
CKV_Leaf_Panel( Panel *parent, const char *name);
virtual void PerformLayout();
virtual void UpdatePanel();
virtual void ApplySchemeSettings(vgui::IScheme *pScheme);
virtual void OnCommand( const char *command );
MESSAGE_FUNC_PTR( TextEntryChanged, "TextChanged", panel );
vgui::TextEntry *m_pTextEntry;
vgui::Label *m_pLabel;
vgui::Button* m_pDeleteButton;
};
#endif // _INCLUDED_KV_LEAF_PANEL_H
@@ -0,0 +1,167 @@
#include "kv_node_panel.h"
#include <vgui_controls/Label.h>
#include <vgui_controls/Button.h>
#include "kv_editor.h"
#include "KeyValues.h"
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
using namespace vgui;
DECLARE_BUILD_FACTORY( CKV_Node_Panel )
//-----------------------------------------------------------------------------
// Constructor
//-----------------------------------------------------------------------------
CKV_Node_Panel::CKV_Node_Panel( Panel *parent, const char *name ) :
BaseClass( parent, name ),
m_iLabelInsetX( 2 ),
m_iLabelInsetY( 2 )
{
m_pLabel = new vgui::Label( this, "Label", "" );
m_pLabel->SetMouseInputEnabled( false );
m_pDeleteButton = new vgui::Button( this, "DeleteButton", "X", this, "Delete" );
SetKeyBoardInputEnabled( false );
m_iAutoPositionStartY = 30;
}
void CKV_Node_Panel::PerformLayout()
{
BaseClass::PerformLayout();
if ( m_pFileSpecNode )
{
m_iLabelInsetX = m_pFileSpecNode->GetInt( "LabelInsetX", m_iLabelInsetX );
m_iLabelInsetY = m_pFileSpecNode->GetInt( "LabelInsetY", m_iLabelInsetY );
}
m_pLabel->SetBounds( m_iLabelInsetX * 2, m_iLabelInsetY, 300, 16 );
int iDeleteWidth = 20;
m_pDeleteButton->SetBounds( GetWide() - (iDeleteWidth + 5), m_iLabelInsetY, iDeleteWidth, 16 );
int wide = GetWide();
int cursor_y = GetTall();
cursor_y -= m_iSpacing;
for ( int i = 0; i < m_pAddButtons.Count(); i++ )
{
vgui::Button *pPanel = m_pAddButtons[i];
if ( pPanel )
{
pPanel->SetPos( m_iBorder, cursor_y );
pPanel->SetSize( 300, 25 );
pPanel->InvalidateLayout( true );
int x, y;
pPanel->GetPos( x, y );
x += pPanel->GetWide();
y += pPanel->GetTall();
cursor_y += pPanel->GetTall() + m_iSpacing;
wide = MAX( wide, x );
}
}
cursor_y += m_iSpacing * 2;
SetSize( wide, cursor_y );
}
void CKV_Node_Panel::ApplySchemeSettings(vgui::IScheme *pScheme)
{
BaseClass::ApplySchemeSettings( pScheme );
m_pLabel->SetPaintBackgroundEnabled( false );
m_pDeleteButton->SetVisible( m_bAllowDeletion );
}
void CKV_Node_Panel::UpdatePanel()
{
if ( m_pFileSpecNode )
{
m_pDeleteButton->SetVisible( !m_pFileSpecNode->FindKey( "Autocreate" ) );
}
// clear out add buttons
for ( int i = 0; i < m_pAddButtons.Count(); i++ )
{
m_pAddButtons[i]->SetVisible( false );
m_pAddButtons[i]->MarkForDeletion();
}
m_pAddButtons.Purge();
if ( !m_pKey )
{
m_pLabel->SetText( "INVALID KEY" );
return;
}
if ( m_pFileSpecNode && m_pFileSpecNode->FindKey( "FriendlyName" ) )
{
m_pLabel->SetText( m_pFileSpecNode->GetString( "FriendlyName" ) );
m_pLabel->SetVisible( Q_strlen( m_pFileSpecNode->GetString( "FriendlyName" ) ) > 0 );
}
else
{
m_pLabel->SetText( m_pKey->GetName() );
}
// add add buttons
if ( m_pFileSpecNode )
{
// go through all _Node or _Leaf children of our filespec node
for ( KeyValues *pSubKey = m_pFileSpecNode->GetFirstSubKey(); pSubKey; pSubKey = pSubKey->GetNextKey() )
{
if ( Q_stricmp( pSubKey->GetName(), "_Node" ) && Q_stricmp( pSubKey->GetName(), "_Leaf" ) )
continue;
// If it's unique, then see if we already have one in our m_pKey.
bool bMakeButton = true;
if ( pSubKey->FindKey( "Unique" ) )
{
for ( KeyValues *pKeyChild = m_pKey->GetFirstSubKey(); pKeyChild; pKeyChild = pKeyChild->GetNextKey() )
{
if ( !Q_stricmp( pKeyChild->GetName(), pSubKey->GetString( "Name" ) ) )
{
bMakeButton = false;
break;
}
}
}
if ( bMakeButton )
{
char buffer[256];
if ( m_pFileSpecNode && pSubKey->FindKey( "FriendlyAddButtonText" ) )
{
Q_snprintf( buffer, sizeof( buffer ), "%s", pSubKey->GetString( "FriendlyAddButtonText", "ADD BUTTON ERROR" ) );
}
else
{
Q_snprintf( buffer, sizeof( buffer ), "Add %s", pSubKey->GetString( "FriendlyName", pSubKey->GetString( "Name", "Unknown key" ) ) );
}
vgui::Button *pAdd = new vgui::Button( this, "AddButton", buffer, this );
pAdd->SetCommand( new KeyValues( "AddButtonPressed", "szKeyName", pSubKey->GetString( "Name", "Unknown key" ) ) );
m_pAddButtons.AddToTail( pAdd );
}
}
}
}
void CKV_Node_Panel::OnCommand( const char *command )
{
if ( !Q_stricmp( command, "Delete" ) && m_pKeyParent && m_bAllowDeletion )
{
m_pKeyParent->RemoveSubKey( m_pKey );
m_pKey->deleteThis();
m_pEditor->OnKeyDeleted();
return;
}
BaseClass::OnCommand( command );
}
void CKV_Node_Panel::OnAddButtonPressed( const char *szKeyName )
{
// Add new subkey of name matching button
m_pEditor->AddToKey( m_pFileSpecNode, m_pKey, szKeyName );
}
@@ -0,0 +1,40 @@
#ifndef _INCLUDED_KV_NODE_PANEL_H
#define _INCLUDED_KV_NODE_PANEL_H
#ifdef _WIN32
#pragma once
#endif
#include "kv_fit_children_panel.h"
namespace vgui
{
class Label;
class Button;
};
// a vgui panel for showing a generic leaf
class CKV_Node_Panel : public CKV_Fit_Children_Panel
{
DECLARE_CLASS_SIMPLE( CKV_Node_Panel, CKV_Fit_Children_Panel );
public:
CKV_Node_Panel( Panel *parent, const char *name);
virtual void PerformLayout();
virtual void UpdatePanel();
virtual void ApplySchemeSettings(vgui::IScheme *pScheme);
virtual void OnCommand( const char *command );
vgui::Label *m_pLabel;
vgui::Button* m_pDeleteButton;
CUtlVector<vgui::Button*> m_pAddButtons;
MESSAGE_FUNC_CHARPTR( OnAddButtonPressed, "AddButtonPressed", szKeyName );
CPanelAnimationVarAliasType( int, m_iLabelInsetX, "LabelInsetX", "2", "proportional_int" );
CPanelAnimationVarAliasType( int, m_iLabelInsetY, "LabelInsetY", "2", "proportional_int" );
};
#endif // _INCLUDED_KV_NODE_PANEL_H