[gnome-games/wip/abhinavsingh/gamepad-config: 32/35] ui: Add GamepadMapper
- From: Abhinav Singh <abhinavsingh src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-games/wip/abhinavsingh/gamepad-config: 32/35] ui: Add GamepadMapper
- Date: Tue, 18 Jul 2017 11:36:32 +0000 (UTC)
commit e11fd333d4d07cf0d7a55d674d7cadd34c40ee7f
Author: theawless <theawless gmail com>
Date: Sun May 28 14:55:59 2017 +0530
ui: Add GamepadMapper
GamepadMapper uses GamepadView to get the user input,
GamepadMappingBuilder to build the sdl string from those inputs and
saves it using GamepadMappingsManager.
data/Makefile.am | 1 +
data/org.gnome.Games.gresource.xml | 1 +
data/ui/gamepad-mapper.ui | 103 +++++++++++++
src/Makefile.am | 1 +
src/ui/gamepad-mapper.vala | 282 ++++++++++++++++++++++++++++++++++++
5 files changed, 388 insertions(+), 0 deletions(-)
---
diff --git a/data/Makefile.am b/data/Makefile.am
index cf1b58b..5f3d675 100644
--- a/data/Makefile.am
+++ b/data/Makefile.am
@@ -37,6 +37,7 @@ EXTRA_DIST = \
ui/empty-collection.ui \
ui/error-display.ui \
ui/error-info-bar.ui \
+ ui/gamepad-mapper.ui \
ui/game-icon-view.ui \
ui/media-menu-button.ui \
ui/media-selector.ui \
diff --git a/data/org.gnome.Games.gresource.xml b/data/org.gnome.Games.gresource.xml
index 9e14d6f..49a7af4 100644
--- a/data/org.gnome.Games.gresource.xml
+++ b/data/org.gnome.Games.gresource.xml
@@ -16,6 +16,7 @@
<file preprocess="xml-stripblanks">ui/empty-collection.ui</file>
<file preprocess="xml-stripblanks">ui/error-display.ui</file>
<file preprocess="xml-stripblanks">ui/error-info-bar.ui</file>
+ <file preprocess="xml-stripblanks">ui/gamepad-mapper.ui</file>
<file preprocess="xml-stripblanks">ui/game-icon-view.ui</file>
<file preprocess="xml-stripblanks">ui/media-menu-button.ui</file>
<file preprocess="xml-stripblanks">ui/media-selector.ui</file>
diff --git a/data/ui/gamepad-mapper.ui b/data/ui/gamepad-mapper.ui
new file mode 100644
index 0000000..7b04b28
--- /dev/null
+++ b/data/ui/gamepad-mapper.ui
@@ -0,0 +1,103 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="GamesGamepadMapper" parent="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkBox" id="gamepad_view_holder">
+ <property name="visible">True</property>
+ <property name="halign">fill</property>
+ <property name="valign">fill</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkActionBar" id="action_bar">
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkButton" id="apply_button">
+ <property name="visible">True</property>
+ <property name="can-default">True</property>
+ <property name="label" translatable="yes">Apply</property>
+ <signal name="clicked" handler="on_apply_clicked"/>
+ <style>
+ <class name="suggested-action"/>
+ </style>
+ </object>
+ <packing>
+ <property name="pack-type">start</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="reset_button">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Reset</property>
+ <signal name="clicked" handler="on_reset_clicked"/>
+ <style>
+ <class name="destructive-action"/>
+ </style>
+ </object>
+ <packing>
+ <property name="pack-type">end</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="skip_button">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Skip</property>
+ <signal name="clicked" handler="on_skip_clicked"/>
+ </object>
+ <packing>
+ <property name="pack-type">start</property>
+ </packing>
+ </child>
+ <child type="center">
+ <object class="GtkLabel" id="info_message">
+ <property name="visible">True</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+ <object class="GtkBox" id="header_content">
+ <property name="orientation">horizontal</property>
+ <property name="visible">True</property>
+ <property name="spacing">2</property>
+ <property name="hexpand">True</property>
+ <child>
+ <object class="GtkButton" id="back_button">
+ <property name="visible">True</property>
+ <signal name="clicked" handler="on_back_clicked"/>
+ <style>
+ <class name="image-button"/>
+ </style>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="a11y-back">
+ <property name="accessible-name" translatable="yes">Back</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkImage" id="back_image">
+ <property name="visible">True</property>
+ <property name="icon-name">go-previous-symbolic</property>
+ <property name="icon-size">1</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="pack-type">start</property>
+ </packing>
+ </child>
+ <child type="center">
+ <object class="GtkLabel" id="title">
+ <property name="visible">True</property>
+ <style>
+ <class name="title"/>
+ </style>
+ </object>
+ </child>
+ </object>
+</interface>
diff --git a/src/Makefile.am b/src/Makefile.am
index 7ae7af8..d5772fa 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -133,6 +133,7 @@ gnome_games_SOURCES = \
ui/empty-collection.vala \
ui/error-display.vala \
ui/error-info-bar.vala \
+ ui/gamepad-mapper.vala \
ui/gamepad-view.vala \
ui/game-icon-view.vala \
ui/game-thumbnail.vala \
diff --git a/src/ui/gamepad-mapper.vala b/src/ui/gamepad-mapper.vala
new file mode 100644
index 0000000..5983e81
--- /dev/null
+++ b/src/ui/gamepad-mapper.vala
@@ -0,0 +1,282 @@
+// This file is part of GNOME Games. License: GPL-3.0+.
+
+[GtkTemplate (ui = "/org/gnome/Games/ui/gamepad-mapper.ui")]
+private class Games.GamepadMapper : Gtk.Box {
+ public signal void back ();
+
+ private enum State {
+ BEGIN,
+ CONFIGURE,
+ FINISH,
+ }
+
+ private State? _state;
+ private State? state {
+ set {
+ switch (value) {
+ case State.BEGIN:
+ apply_button.set_sensitive (false);
+ title.label = _("Configuring ") + gamepad.name;
+ connect_to_gamepad ();
+
+ break;
+ case State.CONFIGURE:
+ gamepad_view.reset ();
+ gamepad_view.highlight (input, true);
+
+ break;
+ case State.FINISH:
+ gamepad_view.reset ();
+ skip_button.set_sensitive (false);
+ apply_button.set_sensitive (true);
+ title.label = _("Finished configuration");
+ disconnect_from_gamepad ();
+
+ break;
+ }
+
+ _state = value;
+ }
+ get { return _state; }
+ }
+
+ private GamepadInput? _input;
+ private GamepadInput? input {
+ set {
+ _input = value;
+ if (_input == null) {
+ info_message.label = "";
+
+ return;
+ }
+
+ switch (input.type) {
+ case EventCode.EV_KEY:
+ info_message.label = _("Press suitable button on your gamepad");
+
+ break;
+ case EventCode.EV_ABS:
+ if (input.code == EventCode.ABS_X || input.code == EventCode.ABS_RX)
+ info_message.label = _("Move suitable axis left/right on your
gamepad");
+ else if (input.code == EventCode.ABS_Y || input.code == EventCode.ABS_RY)
+ info_message.label = _("Move suitable axis up/down on your gamepad");
+
+ break;
+ default:
+ break;
+ }
+ }
+ get { return _input; }
+ }
+
+ [GtkChild]
+ public Gtk.Box header_content;
+ [GtkChild]
+ private Gtk.Button apply_button;
+ [GtkChild]
+ private Gtk.Button skip_button;
+ [GtkChild]
+ private Gtk.Box gamepad_view_holder;
+ [GtkChild]
+ private Gtk.Label title;
+ [GtkChild]
+ private Gtk.Label info_message;
+
+ private const GamepadInput[] STANDARD_GAMEPAD_INPUTS = {
+ { EventCode.EV_KEY, EventCode.BTN_A },
+ { EventCode.EV_KEY, EventCode.BTN_B },
+ { EventCode.EV_KEY, EventCode.BTN_X },
+ { EventCode.EV_KEY, EventCode.BTN_Y },
+ { EventCode.EV_KEY, EventCode.BTN_THUMBL },
+ { EventCode.EV_KEY, EventCode.BTN_THUMBR },
+ { EventCode.EV_KEY, EventCode.BTN_TL },
+ { EventCode.EV_KEY, EventCode.BTN_TR },
+ { EventCode.EV_KEY, EventCode.BTN_TL2 },
+ { EventCode.EV_KEY, EventCode.BTN_TR2 },
+ { EventCode.EV_KEY, EventCode.BTN_DPAD_UP },
+ { EventCode.EV_KEY, EventCode.BTN_DPAD_LEFT },
+ { EventCode.EV_KEY, EventCode.BTN_DPAD_DOWN },
+ { EventCode.EV_KEY, EventCode.BTN_DPAD_RIGHT },
+ { EventCode.EV_KEY, EventCode.BTN_SELECT },
+ { EventCode.EV_KEY, EventCode.BTN_MODE },
+ { EventCode.EV_KEY, EventCode.BTN_START },
+ { EventCode.EV_ABS, EventCode.ABS_X },
+ { EventCode.EV_ABS, EventCode.ABS_RX },
+ { EventCode.EV_ABS, EventCode.ABS_Y },
+ { EventCode.EV_ABS, EventCode.ABS_RY },
+ };
+
+ private const GamepadInputPath[] STANDARD_GAMEPAD_INPUT_PATHS = {
+ { { EventCode.EV_ABS, EventCode.ABS_X }, "leftx" },
+ { { EventCode.EV_ABS, EventCode.ABS_Y }, "lefty" },
+ { { EventCode.EV_ABS, EventCode.ABS_RX }, "rightx" },
+ { { EventCode.EV_ABS, EventCode.ABS_RY }, "righty" },
+ { { EventCode.EV_KEY, EventCode.BTN_A }, "a" },
+ { { EventCode.EV_KEY, EventCode.BTN_B }, "b" },
+ { { EventCode.EV_KEY, EventCode.BTN_DPAD_DOWN }, "dpdown" },
+ { { EventCode.EV_KEY, EventCode.BTN_DPAD_LEFT }, "dpleft" },
+ { { EventCode.EV_KEY, EventCode.BTN_DPAD_RIGHT }, "dpright" },
+ { { EventCode.EV_KEY, EventCode.BTN_DPAD_UP }, "dpup" },
+ { { EventCode.EV_KEY, EventCode.BTN_MODE }, "guide" },
+ { { EventCode.EV_KEY, EventCode.BTN_SELECT }, "back" },
+ { { EventCode.EV_KEY, EventCode.BTN_TL }, "leftshoulder" },
+ { { EventCode.EV_KEY, EventCode.BTN_TR }, "rightshoulder" },
+ { { EventCode.EV_KEY, EventCode.BTN_START }, "start" },
+ { { EventCode.EV_KEY, EventCode.BTN_THUMBL }, "leftstick" },
+ { { EventCode.EV_KEY, EventCode.BTN_THUMBR }, "rightstick" },
+ { { EventCode.EV_KEY, EventCode.BTN_TL2 }, "lefttrigger" },
+ { { EventCode.EV_KEY, EventCode.BTN_TR2 }, "righttrigger" },
+ { { EventCode.EV_KEY, EventCode.BTN_Y }, "x" },
+ { { EventCode.EV_KEY, EventCode.BTN_X }, "y" },
+ };
+
+ private const GamepadViewConfiguration STANDARD_GAMEPAD_VIEW_CONFIGURATION = {
+ "resource:///org/gnome/Games/gamepads/standard-gamepad.svg", STANDARD_GAMEPAD_INPUT_PATHS
+ };
+
+ private Gamepad gamepad;
+ private GamepadView gamepad_view;
+ private GamepadMappingBuilder mapping_builder;
+ private ulong gamepad_event_handler_id;
+ private uint current_input_index;
+
+ public GamepadMapper (Gamepad gamepad) {
+ this.gamepad = gamepad;
+ mapping_builder = new GamepadMappingBuilder ();
+ state = State.BEGIN;
+ current_input_index = 0;
+
+ gamepad_view = new GamepadView (STANDARD_GAMEPAD_VIEW_CONFIGURATION);
+ gamepad_view_holder.pack_start (gamepad_view);
+ gamepad_view.show ();
+ }
+
+ public void start () {
+ next_input ();
+ }
+
+ [GtkCallback]
+ private void on_apply_clicked () {
+ save_mapping ();
+ back ();
+ }
+
+ [GtkCallback]
+ private void on_skip_clicked () {
+ next_input ();
+ }
+
+ [GtkCallback]
+ private void on_reset_clicked () {
+ reset_mapping ();
+ back ();
+ }
+
+ [GtkCallback]
+ private void on_back_clicked () {
+ back ();
+ }
+
+ private void connect_to_gamepad () {
+ gamepad_event_handler_id = this.gamepad.event.connect ((event) => {
+ switch (event.type) {
+ case EventType.EVENT_GAMEPAD_BUTTON_RELEASE:
+ on_button_event (event.gamepad_button);
+
+ break;
+ case EventType.EVENT_GAMEPAD_AXIS:
+ on_axis_event (event.gamepad_axis);
+
+ break;
+ case EventType.EVENT_GAMEPAD_HAT:
+ on_hat_event (event.gamepad_hat);
+
+ break;
+ default:
+ break;
+ }
+ });
+ }
+
+ private void disconnect_from_gamepad () {
+ gamepad.disconnect (gamepad_event_handler_id);
+ }
+
+ private void on_button_event (EventGamepadButton event) {
+ if (input.type == EventCode.EV_ABS)
+ return;
+
+ var success = mapping_builder.set_button_mapping (event.gamepad_button.hardware_index,
+ input);
+ if (!success)
+ return;
+
+ next_input ();
+ }
+
+ private void on_axis_event (EventGamepadAxis event) {
+ if (input.type == EventCode.EV_KEY)
+ return;
+
+ if (-0.8 < event.gamepad_axis.value && event.gamepad_axis.value < 0.8)
+ return;
+
+ var success = mapping_builder.set_axis_mapping (event.gamepad_axis.hardware_index,
+ input);
+ if (!success)
+ return;
+
+ next_input ();
+ }
+
+ private void on_hat_event (EventGamepadHat event) {
+ if (event.gamepad_hat.value == 0)
+ return;
+
+ var success = mapping_builder.set_hat_mapping (event.gamepad_hat.hardware_index,
+ event.gamepad_hat.value,
+ event.gamepad_hat.axis,
+ input);
+ if (!success)
+ return;
+
+ next_input ();
+ }
+
+ private void next_input () {
+ if (state == State.FINISH)
+ return;
+ if (current_input_index >= STANDARD_GAMEPAD_INPUTS.length) {
+ input = null;
+ state = State.FINISH;
+
+ return;
+ }
+
+ input = STANDARD_GAMEPAD_INPUTS[current_input_index++];
+ state = State.CONFIGURE;
+ }
+
+ private void save_mapping () {
+ var sdl_string = mapping_builder.build_sdl_string ();
+ save_sdl_string (sdl_string);
+ }
+
+ private void reset_mapping () {
+ var mappings_manager = GamepadMappingsManager.get_instance ();
+ var sdl_string = mappings_manager.get_default_mapping (gamepad.guid);
+ save_sdl_string (sdl_string);
+ }
+
+ private void save_sdl_string (string sdl_string) {
+ var mappings_manager = GamepadMappingsManager.get_instance ();
+ try {
+ var mapping = new GamepadMapping.from_sdl_string (sdl_string);
+ gamepad.set_mapping (mapping);
+ mappings_manager.save_mapping (gamepad.guid, gamepad.name, sdl_string);
+ }
+ catch (Error e) {
+ warning (e.message);
+ }
+ }
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]