Skip to content

Commit 13d8ab9

Browse files
committed
Update Title/State Monitors to new json settings format
1 parent 8e184b0 commit 13d8ab9

7 files changed

Lines changed: 92 additions & 82 deletions

File tree

Sources/backend-cpp/StreamdeckContext/ExportMonitors/ImageStateMonitor.cpp

Lines changed: 36 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -6,54 +6,62 @@
66

77
ImageStateMonitor::ImageStateMonitor(const json &settings) { update_settings(settings); }
88

9-
void ImageStateMonitor::update_settings(const json &settings)
9+
void ImageStateMonitor::update_settings(const json &state_monitor_settings)
1010
{
11-
const std::string dcs_id_compare_monitor_raw = EPLJSONUtils::GetStringByName(settings, "dcs_id_compare_monitor");
12-
const std::string dcs_id_compare_condition_raw =
13-
EPLJSONUtils::GetStringByName(settings, "dcs_id_compare_condition");
14-
const std::string dcs_id_comparison_value_raw = EPLJSONUtils::GetStringByName(settings, "dcs_id_comparison_value");
11+
settings_per_state_.clear();
12+
monitor_is_set_ = state_monitor_settings.size() > 0;
1513

16-
const bool compare_monitor_is_populated = is_integer(dcs_id_compare_monitor_raw);
17-
const bool comparison_value_is_populated = is_number(dcs_id_comparison_value_raw);
18-
settings_are_filled_ = compare_monitor_is_populated && comparison_value_is_populated;
19-
20-
if (settings_are_filled_) {
21-
dcs_id_compare_monitor_ = std::stoi(dcs_id_compare_monitor_raw);
22-
dcs_id_comparison_value_ = Decimal(dcs_id_comparison_value_raw);
23-
if (dcs_id_compare_condition_raw == "EQUAL_TO") {
24-
dcs_id_compare_condition_ = Comparison::EQUAL_TO;
25-
} else if (dcs_id_compare_condition_raw == "LESS_THAN") {
26-
dcs_id_compare_condition_ = Comparison::LESS_THAN;
27-
} else // Default in Property Inspector html is GREATER_THAN.
28-
{
29-
dcs_id_compare_condition_ = Comparison::GREATER_THAN;
14+
if (monitor_is_set_) {
15+
for (const auto &state : state_monitor_settings) {
16+
const auto addr = SimulatorAddress(state["monitor_address"]["address"],
17+
state["monitor_address"]["mask"],
18+
state["monitor_address"]["shift"]);
19+
Comparison comp_type;
20+
if (state["comparison_type"] == "LT") {
21+
comp_type = Comparison::LESS_THAN;
22+
} else if (state["comparison_type"] == "GT") {
23+
comp_type = Comparison::GREATER_THAN;
24+
} else {
25+
comp_type = Comparison::EQUAL_TO;
26+
}
27+
settings_per_state_.push_back(StateMonitorSettings{addr, comp_type, Decimal(state["comparison_value"])});
3028
}
3129
}
3230
}
3331

3432
int ImageStateMonitor::determineContextState(SimulatorInterface *simulator_interface) const
3533
{
36-
if (settings_are_filled_) {
37-
const auto maybe_current_game_value = simulator_interface->get_value_at_addr(dcs_id_compare_monitor_);
38-
if (maybe_current_game_value.has_value()) {
39-
return comparison_is_satisfied(maybe_current_game_value.value()) ? 1 : 0;
34+
if (monitor_is_set_) {
35+
for (int iState = 0; iState < settings_per_state_.size(); ++iState) {
36+
const auto maybe_value = simulator_interface->get_value_at_addr(settings_per_state_[iState].address);
37+
if (!maybe_value) {
38+
return 0; // Return early if not all addresses are readable.
39+
}
40+
if (maybe_value && comparison_is_satisfied(maybe_value.value())) {
41+
return iState;
42+
}
4043
}
44+
// If no conditional states are satisfied, then the last state is set.
45+
return settings_per_state_.size() + 1;
4146
}
47+
// Default to first state.
4248
return 0;
4349
}
4450

45-
bool ImageStateMonitor::comparison_is_satisfied(Decimal current_game_value) const
51+
bool ImageStateMonitor::comparison_is_satisfied(const Decimal &current_game_value,
52+
const Comparison &comparison,
53+
const Decimal &comparison_value) const
4654
{
4755
bool comparison_result = false;
48-
switch (dcs_id_compare_condition_) {
56+
switch (comparison) {
4957
case Comparison::EQUAL_TO:
50-
comparison_result = (current_game_value == dcs_id_comparison_value_);
58+
comparison_result = (current_game_value == comparison_value);
5159
break;
5260
case Comparison::LESS_THAN:
53-
comparison_result = (current_game_value < dcs_id_comparison_value_);
61+
comparison_result = (current_game_value < comparison_value);
5462
break;
5563
case Comparison::GREATER_THAN:
56-
comparison_result = (current_game_value > dcs_id_comparison_value_);
64+
comparison_result = (current_game_value > comparison_value);
5765
break;
5866
}
5967
return comparison_result;

Sources/backend-cpp/StreamdeckContext/ExportMonitors/ImageStateMonitor.h

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,17 +31,24 @@ class ImageStateMonitor
3131
private:
3232
enum class Comparison { GREATER_THAN, EQUAL_TO, LESS_THAN };
3333

34+
using StateMonitorSettings = struct {
35+
SimulatorAddress address;
36+
Comparison comparison;
37+
Decimal comparison_value;
38+
};
39+
3440
/**
35-
* @brief Checks if current game value satisfies the comparison criteria configured in settings.
36-
*
37-
* @param current_game_value
41+
* @brief Checks if current game value satisfies the comparison criteria for state.
3842
*/
39-
bool comparison_is_satisfied(Decimal current_game_value) const;
43+
bool comparison_is_satisfied(const Decimal &current_game_value,
44+
const Comparison &comparison,
45+
const Decimal &comparison_value) const;
4046

4147
// Status of user-filled fields.
42-
bool settings_are_filled_ = false; // True if all DCS ID comparison monitor settings have been set.
48+
bool monitor_is_set_ = false; // True if all monitor settings have been set.
4349

4450
// Stored settings extracted from user-filled fields.
51+
std::vector<StateMonitorSettings> settings_per_state_;
4552
int dcs_id_compare_monitor_ = 0; // DCS ID to monitor for context state setting according to value comparison.
4653
Comparison dcs_id_compare_condition_ = Comparison::GREATER_THAN; // Comparison to use for DCS ID compare monitor.
4754
Decimal dcs_id_comparison_value_; // Value to compare DCS ID compare monitor value to.

Sources/backend-cpp/StreamdeckContext/ExportMonitors/TitleMonitor.cpp

Lines changed: 14 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -6,34 +6,15 @@
66

77
TitleMonitor::TitleMonitor(const json &settings) { update_settings(settings); }
88

9-
void TitleMonitor::update_settings(const json &settings)
9+
void TitleMonitor::update_settings(const json &title_monitor_settings)
1010
{
11-
const std::string dcs_id_string_monitor_raw = EPLJSONUtils::GetStringByName(settings, "dcs_id_string_monitor");
12-
// Set boolean from checkbox using default false value if it doesn't exist in "settings".
13-
const std::string string_monitor_vertical_spacing_raw =
14-
EPLJSONUtils::GetStringByName(settings, "string_monitor_vertical_spacing");
15-
string_monitor_passthrough_ = EPLJSONUtils::GetBoolByName(settings, "string_monitor_passthrough_check", true);
16-
std::stringstream string_monitor_mapping_raw;
17-
string_monitor_mapping_raw << EPLJSONUtils::GetStringByName(settings, "string_monitor_mapping");
18-
19-
string_monitor_is_set_ = is_integer(dcs_id_string_monitor_raw);
20-
11+
string_monitor_is_set_ = title_monitor_settings["is_set"];
2112
if (string_monitor_is_set_) {
22-
const auto addr = std::stoi(dcs_id_string_monitor_raw);
23-
dcs_id_string_monitor_ = settings.contains("string_monitor_max_string_length")
24-
? SimulatorAddress(addr, settings["string_monitor_max_string_length"])
25-
: SimulatorAddress(addr);
26-
27-
if (is_integer(string_monitor_vertical_spacing_raw)) {
28-
string_monitor_vertical_spacing_ = std::stoi(string_monitor_vertical_spacing_raw);
29-
}
30-
if (!string_monitor_passthrough_) {
31-
string_monitor_mapping_.clear();
32-
std::optional<std::pair<std::string, std::string>> maybe_token_pair;
33-
while (maybe_token_pair = pop_key_and_value(string_monitor_mapping_raw, ',', '=')) {
34-
string_monitor_mapping_[maybe_token_pair.value().first] = maybe_token_pair.value().second;
35-
}
36-
}
13+
monitor_address_ = SimulatorAddress(title_monitor_settings["monitor_address"][0]["address"],
14+
title_monitor_settings["monitor_address"][0]["max_len"]);
15+
modify_string_ = title_monitor_settings["modify_string"];
16+
vertical_spacing_ =
17+
title_monitor_settings.contains("vertical_spacing") ? title_monitor_settings["vertical_spacing"] : 0;
3718
}
3819
}
3920

@@ -43,7 +24,7 @@ std::string TitleMonitor::determineTitle(SimulatorInterface *simulator_interface
4324

4425
if (string_monitor_is_set_) {
4526
const std::optional<std::string> maybe_current_game_value =
46-
simulator_interface->get_string_at_addr(dcs_id_string_monitor_);
27+
simulator_interface->get_string_at_addr(monitor_address_);
4728
if (maybe_current_game_value.has_value()) {
4829
updated_title = convertGameStateToTitle(maybe_current_game_value.value());
4930
}
@@ -55,18 +36,18 @@ std::string TitleMonitor::determineTitle(SimulatorInterface *simulator_interface
5536
std::string TitleMonitor::convertGameStateToTitle(const std::string &current_game_value)
5637
{
5738
std::string title;
58-
if (string_monitor_passthrough_) {
59-
title = current_game_value;
60-
} else {
39+
if (modify_string_) {
6140
title = string_monitor_mapping_[current_game_value];
41+
} else {
42+
title = current_game_value;
6243
}
6344
// Apply vertical spacing.
64-
if (string_monitor_vertical_spacing_ < 0) {
65-
for (int i = 0; i > string_monitor_vertical_spacing_; --i) {
45+
if (vertical_spacing_ < 0) {
46+
for (int i = 0; i > vertical_spacing_; --i) {
6647
title = "\n" + title;
6748
}
6849
} else {
69-
for (int i = 0; i < string_monitor_vertical_spacing_; ++i) {
50+
for (int i = 0; i < vertical_spacing_; ++i) {
7051
title = title + "\n";
7152
}
7253
}

Sources/backend-cpp/StreamdeckContext/ExportMonitors/TitleMonitor.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,9 @@ class TitleMonitor
3838

3939
bool string_monitor_is_set_ = false; // True if all DCS ID string monitor settings have been set.
4040

41-
SimulatorAddress dcs_id_string_monitor_{0}; // Simulator address to monitor for context title.
42-
int string_monitor_vertical_spacing_ = 0; // Vertical spacing (number of '\n') to include before or after title.
43-
bool string_monitor_passthrough_ = true; // Flag set by user to passthrough string to title unaltered.
41+
SimulatorAddress monitor_address_{0}; // Simulator address to monitor for context title.
42+
int vertical_spacing_ = 0; // Vertical spacing (number of '\n') to include before or after title.
43+
bool modify_string_ = false; // Flag set if string should be modified before using as title.
4444
std::unordered_map<std::string, std::string>
4545
string_monitor_mapping_; // Map of received values to title text to display on context.
4646
};

Sources/frontend-react-js/src/comms/StreamdeckButtonSettings.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,15 @@ export default interface StreamdeckButtonSettings {
99

1010
export interface StateMonitorSettings {
1111
monitor_address: SimulatorAddress;
12-
condition_type: "LT" | "EQ" | "GT";
12+
comparison_type: "LT" | "EQ" | "GT";
1313
comparison_value: string;
1414
}
1515

1616
export interface TitleMonitorSettings {
1717
monitor_address: SimulatorAddress[];
1818
modify_string: boolean;
19-
string_monitor_vertical_spacing: string;
20-
string_monitor_mapping: string;
19+
vertical_spacing?: number;
20+
mapping?: string;
2121
is_set: boolean;
2222
}
2323

@@ -55,7 +55,7 @@ interface SimulatorAddress {
5555
type: "ADDRESS_ONLY" | "INTEGER" | "STRING";
5656
mask?: number;
5757
shift?: number;
58-
max_length?: number;
58+
max_len?: number;
5959
}
6060

6161

Sources/frontend-react-js/src/pages/UserInput.tsx

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { ChangeEvent, useState } from "react";
22
import StreamdeckApi from "../comms/StreamdeckApi";
3+
import StreamdeckButtonSettings from "../comms/StreamdeckButtonSettings";
34

45
interface Props {
56
sdApi: StreamdeckApi
@@ -9,8 +10,8 @@ function UserInput({ sdApi }: Props): JSX.Element {
910

1011
const [sendAddress, setSendAddress] = useState(sdApi.buttonSettings.send_address);
1112
const [pressValue, setPressValue] = useState(sdApi.buttonSettings.press_value);
12-
const [titleMonitorAddress, setTitleMonitorAddress] = useState(sdApi.buttonSettings.dcs_id_string_monitor);
13-
const [titleMonitorStrLen, setTitleMonitorStrLen] = useState(sdApi.buttonSettings.string_monitor_max_string_length);
13+
const [titleMonitorAddress, setTitleMonitorAddress] = useState("");
14+
const [titleMonitorStrLen, setTitleMonitorStrLen] = useState(0);
1415

1516
function handleSendAddressChange(event: ChangeEvent<HTMLInputElement>) {
1617
setSendAddress(event.currentTarget.value);
@@ -29,13 +30,26 @@ function UserInput({ sdApi }: Props): JSX.Element {
2930
}
3031

3132
function handleSubmitButtonClick() {
32-
const updatedSettings = Object.assign({}, sdApi.buttonSettings, {
33-
send_address: sendAddress,
34-
press_value: pressValue,
35-
release_value: "0",
36-
dcs_id_string_monitor: titleMonitorAddress,
37-
string_monitor_max_string_length: titleMonitorStrLen,
38-
});
33+
const settings: StreamdeckButtonSettings = {
34+
title_monitor: {
35+
monitor_address: [{
36+
address: titleMonitorAddress,
37+
max_length: titleMonitorStrLen,
38+
type: "STRING"
39+
}],
40+
modify_string: false,
41+
vertical_spacing: 0,
42+
is_set: true,
43+
},
44+
constant_action: {
45+
on_press: [{
46+
send_address: sendAddress,
47+
value: pressValue
48+
}],
49+
type: "CONST"
50+
},
51+
};
52+
const updatedSettings = Object.assign({}, sdApi.buttonSettings, settings);
3953
sdApi.commFns.setSettings(updatedSettings);
4054
}
4155

0 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)