Coded keypad

From Valve Developer Community
Jump to: navigation, search

A functional keypad for the Source engine. Inspirated on SysOp's keypad code for GoldSrc, I made my own for the Source engine.

Features:

  • Close and clear buttons.
  • Hover and click effects on the buttons.
  • Customizable keypad text.
  • Typed code can be set to be hidden.
  • Has outputs for correct and incorrect codes.

Coded on Source SDK 2013 SinglePlayer Episodic, but it should be compatible for NonEpisodic and Multiplayer codes. Credit me (Maestro Fénix) and SysOp if you are going to use it on your mod. This is for everyone.

You can see a video demostration of it here.

Client

vgui_keypad.h

//==========================================================================//
//
// Purpose: VGUI Keypad made by Maestro Fénix 2015
//
// $NoKeywords: $
//===========================================================================//

using namespace vgui;

#include <vgui/IVGui.h>
#include <vgui_controls/Frame.h>
#include <vgui_controls/Button.h>
#include <vgui_controls/ImagePanel.h>
#include <vgui_controls/Label.h>
#include <vgui_controls\Panel.h>
#include <vgui\ISurface.h> 
#include "usermessages.h" //For user messages at keypad
#include "hud_macros.h" //Needed for networking messages
#include "hudelement.h" //Needed for networking messages
#include "iclientmode.h" //Needed for getting the viewport of the player
#include "engine/IEngineSound.h" //For sounds

class CVgui_keypad : public vgui::Frame, public CHudElement
{
	DECLARE_CLASS(CVgui_keypad, vgui::Frame);

public:
	CVgui_keypad(const char *pElementName); 	// Constructor vgui::VPANEL parent
	~CVgui_keypad(){};				// Destructor

	void CheckPass(int number);
	void OnTick();
	void Init();
	void MsgFunc_KeypadHandler(bf_read &msg);

protected:
	//VGUI overrides:
	void PaintBackground();
	void Paint();
	virtual void OnCommand(const char* pcCommand);
	virtual void OnThink(void);

private:
	//Other used VGUI control Elements:
	ImagePanel *m_pBackgroundPanel;
	Button *m_pCloseButton;
	Button *m_pClearButton;
	Button *m_pMenuButtons[100];
	Label *m_pScreenTitle;
	Label *m_pLabel;
	ImagePanel *m_imgMenuButtons[100];
	ImagePanel *m_imgClearButton;
	ImagePanel *m_imgCloseButton;
	char szCode[32];
	int m_pPressedNumbers;
	char szEnteredNumbers[32];
	bool m_pHidePass;
	char szFrameLabel[32];
	bool m_showKeypad;
};

vgui_keypad.cpp

//==========================================================================//
//
// Purpose: VGUI Keypad made by Maestro Fénix 2015
//
// $NoKeywords: $
//===========================================================================//
#include "cbase.h"
#include "vgui_keypad.h"

// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"

//Disable this and all the related for debug purposes
//ConVar cl_showkeypad("cl_showkeypad", "0", FCVAR_HIDDEN, "Toggles keypad panel <state>");

DECLARE_HUDELEMENT(CVgui_keypad);
DECLARE_HUD_MESSAGE(CVgui_keypad, KeypadHandler)

