aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGarrett Brown <themagnificentmrb@gmail.com>2016-05-21 18:09:01 -0700
committerGarrett Brown <themagnificentmrb@gmail.com>2016-08-13 12:17:22 -0700
commit8824342723c7ceb533247ccfed61fb4bbf0761a4 (patch)
treec825a382de72f1c2e8e1183bde87915941cceff4
parentd5bcf6203f40baf9a5562692114a09b54c8e4b13 (diff)
[controller dialog] Group features into categories
-rw-r--r--Kodi.xcodeproj/project.pbxproj8
-rw-r--r--addons/game.controller.default/resources/layout.xml8
-rw-r--r--addons/resource.language.en_gb/resources/strings.po24
-rw-r--r--addons/skin.estuary/1080i/DialogGameControllers.xml16
-rw-r--r--xbmc/games/controllers/ControllerDefinitions.h10
-rw-r--r--xbmc/games/controllers/ControllerFeature.cpp10
-rw-r--r--xbmc/games/controllers/ControllerFeature.h6
-rw-r--r--xbmc/games/controllers/ControllerLayout.cpp26
-rw-r--r--xbmc/games/controllers/ControllerTranslator.cpp26
-rw-r--r--xbmc/games/controllers/ControllerTranslator.h3
-rw-r--r--xbmc/games/controllers/guicontrols/CMakeLists.txt2
-rw-r--r--xbmc/games/controllers/guicontrols/GUIFeatureControls.cpp43
-rw-r--r--xbmc/games/controllers/guicontrols/GUIFeatureControls.h44
-rw-r--r--xbmc/games/controllers/guicontrols/Makefile1
-rw-r--r--xbmc/games/controllers/windows/GUIControllerDefines.h6
-rw-r--r--xbmc/games/controllers/windows/GUIFeatureList.cpp131
-rw-r--r--xbmc/games/controllers/windows/GUIFeatureList.h15
-rw-r--r--xbmc/input/joysticks/JoystickTypes.h15
18 files changed, 303 insertions, 91 deletions
diff --git a/Kodi.xcodeproj/project.pbxproj b/Kodi.xcodeproj/project.pbxproj
index 68df9e9cec..ed0ac02d9a 100644
--- a/Kodi.xcodeproj/project.pbxproj
+++ b/Kodi.xcodeproj/project.pbxproj
@@ -319,6 +319,8 @@
68AE5C321C9243A000C4D527 /* ControllerLayout.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 68AE5C281C9243A000C4D527 /* ControllerLayout.cpp */; };
68AE5C331C9243A000C4D527 /* ControllerTranslator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 68AE5C2A1C9243A000C4D527 /* ControllerTranslator.cpp */; };
68AE5C341C9243A000C4D527 /* ControllerTranslator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 68AE5C2A1C9243A000C4D527 /* ControllerTranslator.cpp */; };
+ 68B7E5E81D5FA9B300A5AEC0 /* GUIFeatureControls.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 68B7E5E61D5FA9B300A5AEC0 /* GUIFeatureControls.cpp */; };
+ 68B7E5E91D5FA9B300A5AEC0 /* GUIFeatureControls.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 68B7E5E61D5FA9B300A5AEC0 /* GUIFeatureControls.cpp */; };
761170901C8B85F8006C6366 /* AddonGUIRenderingControl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7611708C1C8B85F8006C6366 /* AddonGUIRenderingControl.cpp */; };
761170911C8B85F8006C6366 /* AddonGUIWindow.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7611708E1C8B85F8006C6366 /* AddonGUIWindow.cpp */; };
76AEFB361C8F79BD00EF2EC0 /* AddonInterfaces.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDED2E991C878F61000F5E80 /* AddonInterfaces.cpp */; };
@@ -2832,6 +2834,8 @@
68AE5C2A1C9243A000C4D527 /* ControllerTranslator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ControllerTranslator.cpp; path = games/controllers/ControllerTranslator.cpp; sourceTree = "<group>"; };
68AE5C2B1C9243A000C4D527 /* ControllerTranslator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ControllerTranslator.h; path = games/controllers/ControllerTranslator.h; sourceTree = "<group>"; };
68AE5C2C1C9243A000C4D527 /* ControllerTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ControllerTypes.h; path = games/controllers/ControllerTypes.h; sourceTree = "<group>"; };
+ 68B7E5E61D5FA9B300A5AEC0 /* GUIFeatureControls.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GUIFeatureControls.cpp; path = games/controllers/guicontrols/GUIFeatureControls.cpp; sourceTree = "<group>"; };
+ 68B7E5E71D5FA9B300A5AEC0 /* GUIFeatureControls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GUIFeatureControls.h; path = games/controllers/guicontrols/GUIFeatureControls.h; sourceTree = "<group>"; };
6E97BDBF0DA2B620003A2A89 /* EventClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EventClient.h; sourceTree = "<group>"; };
6E97BDC00DA2B620003A2A89 /* EventPacket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EventPacket.h; sourceTree = "<group>"; };
6E97BDC10DA2B620003A2A89 /* EventServer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EventServer.h; sourceTree = "<group>"; };
@@ -6220,6 +6224,8 @@
68AE5C121C92438E00C4D527 /* GUIControllerButton.h */,
68AE5C131C92438E00C4D527 /* GUIFeatureButton.cpp */,
68AE5C141C92438E00C4D527 /* GUIFeatureButton.h */,
+ 68B7E5E61D5FA9B300A5AEC0 /* GUIFeatureControls.cpp */,
+ 68B7E5E71D5FA9B300A5AEC0 /* GUIFeatureControls.h */,
68AE5C151C92438E00C4D527 /* GUIGameController.cpp */,
68AE5C161C92438E00C4D527 /* GUIGameController.h */,
68AE5C171C92438E00C4D527 /* GUIScalarFeatureButton.cpp */,
@@ -10327,6 +10333,7 @@
F5E1138014357F3800175026 /* PeripheralCecAdapter.cpp in Sources */,
DF673AA51443819600A5A509 /* AddonManager.cpp in Sources */,
7C8E022B1BA35D0B0072E8B2 /* GUIContainerBuiltins.cpp in Sources */,
+ 68B7E5E81D5FA9B300A5AEC0 /* GUIFeatureControls.cpp in Sources */,
DFDE5D511AE5658200EE53AD /* PictureScalingAlgorithm.cpp in Sources */,
F5BD02F6148D3A7E001B5583 /* CryptThreading.cpp in Sources */,
DF5276E1151BAEDA00B5B63B /* Base64.cpp in Sources */,
@@ -11066,6 +11073,7 @@
E4991285174E5D9900741B6D /* DirectoryNodeAlbumTop100Song.cpp in Sources */,
395C2A051A9CD25100EBC7AD /* ContextItemAddonInvoker.cpp in Sources */,
E4991286174E5D9900741B6D /* DirectoryNodeArtist.cpp in Sources */,
+ 68B7E5E91D5FA9B300A5AEC0 /* GUIFeatureControls.cpp in Sources */,
DF29BCEF1B5D911800904347 /* BaseEvent.cpp in Sources */,
E4991287174E5D9900741B6D /* DirectoryNodeGrouped.cpp in Sources */,
E4991288174E5D9900741B6D /* DirectoryNodeOverview.cpp in Sources */,
diff --git a/addons/game.controller.default/resources/layout.xml b/addons/game.controller.default/resources/layout.xml
index b8df0e6b41..0ceab7b62b 100644
--- a/addons/game.controller.default/resources/layout.xml
+++ b/addons/game.controller.default/resources/layout.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<layout name="default" label="30000" image="layout.png">
- <category name="face">
+ <category name="face" label="35074">
<button name="a" type="digital" label="30001" geometry="circle" x="651" y="266" radius="32"/>
<button name="b" type="digital" label="30002" geometry="circle" x="709" y="210" radius="32"/>
<button name="x" type="digital" label="30003" geometry="circle" x="583" y="210" radius="32"/>
@@ -15,15 +15,15 @@
<button name="leftthumb" type="digital" label="30008" geometry="rectangle" x1="131" y1="0" x2="194" y2="40"/>
<button name="rightthumb" type="digital" label="30009" geometry="rectangle" x1="567" y1="0" x2="631" y2="40"/>
</category>
- <category name="shoulder">
+ <category name="shoulder" label="35075">
<button name="leftbumper" type="digital" label="30014" geometry="rectangle" x1="272" y1="321" x2="316" y2="365"/>
<button name="rightbumper" type="digital" label="30015" geometry="rectangle" x1="198" y1="321" x2="242" y2="365"/>
</category>
- <category name="triggers">
+ <category name="triggers" label="35076">
<button name="lefttrigger" type="analog" label="30016" geometry="rectangle" x1="36" y1="40" x2="207" y2="108"/>
<button name="righttrigger" type="analog" label="30017" geometry="rectangle" x1="556" y1="40" x2="728" y2="108"/>
</category>
- <category name="analogsticks">
+ <category name="analogsticks" label="35077">
<analogstick name="leftstick" label="30008" geometry="circle" x="500" y="342" r="52"/>
<analogstick name="rightstick" label="30009" geometry="circle" x="500" y="342" r="52"/>
</category>
diff --git a/addons/resource.language.en_gb/resources/strings.po b/addons/resource.language.en_gb/resources/strings.po
index 19d04d7457..397c7ff26e 100644
--- a/addons/resource.language.en_gb/resources/strings.po
+++ b/addons/resource.language.en_gb/resources/strings.po
@@ -16042,7 +16042,29 @@ msgctxt "#35064"
msgid "Pair your controllers with the various input devices of different game systems."
msgstr ""
-#empty strings from id 35065 to 35087
+#empty strings from id 35065 to 35073
+
+#. Label for buttons that appear on the face of the controller. Used in the controller mapping dialog.
+msgctxt "#35074"
+msgid "Face buttons"
+msgstr ""
+
+#. Label for buttons that appear on the shoulders of the controller. Used in the controller mapping dialog.
+msgctxt "#35075"
+msgid "Shoulder buttons"
+msgstr ""
+
+#. Label for triggers on the controller. Used in the controller mapping dialog.
+msgctxt "#35076"
+msgid "Triggers"
+msgstr ""
+
+#. Label for analog sticks on the controller. Used in the controller mapping dialog.
+msgctxt "#35077"
+msgid "Analog sticks"
+msgstr ""
+
+#empty strings from id 35078 to 35087
#. Name of the setting that enables/disables powering off controllers on exit
#: system/settings/settings.xml
diff --git a/addons/skin.estuary/1080i/DialogGameControllers.xml b/addons/skin.estuary/1080i/DialogGameControllers.xml
index f420abdbec..10db3bf47a 100644
--- a/addons/skin.estuary/1080i/DialogGameControllers.xml
+++ b/addons/skin.estuary/1080i/DialogGameControllers.xml
@@ -123,6 +123,22 @@
<texturefocus colordiffuse="button_focus">lists/focus.png</texturefocus>
<texturenofocus>lists/separator.png</texturenofocus>
</control>
+ <control type="label" id="8">
+ <description>Feature group title</description>
+ <height>60</height>
+ <width>330</width>
+ <label>-</label>
+ <align>center</align>
+ <aligny>center</aligny>
+ <font>font12_title</font>
+ <textcolor>grey</textcolor>
+ <shadowcolor>black</shadowcolor>
+ </control>
+ <control type="image" id="9">
+ <description>Feature separator image</description>
+ <height>3</height>
+ <texture colordiffuse="AAAAAAAA" border="3">dialogs/separator-grey.png</texture>
+ </control>
<control type="grouplist" id="9001">
<left>1360</left>
<top>110</top>
diff --git a/xbmc/games/controllers/ControllerDefinitions.h b/xbmc/games/controllers/ControllerDefinitions.h
index 366d49734f..8ade354737 100644
--- a/xbmc/games/controllers/ControllerDefinitions.h
+++ b/xbmc/games/controllers/ControllerDefinitions.h
@@ -21,7 +21,7 @@
#define LAYOUT_XML_ROOT "layout"
-#define LAYOUT_XML_ELM_CATEGORY "category"
+#define LAYOUT_XML_ELM_GROUP "category"
#define LAYOUT_XML_ELM_BUTTON "button"
#define LAYOUT_XML_ELM_ANALOG_STICK "analogstick"
@@ -32,13 +32,7 @@
#define LAYOUT_XML_ATTR_LAYOUT_IMAGE "image"
#define LAYOUT_XML_ATTR_LAYOUT_OVERLAY "overlay"
-#define LAYOUT_XML_ATTR_CATEGORY_NAME "name"
-
-#define LAYOUT_XML_VALUE_CATEGORY_FACE "face"
-#define LAYOUT_XML_VALUE_CATEGORY_SHOULDER "shoulder"
-#define LAYOUT_XML_VALUE_CATEGORY_TRIGGERS "triggers"
-#define LAYOUT_XML_VALUE_CATEGORY_ANALOG_STICKS "analogsticks"
-#define LAYOUT_XML_VALUE_CATEGORY_HAPTICS "haptics"
+#define LAYOUT_XML_ATTR_GROUP_LABEL "label"
#define LAYOUT_XML_ATTR_FEATURE_NAME "name"
#define LAYOUT_XML_ATTR_FEATURE_LABEL "label"
diff --git a/xbmc/games/controllers/ControllerFeature.cpp b/xbmc/games/controllers/ControllerFeature.cpp
index 4c6eadf9b7..e0500eaeba 100644
--- a/xbmc/games/controllers/ControllerFeature.cpp
+++ b/xbmc/games/controllers/ControllerFeature.cpp
@@ -34,7 +34,7 @@ using namespace JOYSTICK;
void CControllerFeature::Reset(void)
{
m_type = FEATURE_TYPE::UNKNOWN;
- m_category = FEATURE_CATEGORY::UNKNOWN;
+ m_group.clear();
m_strName.clear();
m_strLabel.clear();
m_labelId = 0;
@@ -46,7 +46,7 @@ CControllerFeature& CControllerFeature::operator=(const CControllerFeature& rhs)
if (this != &rhs)
{
m_type = rhs.m_type;
- m_category = rhs.m_category;
+ m_group = rhs.m_group;
m_strName = rhs.m_strName;
m_strLabel = rhs.m_strLabel;
m_labelId = rhs.m_labelId;
@@ -55,7 +55,7 @@ CControllerFeature& CControllerFeature::operator=(const CControllerFeature& rhs)
return *this;
}
-bool CControllerFeature::Deserialize(const TiXmlElement* pElement, const CController* controller, const std::string& strCategory)
+bool CControllerFeature::Deserialize(const TiXmlElement* pElement, const CController* controller, const std::string& strGroup)
{
Reset();
@@ -72,8 +72,8 @@ bool CControllerFeature::Deserialize(const TiXmlElement* pElement, const CContro
return false;
}
- // Category was obtained from parent XML node
- m_category = CControllerTranslator::TranslateCategory(strCategory);
+ // Group was obtained from parent XML node
+ m_group = strGroup;
// Name
m_strName = XMLUtils::GetAttribute(pElement, LAYOUT_XML_ATTR_FEATURE_NAME);
diff --git a/xbmc/games/controllers/ControllerFeature.h b/xbmc/games/controllers/ControllerFeature.h
index b68b02d4db..7a2ae4336e 100644
--- a/xbmc/games/controllers/ControllerFeature.h
+++ b/xbmc/games/controllers/ControllerFeature.h
@@ -40,17 +40,17 @@ public:
CControllerFeature& operator=(const CControllerFeature& rhs);
JOYSTICK::FEATURE_TYPE Type(void) const { return m_type; }
- JOYSTICK::FEATURE_CATEGORY Category(void) const { return m_category; }
+ const std::string& Group(void) const { return m_group; }
const std::string& Name(void) const { return m_strName; }
const std::string& Label(void) const { return m_strLabel; }
unsigned int LabelID(void) const { return m_labelId; }
JOYSTICK::INPUT_TYPE InputType(void) const { return m_inputType; }
- bool Deserialize(const TiXmlElement* pElement, const CController* controller, const std::string& strCategory);
+ bool Deserialize(const TiXmlElement* pElement, const CController* controller, const std::string& strGroup);
private:
JOYSTICK::FEATURE_TYPE m_type;
- JOYSTICK::FEATURE_CATEGORY m_category;
+ std::string m_group;
std::string m_strName;
std::string m_strLabel;
unsigned int m_labelId;
diff --git a/xbmc/games/controllers/ControllerLayout.cpp b/xbmc/games/controllers/ControllerLayout.cpp
index 6ee6200b01..6d1bbadc9f 100644
--- a/xbmc/games/controllers/ControllerLayout.cpp
+++ b/xbmc/games/controllers/ControllerLayout.cpp
@@ -19,7 +19,9 @@
*/
#include "ControllerLayout.h"
+#include "Controller.h"
#include "ControllerDefinitions.h"
+#include "guilib/LocalizeStrings.h"
#include "utils/log.h"
#include "utils/XMLUtils.h"
@@ -100,18 +102,32 @@ bool CControllerLayout::Deserialize(const TiXmlElement* pElement, const CControl
CLog::Log(LOGDEBUG, "<%s> tag has no \"%s\" attribute", LAYOUT_XML_ROOT, LAYOUT_XML_ATTR_LAYOUT_OVERLAY);
// Features
- for (const TiXmlElement* pCategory = pElement->FirstChildElement(); pCategory != nullptr; pCategory = pCategory->NextSiblingElement())
+ for (const TiXmlElement* pGroup = pElement->FirstChildElement(); pGroup != nullptr; pGroup = pGroup->NextSiblingElement())
{
- if (std::string(pCategory->Value()) != std::string(LAYOUT_XML_ELM_CATEGORY))
+ if (pGroup->ValueStr() != LAYOUT_XML_ELM_GROUP)
+ {
+ CLog::Log(LOGDEBUG, "<%s> tag is misnamed: <%s>", LAYOUT_XML_ELM_GROUP, pGroup->Value() ? pGroup->Value() : "");
continue;
+ }
+
+ // Group
+ std::string strGroup;
- const std::string strCategoryName = XMLUtils::GetAttribute(pCategory, LAYOUT_XML_ATTR_CATEGORY_NAME);
+ std::string strGroupLabel = XMLUtils::GetAttribute(pGroup, LAYOUT_XML_ATTR_GROUP_LABEL);
+ if (!strGroupLabel.empty())
+ {
+ unsigned int categoryId;
+ std::istringstream(strGroupLabel) >> categoryId;
+ strGroup = g_localizeStrings.GetAddonString(controller->ID(), categoryId);
+ if (strGroup.empty())
+ strGroup = g_localizeStrings.Get(categoryId);
+ }
- for (const TiXmlElement* pFeature = pCategory->FirstChildElement(); pFeature != nullptr; pFeature = pFeature->NextSiblingElement())
+ for (const TiXmlElement* pFeature = pGroup->FirstChildElement(); pFeature != nullptr; pFeature = pFeature->NextSiblingElement())
{
CControllerFeature feature;
- if (!feature.Deserialize(pFeature, controller, strCategoryName))
+ if (!feature.Deserialize(pFeature, controller, strGroup))
return false;
m_features.push_back(feature);
diff --git a/xbmc/games/controllers/ControllerTranslator.cpp b/xbmc/games/controllers/ControllerTranslator.cpp
index 275b87aaf4..692960e720 100644
--- a/xbmc/games/controllers/ControllerTranslator.cpp
+++ b/xbmc/games/controllers/ControllerTranslator.cpp
@@ -48,32 +48,6 @@ FEATURE_TYPE CControllerTranslator::TranslateFeatureType(const std::string& strT
return FEATURE_TYPE::UNKNOWN;
}
-const char* CControllerTranslator::TranslateCategory(FEATURE_CATEGORY category)
-{
- switch (category)
- {
- case FEATURE_CATEGORY::FACE: return LAYOUT_XML_VALUE_CATEGORY_FACE;
- case FEATURE_CATEGORY::SHOULDER: return LAYOUT_XML_VALUE_CATEGORY_SHOULDER;
- case FEATURE_CATEGORY::TRIGGERS: return LAYOUT_XML_VALUE_CATEGORY_TRIGGERS;
- case FEATURE_CATEGORY::ANALOG_STICKS: return LAYOUT_XML_VALUE_CATEGORY_ANALOG_STICKS;
- case FEATURE_CATEGORY::HAPTICS: return LAYOUT_XML_VALUE_CATEGORY_HAPTICS;
- default:
- break;
- }
- return "";
-}
-
-FEATURE_CATEGORY CControllerTranslator::TranslateCategory(const std::string& strCategory)
-{
- if (strCategory == LAYOUT_XML_VALUE_CATEGORY_FACE) return FEATURE_CATEGORY::FACE;
- if (strCategory == LAYOUT_XML_VALUE_CATEGORY_SHOULDER) return FEATURE_CATEGORY::SHOULDER;
- if (strCategory == LAYOUT_XML_VALUE_CATEGORY_TRIGGERS) return FEATURE_CATEGORY::TRIGGERS;
- if (strCategory == LAYOUT_XML_VALUE_CATEGORY_ANALOG_STICKS) return FEATURE_CATEGORY::ANALOG_STICKS;
- if (strCategory == LAYOUT_XML_VALUE_CATEGORY_HAPTICS) return FEATURE_CATEGORY::HAPTICS;
-
- return FEATURE_CATEGORY::UNKNOWN;
-}
-
const char* CControllerTranslator::TranslateInputType(INPUT_TYPE type)
{
switch (type)
diff --git a/xbmc/games/controllers/ControllerTranslator.h b/xbmc/games/controllers/ControllerTranslator.h
index c2c70b3030..c7436134e4 100644
--- a/xbmc/games/controllers/ControllerTranslator.h
+++ b/xbmc/games/controllers/ControllerTranslator.h
@@ -33,9 +33,6 @@ public:
static const char* TranslateFeatureType(JOYSTICK::FEATURE_TYPE type);
static JOYSTICK::FEATURE_TYPE TranslateFeatureType(const std::string& strType);
- static const char* TranslateCategory(JOYSTICK::FEATURE_CATEGORY category);
- static JOYSTICK::FEATURE_CATEGORY TranslateCategory(const std::string& strCategory);
-
static const char* TranslateInputType(JOYSTICK::INPUT_TYPE type);
static JOYSTICK::INPUT_TYPE TranslateInputType(const std::string& strType);
};
diff --git a/xbmc/games/controllers/guicontrols/CMakeLists.txt b/xbmc/games/controllers/guicontrols/CMakeLists.txt
index dafd43cea4..c719a88fd0 100644
--- a/xbmc/games/controllers/guicontrols/CMakeLists.txt
+++ b/xbmc/games/controllers/guicontrols/CMakeLists.txt
@@ -1,12 +1,14 @@
set(SOURCES GUIAnalogStickButton.cpp
GUIControllerButton.cpp
GUIFeatureButton.cpp
+ GUIFeatureControls.cpp
GUIGameController.cpp
GUIScalarFeatureButton.cpp)
set(HEADERS GUIAnalogStickButton.h
GUIControllerButton.h
GUIFeatureButton.h
+ GUIFeatureControls.h
GUIGameController.h
GUIScalarFeatureButton.h)
diff --git a/xbmc/games/controllers/guicontrols/GUIFeatureControls.cpp b/xbmc/games/controllers/guicontrols/GUIFeatureControls.cpp
new file mode 100644
index 0000000000..46866732c4
--- /dev/null
+++ b/xbmc/games/controllers/guicontrols/GUIFeatureControls.cpp
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2016 Team Kodi
+ * http://kodi.tv
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this Program; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "GUIFeatureControls.h"
+#include "games/controllers/windows/GUIControllerDefines.h"
+
+using namespace GAME;
+
+CGUIFeatureGroupTitle::CGUIFeatureGroupTitle(const CGUILabelControl& groupTitleTemplate, const std::string& groupName, unsigned int featureIndex) :
+ CGUILabelControl(groupTitleTemplate)
+{
+ // Initialize CGUILabelControl
+ SetLabel(groupName);
+ SetID(CONTROL_FEATURE_GROUPS_START + featureIndex);
+ SetVisible(true);
+ AllocResources();
+}
+
+CGUIFeatureSeparator::CGUIFeatureSeparator(const CGUIImage& separatorTemplate, unsigned int featureIndex) :
+ CGUIImage(separatorTemplate)
+{
+ // Initialize CGUIImage
+ SetID(CONTROL_FEATURE_SEPARATORS_START + featureIndex);
+ SetVisible(true);
+ AllocResources();
+}
diff --git a/xbmc/games/controllers/guicontrols/GUIFeatureControls.h b/xbmc/games/controllers/guicontrols/GUIFeatureControls.h
new file mode 100644
index 0000000000..beccc94fbd
--- /dev/null
+++ b/xbmc/games/controllers/guicontrols/GUIFeatureControls.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2016 Team Kodi
+ * http://kodi.tv
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this Program; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+#pragma once
+
+#include "guilib/GUILabelControl.h"
+#include "guilib/GUIImage.h"
+
+#include <string>
+
+namespace GAME
+{
+ class CGUIFeatureGroupTitle : public CGUILabelControl
+ {
+ public:
+ CGUIFeatureGroupTitle(const CGUILabelControl& groupTitleTemplate, const std::string& groupName, unsigned int featureIndex);
+
+ virtual ~CGUIFeatureGroupTitle(void) { }
+ };
+
+ class CGUIFeatureSeparator : public CGUIImage
+ {
+ public:
+ CGUIFeatureSeparator(const CGUIImage& separatorTemplate, unsigned int featureIndex);
+
+ virtual ~CGUIFeatureSeparator(void) { }
+ };
+}
diff --git a/xbmc/games/controllers/guicontrols/Makefile b/xbmc/games/controllers/guicontrols/Makefile
index c9e2b3090a..c00d858b0c 100644
--- a/xbmc/games/controllers/guicontrols/Makefile
+++ b/xbmc/games/controllers/guicontrols/Makefile
@@ -1,6 +1,7 @@
SRCS=GUIAnalogStickButton.cpp \
GUIControllerButton.cpp \
GUIFeatureButton.cpp \
+ GUIFeatureControls.cpp \
GUIGameController.cpp \
GUIScalarFeatureButton.cpp \
diff --git a/xbmc/games/controllers/windows/GUIControllerDefines.h b/xbmc/games/controllers/windows/GUIControllerDefines.h
index 17d83d7567..54e1e28ac6 100644
--- a/xbmc/games/controllers/windows/GUIControllerDefines.h
+++ b/xbmc/games/controllers/windows/GUIControllerDefines.h
@@ -29,6 +29,8 @@
#define CONTROL_CONTROLLER_LIST 3
#define CONTROL_FEATURE_LIST 5
#define CONTROL_FEATURE_BUTTON_TEMPLATE 7
+#define CONTROL_FEATURE_GROUP_TITLE 8
+#define CONTROL_FEATURE_SEPARATOR 9
#define CONTROL_CONTROLLER_BUTTON_TEMPLATE 10
#define CONTROL_HELP_BUTTON 17
#define CONTROL_CLOSE_BUTTON 18
@@ -43,3 +45,7 @@
#define CONTROL_CONTROLLER_BUTTONS_END (CONTROL_CONTROLLER_BUTTONS_START + MAX_CONTROLLER_COUNT)
#define CONTROL_FEATURE_BUTTONS_START CONTROL_CONTROLLER_BUTTONS_END
#define CONTROL_FEATURE_BUTTONS_END (CONTROL_FEATURE_BUTTONS_START + MAX_FEATURE_COUNT)
+#define CONTROL_FEATURE_GROUPS_START CONTROL_FEATURE_BUTTONS_END
+#define CONTROL_FEATURE_GROUPS_END (CONTROL_FEATURE_GROUPS_START + MAX_FEATURE_COUNT)
+#define CONTROL_FEATURE_SEPARATORS_START CONTROL_FEATURE_GROUPS_END
+#define CONTROL_FEATURE_SEPARATORS_END (CONTROL_FEATURE_SEPARATORS_START + MAX_FEATURE_COUNT)
diff --git a/xbmc/games/controllers/windows/GUIFeatureList.cpp b/xbmc/games/controllers/windows/GUIFeatureList.cpp
index 862055bb4c..4aa114c870 100644
--- a/xbmc/games/controllers/windows/GUIFeatureList.cpp
+++ b/xbmc/games/controllers/windows/GUIFeatureList.cpp
@@ -19,13 +19,17 @@
*/
#include "GUIFeatureList.h"
+
#include "GUIConfigurationWizard.h"
#include "GUIControllerDefines.h"
#include "games/controllers/guicontrols/GUIAnalogStickButton.h"
+#include "games/controllers/guicontrols/GUIFeatureControls.h"
#include "games/controllers/guicontrols/GUIScalarFeatureButton.h"
#include "games/controllers/Controller.h"
#include "guilib/GUIButtonControl.h"
#include "guilib/GUIControlGroupList.h"
+#include "guilib/GUIImage.h"
+#include "guilib/GUILabelControl.h"
#include "guilib/GUIWindow.h"
using namespace GAME;
@@ -34,6 +38,8 @@ CGUIFeatureList::CGUIFeatureList(CGUIWindow* window) :
m_window(window),
m_guiList(nullptr),
m_guiButtonTemplate(nullptr),
+ m_guiGroupTitle(nullptr),
+ m_guiFeatureSeparator(nullptr),
m_wizard(new CGUIConfigurationWizard)
{
}
@@ -48,11 +54,19 @@ bool CGUIFeatureList::Initialize(void)
{
m_guiList = dynamic_cast<CGUIControlGroupList*>(m_window->GetControl(CONTROL_FEATURE_LIST));
m_guiButtonTemplate = dynamic_cast<CGUIButtonControl*>(m_window->GetControl(CONTROL_FEATURE_BUTTON_TEMPLATE));
+ m_guiGroupTitle = dynamic_cast<CGUILabelControl*>(m_window->GetControl(CONTROL_FEATURE_GROUP_TITLE));
+ m_guiFeatureSeparator = dynamic_cast<CGUIImage*>(m_window->GetControl(CONTROL_FEATURE_SEPARATOR));
if (m_guiButtonTemplate)
m_guiButtonTemplate->SetVisible(false);
- return m_guiList && m_guiButtonTemplate;
+ if (m_guiGroupTitle)
+ m_guiGroupTitle->SetVisible(false);
+
+ if (m_guiFeatureSeparator)
+ m_guiFeatureSeparator->SetVisible(false);
+
+ return m_guiList != nullptr && m_guiButtonTemplate != nullptr;
}
void CGUIFeatureList::Deinitialize(void)
@@ -61,6 +75,8 @@ void CGUIFeatureList::Deinitialize(void)
m_guiList = nullptr;
m_guiButtonTemplate = nullptr;
+ m_guiGroupTitle = nullptr;
+ m_guiFeatureSeparator = nullptr;
}
void CGUIFeatureList::Load(const ControllerPtr& controller)
@@ -70,35 +86,48 @@ void CGUIFeatureList::Load(const ControllerPtr& controller)
CleanupButtons();
+ // Set new controller
m_controller = controller;
+ // Get features
const std::vector<CControllerFeature>& features = controller->Layout().Features();
- for (unsigned int buttonIndex = 0; buttonIndex < features.size(); buttonIndex++)
+ // Split into groups
+ auto featureGroups = GetFeatureGroups(features);
+
+ // Create controls
+ unsigned int featureIndex = 0;
+ for (auto itGroup = featureGroups.begin(); itGroup != featureGroups.end(); ++itGroup)
{
- const CControllerFeature& feature = features[buttonIndex];
+ const std::string& groupName = itGroup->groupName;
- CGUIButtonControl* pButton = nullptr;
- switch (feature.Type())
+ // Create buttons
+ std::vector<CGUIButtonControl*> buttons = GetButtons(itGroup->features, featureIndex);
+ if (!buttons.empty())
{
- case JOYSTICK::FEATURE_TYPE::SCALAR:
+ // Add a separator if the group list isn't empty
+ if (m_guiFeatureSeparator && m_guiList->GetTotalSize() > 0)
{
- pButton = new CGUIScalarFeatureButton(*m_guiButtonTemplate, m_wizard, feature, buttonIndex);
- break;
+ CGUIFeatureSeparator* pSeparator = new CGUIFeatureSeparator(*m_guiFeatureSeparator, featureIndex);
+ m_guiList->AddControl(pSeparator);
}
- case JOYSTICK::FEATURE_TYPE::ANALOG_STICK:
+
+ // Add the group title
+ if (m_guiGroupTitle && !groupName.empty())
{
- pButton = new CGUIAnalogStickButton(*m_guiButtonTemplate, m_wizard, feature, buttonIndex);
- break;
+ CGUIFeatureGroupTitle* pGroupTitle = new CGUIFeatureGroupTitle(*m_guiGroupTitle, groupName, featureIndex);
+ m_guiList->AddControl(pGroupTitle);
}
- default:
- break;
+
+ // Add the buttons
+ for (CGUIButtonControl* pButton : buttons)
+ m_guiList->AddControl(pButton);
+
+ featureIndex += itGroup->features.size();
}
- if (pButton)
- m_guiList->AddControl(pButton);
// Just in case
- if (buttonIndex >= MAX_FEATURE_COUNT)
+ if (featureIndex >= MAX_FEATURE_COUNT)
break;
}
}
@@ -112,10 +141,8 @@ void CGUIFeatureList::OnSelect(unsigned int index)
for ( ; index < featureCount; index++)
{
IFeatureButton* control = GetButtonControl(index);
- if (!control)
- break;
-
- buttons.push_back(control);
+ if (control)
+ buttons.push_back(control);
}
m_wizard->Run(m_controller->ID(), buttons);
@@ -135,3 +162,67 @@ void CGUIFeatureList::CleanupButtons(void)
if (m_guiList)
m_guiList->ClearAll();
}
+
+std::vector<CGUIFeatureList::FeatureGroup> CGUIFeatureList::GetFeatureGroups(const std::vector<CControllerFeature>& features)
+{
+ std::vector<CGUIFeatureList::FeatureGroup> groups;
+
+ // Get group names
+ std::vector<std::string> groupNames;
+ for (const CControllerFeature& feature : features)
+ {
+ if (std::find(groupNames.begin(), groupNames.end(), feature.Group()) == groupNames.end())
+ groupNames.push_back(feature.Group());
+ }
+
+ // Divide features into groups
+ for (std::string& groupName : groupNames)
+ {
+ FeatureGroup group = { groupName };
+ for (const CControllerFeature& feature : features)
+ {
+ if (feature.Group() == groupName)
+ group.features.push_back(feature);
+ }
+ groups.emplace_back(std::move(group));
+ }
+
+ return groups;
+}
+
+std::vector<CGUIButtonControl*> CGUIFeatureList::GetButtons(const std::vector<CControllerFeature>& features, unsigned int startIndex)
+{
+ std::vector<CGUIButtonControl*> buttons;
+
+ // Create buttons
+ unsigned int featureIndex = startIndex;
+ for (const CControllerFeature& feature : features)
+ {
+ CGUIButtonControl* pButton = nullptr;
+
+ // Create button
+ switch (feature.Type())
+ {
+ case JOYSTICK::FEATURE_TYPE::SCALAR:
+ {
+ pButton = new CGUIScalarFeatureButton(*m_guiButtonTemplate, m_wizard, feature, featureIndex);
+ break;
+ }
+ case JOYSTICK::FEATURE_TYPE::ANALOG_STICK:
+ {
+ pButton = new CGUIAnalogStickButton(*m_guiButtonTemplate, m_wizard, feature, featureIndex);
+ break;
+ }
+ default:
+ break;
+ }
+
+ // If successful, add button to result
+ if (pButton)
+ buttons.push_back(pButton);
+
+ featureIndex++;
+ }
+
+ return buttons;
+}
diff --git a/xbmc/games/controllers/windows/GUIFeatureList.h b/xbmc/games/controllers/windows/GUIFeatureList.h
index eb4b890d6e..e5ed44d649 100644
--- a/xbmc/games/controllers/windows/GUIFeatureList.h
+++ b/xbmc/games/controllers/windows/GUIFeatureList.h
@@ -20,11 +20,13 @@
#pragma once
#include "IConfigurationWindow.h"
+#include "games/controllers/ControllerFeature.h"
#include "games/controllers/ControllerTypes.h"
-#include "threads/Thread.h"
class CGUIButtonControl;
class CGUIControlGroupList;
+class CGUIImage;
+class CGUILabelControl;
class CGUIWindow;
namespace GAME
@@ -47,10 +49,21 @@ namespace GAME
void CleanupButtons(void);
+ // Helper functions
+ struct FeatureGroup
+ {
+ std::string groupName;
+ std::vector<CControllerFeature> features;
+ };
+ static std::vector<FeatureGroup> GetFeatureGroups(const std::vector<CControllerFeature>& features);
+ std::vector<CGUIButtonControl*> GetButtons(const std::vector<CControllerFeature>& features, unsigned int startIndex);
+
// GUI stuff
CGUIWindow* const m_window;
CGUIControlGroupList* m_guiList;
CGUIButtonControl* m_guiButtonTemplate;
+ CGUILabelControl* m_guiGroupTitle;
+ CGUIImage* m_guiFeatureSeparator;
// Game window stuff
ControllerPtr m_controller;
diff --git a/xbmc/input/joysticks/JoystickTypes.h b/xbmc/input/joysticks/JoystickTypes.h
index 25e15162cc..fff53f141f 100644
--- a/xbmc/input/joysticks/JoystickTypes.h
+++ b/xbmc/input/joysticks/JoystickTypes.h
@@ -52,21 +52,6 @@ namespace JOYSTICK
};
/*!
- * \brief Types of categories that features can belong to
- *
- * Used to separate lists of features in the GUI.
- */
- enum class FEATURE_CATEGORY
- {
- UNKNOWN,
- FACE,
- SHOULDER,
- TRIGGERS,
- ANALOG_STICKS,
- HAPTICS,
- };
-
- /*!
* \brief Direction arrows on the hat (directional pad)
*/
enum class HAT_DIRECTION