Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

377 lines
13 KiB

//=========== Copyright Valve Corporation, All rights reserved. ===============//
//
// Purpose:
//=============================================================================//
#ifndef PANORAMA_TEXTINPUT_DAISYWHEEL_H
#define PANORAMA_TEXTINPUT_DAISYWHEEL_H
#include "panorama/textinput/textinput.h"
#include "panorama/controls/panel2d.h"
#include "panorama/controls/label.h"
#include "panorama/input/iuiinput.h"
#include "mathlib/beziercurve.h"
#include "tier1/utlptr.h"
#include "panorama/uischeduleddel.h"
namespace panorama
{
// Forward declaration
class CTextInputDaisyWheel;
class CTextEntry;
class ITextInputSuggest;
class CLabel;
//-----------------------------------------------------------------------------
// Purpose: Implementation of daisy wheel text input handler
//-----------------------------------------------------------------------------
class CTextInputDaisyWheel : public panorama::CTextInputHandler
{
DECLARE_PANEL2D( CTextInputDaisyWheel, panorama::CPanel2D );
public:
// Constructor
CTextInputDaisyWheel( panorama::IUIWindow *pParent, const CTextInputHandlerSettings &settings, ITextInputControl *pTextControl );
CTextInputDaisyWheel( panorama::CPanel2D *parent, const CTextInputHandlerSettings &settings, ITextInputControl *pTextControl );
// Destructor
~CTextInputDaisyWheel();
// CTextInputHandler overrides
virtual void OpenHandler() OVERRIDE;
virtual void CloseHandlerImpl( bool bCommitText ) OVERRIDE;
virtual ETextInputHandlerType_t GetType() OVERRIDE;
virtual ITextInputControl *GetControlInterface() OVERRIDE;
virtual void SuggestWord( const wchar_t *pwch, int ich ) OVERRIDE;
virtual void SetYButtonAction( const char *pchLabel, IUIEvent *pEvent ) OVERRIDE;
static void GetSupportedLanguages( CUtlVector<ELanguage> &vecLangs );
private:
void Initialize( const CTextInputHandlerSettings &settings, ITextInputControl *pTextControl );
// This isn't part of CTextInputHandler because currently there is no need to set this dynamically
void SetMode( ETextInputMode_t mode );
// CPanel2D overrides
virtual bool OnGamePadUp( const panorama::GamePadData_t &code ) OVERRIDE;
virtual bool OnGamePadDown( const panorama::GamePadData_t &code ) OVERRIDE;
virtual bool OnGamePadAnalog( const panorama::GamePadData_t &code ) OVERRIDE;
virtual bool OnKeyTyped( const KeyData_t &unichar ) OVERRIDE;
virtual bool OnKeyDown( const KeyData_t &code ) OVERRIDE;
virtual bool OnKeyUp( const KeyData_t &code ) OVERRIDE;
//
// Daisy wheel input type
//
enum EDaisyInputType_t
{
k_EDaisyInputTypeABXY, // ABXY layout has color buttons printing keys
k_EDaisyInputTypeRS, // RS layout requires Right Stick usage to print keys
k_EDaisyInputTypePIN, // Button map to numbers for secret PIN entry
};
// Set daisy wheel type
void SetDaisyInputType( EDaisyInputType_t eType );
// Add an emoticon to the list of emoji this daisywheel will show
// TODO: Currently not part of CTextInputHandler because emoticons need work
void AddEmoticon( const char *szInsert, const char *szImageURL );
void CommitEmoticons();
#ifdef DBGFLAG_VALIDATE
void ValidateClientPanel( CValidator &validator, const tchar *pchName );
#endif
// User wants to move focus to the next field on the page
bool NextFocus();
static const int k_cPetals = 8; // # petals in flower (hardcoded for now)
static const int k_cItemsPerPetal = 4; // # letters visible on each petal, max
static const int k_cItemsPerLayoutMax = k_cPetals * k_cItemsPerPetal; // # letters total per layout, max
struct Emoticon_t
{
CUtlString sType;
CUtlString sImageURL;
};
//
// A single wheel layout configuration: name and UTF-8 sequences of characters
// Structure is allocated with more memory at the end of the structure, name and
// UTF-8 sequences follow this structure object
//
class CDaisyConfig
{
public:
CDaisyConfig( const char *pchName ) : m_sName( pchName )
{
}
// Get the name of wheel layout
char const * GetName() const { return m_sName.String(); }
// Get number of items in this wheel layout
int GetNumItems() const { return m_cItems; }
// Get a given item in this wheel layout, must be >= zero and < number of items
// double the index, because each item is NUL terminated
const char * GetItem( int idx ) const
{
if ( idx >= k_cItemsPerLayoutMax || idx < 0 )
{
Assert( false );
return "";
}
return m_vecText.Base() + m_rgich[ idx ];
}
#ifdef DBGFLAG_VALIDATE
void Validate( CValidator &validator, const tchar *pchName )
{
VALIDATE_SCOPE();
ValidateObj( m_sName );
ValidateObj( m_vecText );
}
#endif
// name of this layout
CUtlString m_sName;
// Number of items in this wheel layout
int m_cItems;
// offsets into the text block for each item in this layout
int m_rgich[ k_cItemsPerLayoutMax ];
// block of text for this layout, UTF-8
CUtlVector< char > m_vecText;
};
// After configuration has been loaded and assigned walk through all
// controls and set their values to represent the loaded config
void SetControlsFromConfiguration();
// map the trigger inputs to a config
enum EDaisyConfig_t
{
k_EDaisyConfigNone = -1,
k_EDaisyConfigCaps,
k_EDaisyConfigLetters,
k_EDaisyConfigNumbers,
k_EDaisyConfigSpecial,
k_EDaisyConfigNumbersOnly,
k_EDaisyConfigPhoneNumber,
k_EDaisyConfigSteamCodeChars,
k_EDaisyConfigEmoji,
};
typedef CUtlMap< EDaisyConfig_t, CUtlPtr< CDaisyConfig >, int, CDefLess< EDaisyConfig_t > > MapConfigEntries_t;
EDaisyConfig_t EDaisyConfigFromString( const char *pchValue );
EDaisyConfig_t ConfigFromTriggerState( bool bLeftTrigger, bool bRightTrigger );
// update the trigger legends based on the current trigger state
void UpdateTriggerLegends();
// moves controls to existing config (caps -> lowercase)
void AdvanceControlsConfiguration( EDaisyConfig_t eConfig );
// Types a character from selected group's side of world: "E" | "W" | "N" | "S"
bool TypeCharacterFromSide( char chSide );
// Types a given wide character into text entry
bool TypeWchar( uchar16 wch );
// Simulates a key down event
bool TypeKeyDown( panorama::KeyCode eCode );
// Loads configuration file for specified language
bool LoadInputConfigurationFile( ELanguage language );
// Loads configuration file
bool LoadInputConfigurationFile( const char *szConfig, const char *szConfigRootDir );
// Builds configuration structure based on buffer loaded from config file
bool LoadConfigurationBuffer( char const *pszBase, MapConfigEntries_t *pmapConfigs );
// Switch between most recent languages
bool SwitchLanguage();
bool ShowThisLanguage( ELanguage language );
// For a given config item determine which group and group side the item should be at
void GetItemLocation( CDaisyConfig *pCfg, int iItem, char const *&szGroup, char const *&szItem );
// Get name of the group square indexed by -1|0|1 pair of x,y coordinates; returns side or wolrd like: "E" | "NE" | "N" | "NW" | etc.
char const * GetGroupNameSq( int x, int y );
// Gets a sequential index of the group square indexed by -1|0|1 pair of x,y coordinates
int GetGroupIdxSq( int x, int y );
// Gets the side of world name of group by its sequential index
char const * GetGroup( int idxGroup );
// Gets the side of world name of item by its sequential index
char const * GetSide( int idxSide );
// Process scheduled key repeat
void ScheduleKeyRepeats( panorama::GamePadCode eCode );
void CancelOutstandingRepeats() { ScheduleKeyRepeats( XK_NULL ); }
void ScheduledKeyRepeatFunction();
bool HandlePropertyTransitionEnd( const panorama::CPanelPtr< panorama::IUIPanel > &pPanel, CStyleSymbol sym );
// Listen for focus lost
bool HandleInputFocusLost( const panorama::CPanelPtr< panorama::IUIPanel > &ptrPanel );
// events bound in window_keybinds.cfg
bool ShowHideSettings();
// settings events
bool CancelSettings();
// auto-suggestion
void ShowSuggestion( const char *szPrefix, const char *szSuffix );
void ClearSuggestionVisual()
{
ShowSuggestion( "", "" );
}
void ClearSuggestionState()
{
m_sSuggestion.Clear();
ClearSuggestionVisual();
}
bool BCursorAtStartOfSentence();
bool BConvertNextSpaceToPeriod();
// Play sound for a give daisy wheel activity
enum EDaisyAction_t
{
k_EDaisySound_ButtonA,
k_EDaisySound_ButtonB,
k_EDaisySound_ButtonX,
k_EDaisySound_ButtonY,
k_EDaisySound_KeySpacebar,
k_EDaisySound_KeyBackspace,
k_EDaisySound_KeyLeft,
k_EDaisySound_KeyRight,
k_EDaisySound_KeyHome,
k_EDaisySound_KeyEnd,
k_EDaisySound_FocusAreaChanged,
k_EDaisySound_ConfigChanged,
k_EDaisySound_FocusAreaCold,
k_EDaisySound_PerformAutosuggest,
};
void PlayDaisyActionSound( EDaisyAction_t eAction );
// Function to handle gamepad data depending on daisy wheel settings
typedef bool (CTextInputDaisyWheel::*PFNGamePadData)( const panorama::GamePadData_t &code );
MapConfigEntries_t m_mapConfigEntries; // Processed configuration entries
EDaisyConfig_t m_eConfigCurrent; // Current config, can be cycled with triggers
bool m_bRestrictConfig; // if true, stick to current config (no changing layouts)
panorama::CPanel2D *m_pStickPri; // Primary stick control
float m_flStickPriSelectOct[2]; // Selection octant angles (std: lo=M_PI/6, hi=M_PI/3)
float m_flStickPriMoveScale[2]; // Scale for primary stick movement
float m_flStickPriSelectDist[2]; // Selection distances
float m_flStickPriSelectAngleSticky; // Selection angle to stick to area
float m_flStickPriColdTime; // How long we need primary stick to remain cold
int m_nSelectionGroup[2]; // Currently selected group
panorama::CPanel2D *m_pStickSnd; // Secondary stick control
float m_flStickSndMoveScale[2]; // Scale for secondary stick movement
float m_flStickSndSelectDist[2]; // Selection distances for secondary stick
float m_flStickSndSelectAngleSticky; // Selection angle for secondary stick to stick to area
panorama::CLabel *m_pLang; // Language legend label
double m_flPickedItemTransitionTime; // Time for picked item to highlight
PFNGamePadData m_pfnOnGamePadDown; // Current config for gamepad down
PFNGamePadData m_pfnOnGamePadAnalog; // Current config for gamepad analog
// settings
bool m_bDoubleSpaceToDotSpace;
bool m_bAutoCaps;
// Tracking doublespace = dot+space
bool m_bOnlySpacesEnteredSinceBackspace;
// Tracking trigger state for typing
bool m_bTriggersDownState[2]; // Whether trigger is down
// Tracking stick cold state
double m_flTimeStickCold; // When stick went into cold state (rolls when hot)
// Tracking key repeats
CCubicBezierCurve< Vector2D > m_repeatCurve; // Curve for key repeats
double m_repeatStartTime; // Time when the key was initially pressed
double m_repeatNextTime; // Time when the key will repeat next
panorama::GamePadCode m_repeatGamePadCode; // Which key was pressed (low level, for key-up tracking)
uint32 m_repeatCounter; // How many key repeats have happened
panorama::CUIScheduledDel m_repeatFunction; // Scheduled function triggering key repeats
// Stick processing routines
bool OnGamePadAnalog_ProcessLeftStickForGroup( const panorama::GamePadData_t &code );
bool OnGamePadAnalog_ProcessRightStickForSide( const panorama::GamePadData_t &code );
bool OnGamePadAnalog_Trigger( const panorama::GamePadData_t &code );
bool HandleTextInputDaisyWheelOnGamePadAnalogTriggersChanged();
// ABXY handlers
bool DaisyABXY_OnGamePadDown( const panorama::GamePadData_t &code );
bool DaisyABXY_OnGamePadAnalog( const panorama::GamePadData_t &code );
// RS handlers
bool DaisyRS_OnGamePadDown( const panorama::GamePadData_t &code );
bool DaisyRS_OnGamePadAnalog( const panorama::GamePadData_t &code );
// PINpad handlers
bool DaisyPIN_OnGamePadDown( const panorama::GamePadData_t & code );
bool DaisyPIN_OnGamePadAnalog( const panorama::GamePadData_t &code );
ELanguage m_language; // currently loaded language
ITextInputSuggest *m_psuggest; // suggestion engine
CUtlString m_sSuggestion; // result of suggestion
panorama::CLabel *m_plabelSuggestionPrefix; // label containing prefix of current suggestion
panorama::CLabel *m_plabelSuggestionSuffix; // label containing prefix of current suggestion
double m_flInputStartTime; // when did the user first start typing
bool m_bUsedKeyboard; // true if the kb was used for ANY input
bool m_bUsedGamepad; // true if the gamepad was used for ANY input
ITextInputControl *m_pTextInputControl; // control interface for moving text input between a control and daisy wheel
IUIEvent *m_pYbuttonAction; // the action to fire if the Y button is hit
panorama::CLabel *m_pYButtonText; // label for ybutton text
ETextInputMode_t m_mode; // text input mode
bool m_bDisplaySuggestions; // If true, allow suggestions to be displayed
// mode can disable specific footer sections
bool m_bDisableRightTrigger;
bool m_bDisableRightBumper;
bool m_bDisableLeftTrigger;
bool m_bDisableLanguageSelect;
enum ERightStickPos
{
k_RightStick_None,
k_RightStick_Up,
k_RightStick_Down,
k_RightStick_Left,
k_RightStick_Right,
};
ERightStickPos m_eSteamRightStickPos;
Vector2D m_vecRightPadPos;
CUtlVector< Emoticon_t > m_vecEmoji;
bool m_bLoadedEmoji;
};
} // namespace panorama
#endif // PANORAMA_TEXTINPUT_DAISYWHEEL_H