CVgui_keypad::CVgui_keypad(const char *pElementName) : CHudElement(pElementName), BaseClass(NULL, "Vgui_keypad") //vgui::VPANEL parent
{	

	m_showKeypad = false;

	vgui::Panel *parent = g_pClientMode->GetViewport();
	SetParent(parent);

	SetTitleBarVisible(false);
	SetMinimizeButtonVisible(false);
	SetMaximizeButtonVisible(false);
	SetCloseButtonVisible(false);
	SetSizeable(false);
	SetMoveable(false);
	SetSize(300, 600);

	vgui::ivgui()->AddTickSignal(GetVPanel(), 100);

	SetScheme(vgui::scheme()->LoadSchemeFromFile("resource/SourceScheme.res", "SourceScheme"));

	LoadControlSettings("resource/ui/keypad.res");

	//Keypad background
	m_pBackgroundPanel = FindControl<ImagePanel>("KeypadBackground", true); //Searches at the RES file the button, so we can modify it here
	m_pBackgroundPanel->SetImage(scheme()->GetImage("keypad/keypad_base", false));
	m_pBackgroundPanel->SetSize(512, 1024);

	//Close Button
	m_pCloseButton = FindControl<Button>("ButtonCls", true);
	m_pCloseButton->SetDepressedSound("buttons/blip1.wav");
	m_pCloseButton->SetAlpha(0);
	m_pCloseButton->SetSize(64, 64);
	m_imgCloseButton = FindControl<ImagePanel>("ButtonClsImg", true);
	m_imgCloseButton->SetImage("keypad/keypad_close");
	m_imgCloseButton->SetSize(64, 64);

	//Clear Button
	m_pClearButton = FindControl<Button>("ButtonClr", true);
	m_pClearButton->SetAlpha(0);
	m_pClearButton->SetDepressedSound("buttons/blip1.wav");
	m_pClearButton->SetSize(64, 64);
	m_imgClearButton = FindControl<ImagePanel>("ButtonClrImg", true);
	m_imgClearButton->SetImage("keypad/keypad_clear");
	m_imgClearButton->SetSize(64, 64);

	//Code viewport
	m_pLabel = FindControl<Label>("KeypadLabel", true);
	m_pLabel->SetVisible(true);
	m_pLabel->SetText("");
	IScheme *pScheme = scheme()->GetIScheme(GetScheme());
	HFont font = pScheme->GetFont("CreditsText");
	m_pLabel->SetFont(font);
	m_pLabel->SetWide(512);

	//Keypad screen text
	m_pScreenTitle = FindControl<Label>("KeypadLabelTitle", true);
	m_pScreenTitle->SetVisible(true);
	font = pScheme->GetFont("CreditsText");
	m_pScreenTitle->SetFont(font);
	m_pScreenTitle->SetWide(512);

	//NumPad Buttons
	//FUgly, find a way to do it on a loop
	m_pMenuButtons[0] = FindControl<Button>("KeypadButton0", true);
	m_pMenuButtons[1] = FindControl<Button>("KeypadButton1", true);
	m_pMenuButtons[2] = FindControl<Button>("KeypadButton2", true);
	m_pMenuButtons[3] = FindControl<Button>("KeypadButton3", true);
	m_pMenuButtons[4] = FindControl<Button>("KeypadButton4", true);
	m_pMenuButtons[5] = FindControl<Button>("KeypadButton5", true);
	m_pMenuButtons[6] = FindControl<Button>("KeypadButton6", true);
	m_pMenuButtons[7] = FindControl<Button>("KeypadButton7", true);
	m_pMenuButtons[8] = FindControl<Button>("KeypadButton8", true);
	m_pMenuButtons[9] = FindControl<Button>("KeypadButton9", true);

	m_imgMenuButtons[0] = FindControl<ImagePanel>("KeypadButton0img", true);
	m_imgMenuButtons[0]->SetImage("keypad/keypad_0");

	m_imgMenuButtons[1] = FindControl<ImagePanel>("KeypadButton1img", true);
	m_imgMenuButtons[1]->SetImage("keypad/keypad_1");

	m_imgMenuButtons[2] = FindControl<ImagePanel>("KeypadButton2img", true);
	m_imgMenuButtons[2]->SetImage("keypad/keypad_2");

	m_imgMenuButtons[3] = FindControl<ImagePanel>("KeypadButton3img", true);
	m_imgMenuButtons[3]->SetImage("keypad/keypad_3");

	m_imgMenuButtons[4] = FindControl<ImagePanel>("KeypadButton4img", true);
	m_imgMenuButtons[4]->SetImage("keypad/keypad_4");

	m_imgMenuButtons[5] = FindControl<ImagePanel>("KeypadButton5img", true);
	m_imgMenuButtons[5]->SetImage("keypad/keypad_5");

	m_imgMenuButtons[6] = FindControl<ImagePanel>("KeypadButton6img", true);
	m_imgMenuButtons[6]->SetImage("keypad/keypad_6");

	m_imgMenuButtons[7] = FindControl<ImagePanel>("KeypadButton7img", true);
	m_imgMenuButtons[7]->SetImage("keypad/keypad_7");

	m_imgMenuButtons[8] = FindControl<ImagePanel>("KeypadButton8img", true);
	m_imgMenuButtons[8]->SetImage("keypad/keypad_8");

	m_imgMenuButtons[9] = FindControl<ImagePanel>("KeypadButton9img", true);
	m_imgMenuButtons[9]->SetImage("keypad/keypad_9");

	for (int i = 0; i < 10; i++)
	{
		m_pMenuButtons[i]->SetDepressedSound("buttons/blip1.wav");
		m_pMenuButtons[i]->SetAlpha(0);
		m_pMenuButtons[i]->SetSize(32, 32);
		m_imgMenuButtons[i]->SetSize(32, 32);
	}
}

