summaryrefslogtreecommitdiff
path: root/Source/Core/InputCommon/ControllerEmu/ControlGroup/ControlGroup.h
blob: c67b0ac13234b74b9bdc9c95ac9f43837f0aafcd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
// Copyright 2017 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#pragma once

#include <algorithm>
#include <cmath>
#include <functional>
#include <memory>
#include <optional>
#include <string>
#include <string_view>
#include <type_traits>
#include <vector>

#include "Common/IniFile.h"
#include "InputCommon/ControllerEmu/Control/Control.h"
#include "InputCommon/ControllerEmu/Setting/NumericSetting.h"
#include "InputCommon/ControllerInterface/CoreDevice.h"

namespace ControllerEmu
{
class Control;

class NumericSettingBase;
struct NumericSettingDetails;

template <typename T>
class NumericSetting;

template <typename T>
class SettingValue;

using InputOverrideFunction = std::function<std::optional<ControlState>(
    const std::string_view group_name, const std::string_view control_name, ControlState state)>;

enum class GroupType
{
  Other,
  Stick,
  MixedTriggers,
  Buttons,
  Force,
  Attachments,
  Tilt,
  Cursor,
  Triggers,
  Slider,
  Shake,
  IMUAccelerometer,
  IMUGyroscope,
  IMUCursor,
  IRPassthrough,
};

class ControlGroup
{
public:
  enum class DefaultValue
  {
    AlwaysEnabled,
    Enabled,
    Disabled,
  };

  explicit ControlGroup(const std::string& name, GroupType type = GroupType::Other,
                        DefaultValue default_value = DefaultValue::AlwaysEnabled);
  ControlGroup(std::string name, std::string ui_name, GroupType type = GroupType::Other,
               DefaultValue default_value = DefaultValue::AlwaysEnabled);
  virtual ~ControlGroup();

  virtual void LoadConfig(Common::IniFile::Section* sec, const std::string& base);
  virtual void SaveConfig(Common::IniFile::Section* sec, const std::string& base);

  virtual void UpdateReferences(ciface::ExpressionParser::ControlEnvironment& env);

  void SetControlExpression(int index, const std::string& expression);

  void AddInput(Translatability translate, std::string name);
  void AddInput(Translatability translate, std::string name, std::string ui_name);
  void AddOutput(Translatability translate, std::string name);

  template <typename T>
  void AddSetting(SettingValue<T>* value, const NumericSettingDetails& details,
                  std::common_type_t<T> default_value_, std::common_type_t<T> min_value = {},
                  std::common_type_t<T> max_value = T(100))
  {
    numeric_settings.emplace_back(
        std::make_unique<NumericSetting<T>>(value, details, default_value_, min_value, max_value));
  }

  void AddVirtualNotchSetting(SettingValue<double>* value, double max_virtual_notch_deg);

  void AddDeadzoneSetting(SettingValue<double>* value, double maximum_deadzone);

  template <typename T>
  static T ApplyDeadzone(T input, std::common_type_t<T> deadzone)
  {
    return std::copysign(std::max(T{0}, std::abs(input) - deadzone) / (T{1} - deadzone), input);
  }

  bool HasEnabledSetting() const;

  const std::string name;
  const std::string ui_name;
  const GroupType type;

  // The default "enabled" state.
  const DefaultValue default_value;
  SettingValue<bool> enabled;
  std::unique_ptr<NumericSetting<bool>> enabled_setting;

  std::vector<std::unique_ptr<Control>> controls;
  std::vector<std::unique_ptr<NumericSettingBase>> numeric_settings;
};
}  // namespace ControllerEmu