//=========== 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 &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