void CVgui_keypad::Init()
{
	//Gets the message sent from from func_keypad: code, keypad title and if code must be hidden
	HOOK_HUD_MESSAGE(CVgui_keypad, KeypadHandler);
}

void CVgui_keypad::PaintBackground()
{
	//vgui::surface()->DrawSetColor(255, 0, 0, 255);	
}

void CVgui_keypad::Paint()
{
	//Change this value if you want a longer pass
	if (m_pPressedNumbers == 4)
	{
		//Disable to check into DEV mode if the codes are correct

		//Transforms the char into a int so we really get the number itself
		/*char * numberC;
		int numberN = strtol(szEnteredNumbers, &numberC, 10);
		DevMsg("Code entered is: %i \n", numberN);
		numberN = strtol(szCode, &numberC, 10);
		DevMsg("Correct code is: %i \n", numberN);*/

		//Checks if the code is the good one
		if (strcmp(szEnteredNumbers, szCode))
		{
			engine->ClientCmd("keypad_codematch");

			/*Mysteriously enough, as soon as keypad_codematch is fired,
			it runs the stuff at the other side. That's why stuff
			is mixed on both places*/

			//Wrong code is set
			surface()->PlaySound("buttons/button2.wav");
			m_pPressedNumbers = 0;
		}
		else
		{
			engine->ClientCmd("keypad_codedismatch");

			/*Mysteriously enough, as soon as keypad_codedismatch is fired,
			it runs the stuff at the other side. That's why stuff
			is mixed on both places*/

			//Correct code is set
			surface()->PlaySound("buttons/button5.wav");
			SetVisible(false);
			m_showKeypad = false;
			//cl_showkeypad.SetValue(0);
			m_pPressedNumbers = 0;
		}
	}

	//Makes buttons go grey if they are pushed
	for (int i = 0; i < 10; i++)
	{
		if (m_pMenuButtons[i]->IsArmed())
		{
			m_imgMenuButtons[i]->SetAlpha(255);
		}
		else
		{
			m_imgMenuButtons[i]->SetAlpha(150);
		}
	}
	
	if (m_pClearButton->IsArmed())
	{
		m_imgClearButton->SetAlpha(255);
	}
	else
	{
		m_imgClearButton->SetAlpha(150);
	}

	if (m_pCloseButton->IsArmed())
	{
		m_imgCloseButton->SetAlpha(255);
	}
	else
	{
		m_imgCloseButton->SetAlpha(150);
	}
}

void CVgui_keypad::OnTick()
{
	BaseClass::OnTick();
}

void CVgui_keypad::OnCommand(const char* pcCommand)
{
	BaseClass::OnCommand(pcCommand);

	if (!Q_stricmp(pcCommand, "clear"))
	{
		m_pPressedNumbers = 0;
		m_pLabel->SetText("");
	}
		
	if (!Q_stricmp(pcCommand, "turnoff"))
	{ 
		//cl_showkeypad.SetValue(0);
		m_showKeypad = false;
	}
		
	//ToDo: Search a better way to do this
	if (!Q_stricmp(pcCommand, "0"))
	{
		CheckPass(0);
	}
	if (!Q_stricmp(pcCommand, "1"))
	{
		CheckPass(1);
	}
	if (!Q_stricmp(pcCommand, "2"))
	{
		CheckPass(2);
	}
	if (!Q_stricmp(pcCommand, "3"))
	{
		CheckPass(3);
	}
	if (!Q_stricmp(pcCommand, "4"))
	{
		CheckPass(4);
	}
	if (!Q_stricmp(pcCommand, "5"))
	{
		CheckPass(5);
	}
	if (!Q_stricmp(pcCommand, "6"))
	{
		CheckPass(6);
	}
	if (!Q_stricmp(pcCommand, "7"))
	{
		CheckPass(7);
	}
	if (!Q_stricmp(pcCommand, "8"))
	{
		CheckPass(8);
	}
	if (!Q_stricmp(pcCommand, "9"))
	{
		CheckPass(9);
	}
}

void CVgui_keypad::CheckPass(int number)
{
	//Disable if you wanna check on DEV mode if the number pressed is correct
	//DevMsg("Number entered is: %i \n", number);

	//We need the number as a string
	char numberN[8];
	sprintf(numberN, "%i", number);

	//Used to check how many numbers we are adding
	m_pPressedNumbers++;

	//Add the new number, otherwise, display the first one
	if (m_pPressedNumbers >1)
		strcat(szEnteredNumbers, numberN);
	else
		strcpy(szEnteredNumbers, numberN);

	//Disable if you wanna check on DEV mode if the code is correct
	//DevMsg("Code entered is: %i \n", szEnteredNumbers);

	m_pLabel->SetVisible(true);

	//If is enabled to hide numbers, do so
	if (m_pHidePass)
	{
		//SysOp: so fucking lazy, blame me
		if (m_pPressedNumbers == 1)
			m_pLabel->SetText("*");
		if (m_pPressedNumbers == 2)
			m_pLabel->SetText("**");
		if (m_pPressedNumbers == 3)
			m_pLabel->SetText("***");
		if (m_pPressedNumbers == 4)
			m_pLabel->SetText("****");
	}
	else
	{ 
		//Show the number itself then
		m_pLabel->SetText(szEnteredNumbers);
	}
}

// declare the user message handler
void CVgui_keypad::MsgFunc_KeypadHandler(bf_read &msg)
{
	msg.ReadString(szCode, sizeof(szCode));

	msg.ReadString(szFrameLabel, sizeof(szFrameLabel));
	m_pScreenTitle->SetText(szFrameLabel);

	m_pHidePass = msg.ReadByte();

	//cl_showkeypad.SetValue(1);
	m_showKeypad = true;
}

void CVgui_keypad::OnThink(void)
{
	if (m_showKeypad) //cl_showkeypad.GetBool()
	{
		SetVisible(true);
		SetMouseInputEnabled(true);

		//Fix for known VGUI bug with SetMouseInputEnabled making the keyboard not accepting two or more pressed buttons
		SetKeyBoardInputEnabled(true);
	}
	else
	{
		SetVisible(false);
		SetMouseInputEnabled(false);
		
		//Fix for known VGUI bug with SetMouseInputEnabled making the keyboard not accepting two or more pressed buttons
		SetKeyBoardInputEnabled(false);
	}

	BaseClass::OnThink();
}

Server

point_keypad.h

//==========================================================================//
//
// Purpose: VGUI Keypad made by Maestro Fénix 2015
//
// $NoKeywords: $
//===========================================================================//
class CPointKeypad : public CPointEntity
{
public:
	DECLARE_CLASS(CPointKeypad, CPointEntity);

	void	Spawn(void);
	void	Precache(void);

	bool KeyValue(const char *szKeyName, const char *szValue);
	
	//BOOL		m_bNeedsUpdate;

	string_t	s_code;
	string_t	s_frame_label;

	bool		b_hide_pass;

	void FireTarget(void);
	void WrongCode(void);


private:
	void Enable(inputdata_t &inputdata);

	COutputEvent OnCorrectCode;
	COutputEvent OnIncorrectCode;

	DECLARE_DATADESC();
};

point_keypad.cpp

//==========================================================================//
//
// Purpose: VGUI Keypad made by Maestro Fénix 2015
//
// $NoKeywords: $
//===========================================================================//

#include "cbase.h"


#include "point_keypad.h"

#include "baseentity.h"
#include "entityinput.h"
#include "entityoutput.h"
#include "recipientfilter.h"
#include "usermessages.h" //For user messages at keypad


// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"

LINK_ENTITY_TO_CLASS(point_keypad, CPointKeypad);

BEGIN_DATADESC(CPointKeypad)
	DEFINE_FIELD(s_code, FIELD_STRING),
	DEFINE_FIELD(s_frame_label, FIELD_STRING),
	DEFINE_FIELD(b_hide_pass, FIELD_BOOLEAN),

	//Inputs
	DEFINE_INPUTFUNC(FIELD_VOID, "Enable", Enable),

	//Outputs
	DEFINE_OUTPUT(OnCorrectCode, "OnCorrectCode"),
	DEFINE_OUTPUT(OnIncorrectCode, "OnIncorrectCode")
END_DATADESC()



void CPointKeypad::Spawn(void)
{

	Precache();

	SetSolid(SOLID_NONE);
	SetMoveType(MOVETYPE_NONE);

}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CPointKeypad::Precache(void)
{
}

//-----------------------------------------------------------------------------
// Purpose: Cache user-entity-field values until spawn is called.
// Input  : szKeyName - 
//			szValue - 
// Output : Returns true if handled, false if not.
//-----------------------------------------------------------------------------
bool CPointKeypad::KeyValue(const char *szKeyName, const char *szValue)
{
	if (FStrEq(szKeyName, "code"))
	{
		s_code = AllocPooledString(szValue);
	}
	else if (FStrEq(szKeyName, "label"))
	{
		s_frame_label = AllocPooledString(szValue);
	}
	else if (FStrEq(szKeyName, "hide_pass"))
	{
		b_hide_pass = (atoi(szValue) !=0 );
	}
	else
	{
		return CPointEntity::KeyValue(szKeyName, szValue);
	}
	return true;
}

void CPointKeypad::Enable(inputdata_t &inputdata)
{
	
	CBasePlayer *pPlayer = NULL;
	if (inputdata.pActivator && inputdata.pActivator->IsPlayer())
	{
		pPlayer = ToBasePlayer(inputdata.pActivator);
	}
	else
	{
		pPlayer = UTIL_GetLocalPlayer();
	}

	CSingleUserRecipientFilter user(pPlayer);
	//user.MakeReliable(); Needed?
	UserMessageBegin(user, "KeypadHandler");
	WRITE_STRING(STRING(s_code));//password
	WRITE_STRING(STRING(s_frame_label));//what's displayed on LCD screen
	WRITE_BOOL(b_hide_pass);//hide password option
	MessageEnd();
}


//-----------------------------------------------------------------------------
// Purpose: this function is callled when the user introduced the correct code and vgui sent a command(keypad_codematch) and
// the command(keypad_codematch) checks if there is a keypad that needs that code(see player.cpp)
//-----------------------------------------------------------------------------
void CPointKeypad::FireTarget(void)
{
	OnCorrectCode.FireOutput(this, this);
}


//-----------------------------------------------------------------------------
// Purpose: this function is callled when the user introduced the incorrect code and vgui sent a command(keypad_codedismatch) and
// the command(keypad_codedismatch) checks if there is a keypad that needs that code(see player.cpp)
//-----------------------------------------------------------------------------
void CPointKeypad::WrongCode(void)
{
	OnIncorrectCode.FireOutput(this, this);
}

player.cpp

Go to player.cpp, and search for this function:

else if ( stricmp( cmd, "playerperf" ) == 0 )

Paste the following code after it (in the case you can't find it, just place it inside the bool CBasePlayer::ClientCommand( const CCommand &args ) function ):

        //Keypad
	else if (stricmp(cmd, "keypad_codematch"))
	{

		CBaseEntity *pEntity = NULL;

		//while ((pEntity = gEntList.FindEntityByClassnameWithin(pEntity, "player", GetLocalOrigin(), 512)) != NULL)
		//	CBasePlayer *pPlayer = ToBasePlayer(pEntity);


		while ((pEntity = gEntList.FindEntityInSphere(pEntity, GetLocalOrigin(), 512)) != NULL)//512 
		{
			if (FClassnameIs(pEntity, "point_keypad"))
			{
				edict_t *pFind;
				pFind = pEntity->edict();

				CBaseEntity *pEnt = CBaseEntity::Instance(pFind);
				CPointKeypad *pKeypadSettings = (CPointKeypad *)pEnt;

					//DevMsg("code_match - firing FireTarget\n");

					pKeypadSettings->FireTarget();

					return true;
			}
		}
	}
	else if (stricmp(cmd, "keypad_codedismatch"))
	{
		CBaseEntity *pEntity = NULL;

		//	while ((pEntity = gEntList.FindEntityByClassnameWithin(pEntity, "player", GetLocalOrigin(), 512)) != NULL)
		//	CBasePlayer *pPlayer = ToBasePlayer(pEntity);

		//same as above, but calls a different function
		while ((pEntity = gEntList.FindEntityInSphere(pEntity, GetLocalOrigin(), 512)) != NULL)//512
		{
			if (FClassnameIs(pEntity, "point_keypad"))
			{
				edict_t *pFind;
				pFind = pEntity->edict();

				CBaseEntity *pEnt = CBaseEntity::Instance(pFind);
				CPointKeypad *pKeypadSettings = (CPointKeypad *)pEnt;

					//DevMsg("code_dismatch - firing WrongCode\n");

					pKeypadSettings->WrongCode();

					return true;
			}
		}
	}

Shared

hl2_usermessages.cpp

Go to shared/hl2/hl2_usermessages.cpp, and add the following inside the "void RegisterUserMessages( void )" function:

 usermessages->Register("KeypadHandler", -1); //Keypad

FGD

Add this to your mod.fgd:

@PointClass base(Targetname) size(-8 -8 -8, 8 8 8) = point_keypad : "An interactive keypad that fires outputs depending if is correct " +
"or not the introduced code."
[
	//my_target(string) : "Target" : ""
	code(string) : "Code (MAX 4!)" : "1234"
	label(string) : "Label" : "Mah keypad"
	hide_pass(choices) : "Hide password?" : "1" =
	[
		"0" : 	"No"
		"1": 	"Yes"
	]
	
	// Inputs
	input Enable(void) : "Enables the keypad."
	
	// Outputs
	output OnCorrectCode(void) : "Fired when the code is correct."
	output OnIncorrectCode(void) : "Fired when the code is incorrect."
]

keypad.res

Place the following RES file in resource/ui/:

"resource/ui/keypad.res"
{
	"Vgui_keypad"
	{
		"ControlName"		"Frame"
		"fieldName"		"Vgui_keypad"
		"xpos"		"c-150"
		"ypos"		"c-200"
		"visible"		"0"
		"enabled"		"0"
	}
	"frame_topGrip" 
	{
		"ControlName"		"Panel"
		"fieldName"		"frame_topGrip"
		"visible"		"0"
		"enabled"		"0"
	}
	"frame_bottomGrip"
	{
		"ControlName"		"Panel"
		"fieldName"		"frame_bottomGrip"
		"visible"		"0"
		"enabled"		"0"
		"tabPosition"		"0"
	}
	"frame_leftGrip"
	{
		"ControlName"		"Panel"
		"fieldName"		"frame_leftGrip"
		"visible"		"0"
		"enabled"		"0"
	}
	"frame_rightGrip"
	{
		"ControlName"		"Panel"
		"fieldName"		"frame_rightGrip"
		"visible"		"0"
		"enabled"		"0"
	}
	"frame_tlGrip"
	{
		"ControlName"		"Panel"
		"fieldName"		"frame_tlGrip"
		"visible"		"0"
		"enabled"		"0"
	}
	"frame_trGrip"
	{
		"ControlName"		"Panel"
		"fieldName"		"frame_trGrip"
		"visible"		"0"
		"enabled"		"0"
	}
	"frame_blGrip"
	{
		"ControlName"		"Panel"
		"fieldName"		"frame_blGrip"
		"visible"		"0"
		"enabled"		"0"
	}
	"frame_brGrip"
	{
		"ControlName"		"Panel"
		"fieldName"		"frame_brGrip"
		"visible"		"0"
		"enabled"		"0"
	}
	"frame_caption"
	{
		"ControlName"		"Panel"
		"fieldName"		"frame_caption"
		"visible"		"0"
		"enabled"		"0"
	}
	"frame_minimize"
	{
		"ControlName"		"Button"
		"fieldName"		"frame_minimize"
		"visible"		"0"
		"enabled"		"0"
	}
	"frame_maximize"
	{
		"ControlName"		"Button"
		"fieldName"		"frame_maximize"
		"visible"		"0"
		"enabled"		"0"
	}
	"frame_mintosystray"
	{
		"ControlName"		"Button"
		"fieldName"		"frame_mintosystray"
		"visible"		"0"
		"enabled"		"0"
	}
	"frame_close"
	{
		"ControlName"		"Button"
		"fieldName"		"frame_close"
		"visible"		"0"
		"enabled"		"0"
	}
	"frame_menu"
	{
		"ControlName"		"FrameSystemButton"
		"fieldName"		"frame_menu"
		"visible"		"0"
		"enabled"		"0"
	}
	"KeypadBackground"
	{
		"ControlName"		"ImagePanel"
		"fieldName"		"KeypadBackground"
		"xpos"		"-4"
		"ypos"		"34"
		"zpos"		"1"
		"wide"		"227"
		"tall"		"455"

	}
	"KeypadLabelTitle"
	{
		"ControlName"		"Label"
		"fieldName"		"KeypadLabelTitle"
		"xpos"		"43"
		"ypos"		"100"
		"zpos"		"2"
		"wide"		"227"
		"tall"		"13"
	}
	"KeypadLabel"
	{
		"ControlName"		"Label"
		"fieldName"		"KeypadLabel"
		"xpos"		"43"
		"ypos"		"130"
		"zpos"		"2"
		"wide"		"227"
		"tall"		"13"
	}
	"KeypadButton0"
	{
		"ControlName"		"Button"
		"fieldName"		"KeypadButton0"
		"xpos"		"105"
		"ypos"		"320"
		"zpos"		"3"
		"command"	"0"
	}
	"KeypadButton0img"
	{
		"ControlName"		"ImagePanel"
		"fieldName"		"KeypadButton0img"
		"xpos"		"105"
		"ypos"		"320"
		"zpos"		"2"
	}
	"KeypadButton1"
	{
		"ControlName"		"Button"
		"fieldName"		"KeypadButton1"
		"xpos"		"65"
		"ypos"		"170"
		"zpos"		"3"
		"command"	"1"
	}
	"KeypadButton1img"
	{
		"ControlName"		"ImagePanel"
		"fieldName"		"KeypadButton1img"
		"xpos"		"65"
		"ypos"		"170"
		"zpos"		"2"
	}
	"KeypadButton2"
	{
		"ControlName"		"Button"
		"fieldName"		"KeypadButton2"
		"xpos"		"105"
		"ypos"		"170"
		"zpos"		"3"
		"command"	"2"
	}
	"KeypadButton2img"
	{
		"ControlName"		"ImagePanel"
		"fieldName"		"KeypadButton2img"
		"xpos"		"105"
		"ypos"		"170"
		"zpos"		"2"
	}
	"KeypadButton3"
	{
		"ControlName"		"Button"
		"fieldName"		"KeypadButton3"
		"xpos"		"145"
		"ypos"		"170"
		"zpos"		"3"
		"command"	"3"
	}
	"KeypadButton3img"
	{
		"ControlName"		"ImagePanel"
		"fieldName"		"KeypadButton3img"
		"xpos"		"145"
		"ypos"		"170"
		"zpos"		"2"
	}
	"KeypadButton4"
	{
		"ControlName"		"Button"
		"fieldName"		"KeypadButton4"
		"xpos"		"65"
		"ypos"		"220"
		"zpos"		"3"
		"command"	"4"
	}
	"KeypadButton4img"
	{
		"ControlName"		"ImagePanel"
		"fieldName"		"KeypadButton4img"
		"xpos"		"65"
		"ypos"		"220"
		"zpos"		"2"
	}
	"KeypadButton5"
	{
		"ControlName"		"Button"
		"fieldName"		"KeypadButton5"
		"xpos"		"105"
		"ypos"		"220"
		"zpos"		"3"
		"command"	"5"
	}
	"KeypadButton5img"
	{
		"ControlName"		"ImagePanel"
		"fieldName"		"KeypadButton5img"
		"xpos"		"105"
		"ypos"		"220"
		"zpos"		"2"
	}
	"KeypadButton6"
	{
		"ControlName"		"Button"
		"fieldName"		"KeypadButton6"
		"xpos"		"145"
		"ypos"		"220"
		"zpos"		"3"
		"command"	"6"
	}
	"KeypadButton6img"
	{
		"ControlName"		"ImagePanel"
		"fieldName"		"KeypadButton6img"
		"xpos"		"145"
		"ypos"		"220"
		"zpos"		"2"
	}
	"KeypadButton7"
	{
		"ControlName"		"Button"
		"fieldName"		"KeypadButton7"
		"xpos"		"65"
		"ypos"		"270"
		"zpos"		"3"
		"command"	"7"
	}
	"KeypadButton7img"
	{
		"ControlName"		"ImagePanel"
		"fieldName"		"KeypadButton7img"
		"xpos"		"65"
		"ypos"		"270"
		"zpos"		"2"
	}
	"KeypadButton8"
	{
		"ControlName"		"Button"
		"fieldName"		"KeypadButton8"
		"xpos"		"105"
		"ypos"		"270"
		"zpos"		"3"
		"command"	"8"
	}
	"KeypadButton8img"
	{
		"ControlName"		"ImagePanel"
		"fieldName"		"KeypadButton8img"
		"xpos"		"105"
		"ypos"		"270"
		"zpos"		"2"
	}
	"KeypadButton9"
	{
		"ControlName"		"Button"
		"fieldName"		"KeypadButton9"
		"xpos"		"145"
		"ypos"		"270"
		"zpos"		"3"
		"command"	"9"
	}
	"KeypadButton9img"
	{
		"ControlName"		"ImagePanel"
		"fieldName"		"KeypadButton9img"
		"xpos"		"145"
		"ypos"		"270"
		"zpos"		"2"
	}
	"ButtonCls"
	{
		"ControlName"		"Button"
		"fieldName"		"ButtonCls"
		"xpos"		"140"
		"ypos"		"400"
		"zpos"		"3"
		"command"	"turnoff"
	}
	"ButtonClsImg"
	{
		"ControlName"		"ImagePanel"
		"fieldName"		"ButtonClsImg"
		"xpos"		"140"
		"ypos"		"400"
		"zpos"		"2"
	}
	"ButtonClr"
	{
		"ControlName"		"Button"
		"fieldName"		"ButtonClr"
		"xpos"		"40"
		"ypos"		"400"
		"zpos"		"3"
		"command"	"clear"
	}
	"ButtonClrImg"
	{
		"ControlName"		"ImagePanel"
		"fieldName"		"ButtonClrImg"
		"xpos"		"40"
		"ypos"		"400"
		"zpos"		"2"
	}
}

GitHub link

In case you prefer to download the files, as well as the test map and the textures for it: https://github.com/MaestroFenix/Keypad