Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#include "Utilities/StringUtilities.h"

SimulatorAddress::SimulatorAddress() : type(AddressType::UNDEFINED) {}
SimulatorAddress::SimulatorAddress(unsigned int address) : type(AddressType::ADDRESS_ONLY), address(address) {}
SimulatorAddress::SimulatorAddress(unsigned int address, unsigned int mask, uint8_t shift)
: type(AddressType::INTEGER), address(address), mask(mask), shift(shift)
Expand Down
3 changes: 2 additions & 1 deletion Sources/backend-cpp/SimulatorInterface/SimulatorInterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ using SimulatorConnectionSettings = struct {
std::string multicast_address; // UDP Multicast address group to join.
};

enum class AddressType { ADDRESS_ONLY, INTEGER, STRING };
enum class AddressType { UNDEFINED, ADDRESS_ONLY, INTEGER, STRING };

struct SimulatorAddress {
AddressType type;
Expand All @@ -30,6 +30,7 @@ struct SimulatorAddress {
// Only for STRING:
unsigned int max_length;

SimulatorAddress();
SimulatorAddress(unsigned int address);
SimulatorAddress(unsigned int address, unsigned int mask, uint8_t shift);
SimulatorAddress(unsigned int address, unsigned int max_length);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,66 +6,71 @@

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

void ImageStateMonitor::update_settings(const json &settings)
void ImageStateMonitor::update_settings(const json &state_monitor_settings)
{
const std::string dcs_id_compare_monitor_raw = EPLJSONUtils::GetStringByName(settings, "dcs_id_compare_monitor");
const std::string dcs_id_compare_condition_raw =
EPLJSONUtils::GetStringByName(settings, "dcs_id_compare_condition");
const std::string dcs_id_comparison_value_raw = EPLJSONUtils::GetStringByName(settings, "dcs_id_comparison_value");
settings_per_state_.clear();
monitor_is_set_ = state_monitor_settings["is_set"];

const bool compare_monitor_is_populated = !dcs_id_compare_monitor_raw.empty();
const bool comparison_value_is_populated = is_number(dcs_id_comparison_value_raw);
settings_are_filled_ = compare_monitor_is_populated && comparison_value_is_populated;

if (settings_are_filled_) {
if (is_integer(dcs_id_compare_monitor_raw)) {
dcs_id_compare_monitor_ = SimulatorAddress(std::stoi(dcs_id_compare_monitor_raw));
if (monitor_is_set_) {
for (const auto &state : state_monitor_settings) {
SimulatorAddress address;
if (state["monitor_address"]["type"] == "INTEGER") {
address = SimulatorAddress{state["monitor_address"]["address"],
state["monitor_address"]["mask"],
state["monitor_address"]["shift"]};
} else if (state["monitor_address"]["type"] == "ADDRESS_ONLY") {
address = SimulatorAddress{state["monitor_address"]["address"]};
} else {
// Unsupported type.
break;
}

} else {
if (dcs_id_compare_monitor_raw == "INTEGER") {
dcs_id_compare_monitor_ = SimulatorAddress(settings["compare_monitor_address"],
settings["compare_monitor_mask"],
settings["compare_monitor_shift"]);
} else if (dcs_id_compare_monitor_raw == "STRING") {
dcs_id_compare_monitor_ =
SimulatorAddress(settings["compare_monitor_address"], settings["compare_monitor_max_length"]);
Comparison comp_type;
if (state["comparison_type"] == "LT") {
comp_type = Comparison::LESS_THAN;
} else if (state["comparison_type"] == "GT") {
comp_type = Comparison::GREATER_THAN;
} else {
comp_type = Comparison::EQUAL_TO;
}
}
dcs_id_comparison_value_ = Decimal(dcs_id_comparison_value_raw);
if (dcs_id_compare_condition_raw == "EQUAL_TO") {
dcs_id_compare_condition_ = Comparison::EQUAL_TO;
} else if (dcs_id_compare_condition_raw == "LESS_THAN") {
dcs_id_compare_condition_ = Comparison::LESS_THAN;
} else // Default in Property Inspector html is GREATER_THAN.
{
dcs_id_compare_condition_ = Comparison::GREATER_THAN;
settings_per_state_.push_back(StateMonitorSettings{address, comp_type, Decimal(state["comparison_value"])});
}
}
}

int ImageStateMonitor::determineContextState(SimulatorInterface *simulator_interface) const
{
if (settings_are_filled_) {
const auto maybe_current_game_value = simulator_interface->get_value_at_addr(dcs_id_compare_monitor_);
if (maybe_current_game_value.has_value()) {
return comparison_is_satisfied(maybe_current_game_value.value()) ? 1 : 0;
if (monitor_is_set_) {
for (int iState = 0; iState < settings_per_state_.size(); ++iState) {
const auto maybe_value = simulator_interface->get_value_at_addr(settings_per_state_[iState].address);
if (!maybe_value) {
return 0; // Return early if not all addresses are readable.
}
if (maybe_value && comparison_is_satisfied(maybe_value.value())) {
return iState;
}
}
// If no conditional states are satisfied, then the last state is set.
return settings_per_state_.size() + 1;
}
// Default to first state.
return 0;
}

bool ImageStateMonitor::comparison_is_satisfied(Decimal current_game_value) const
bool ImageStateMonitor::comparison_is_satisfied(const Decimal &current_game_value,
const Comparison &comparison,
const Decimal &comparison_value) const
{
bool comparison_result = false;
switch (dcs_id_compare_condition_) {
switch (comparison) {
case Comparison::EQUAL_TO:
comparison_result = (current_game_value == dcs_id_comparison_value_);
comparison_result = (current_game_value == comparison_value);
break;
case Comparison::LESS_THAN:
comparison_result = (current_game_value < dcs_id_comparison_value_);
comparison_result = (current_game_value < comparison_value);
break;
case Comparison::GREATER_THAN:
comparison_result = (current_game_value > dcs_id_comparison_value_);
comparison_result = (current_game_value > comparison_value);
break;
}
return comparison_result;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,18 +31,24 @@ class ImageStateMonitor
private:
enum class Comparison { GREATER_THAN, EQUAL_TO, LESS_THAN };

using StateMonitorSettings = struct {
SimulatorAddress address;
Comparison comparison;
Decimal comparison_value;
};

/**
* @brief Checks if current game value satisfies the comparison criteria configured in settings.
*
* @param current_game_value
* @brief Checks if current game value satisfies the comparison criteria for state.
*/
bool comparison_is_satisfied(Decimal current_game_value) const;
bool comparison_is_satisfied(const Decimal &current_game_value,
const Comparison &comparison,
const Decimal &comparison_value) const;

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

// Stored settings extracted from user-filled fields.
SimulatorAddress dcs_id_compare_monitor_{0}; // Simulator address to monitor for state change.
std::vector<StateMonitorSettings> settings_per_state_;
Comparison dcs_id_compare_condition_ = Comparison::GREATER_THAN; // Comparison to use for DCS ID compare monitor.
Decimal dcs_id_comparison_value_; // Value to compare DCS ID compare monitor value to.
};
Original file line number Diff line number Diff line change
Expand Up @@ -6,43 +6,34 @@

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

void TitleMonitor::update_settings(const json &settings)
void TitleMonitor::update_settings(const json &title_monitor_settings)
{
const std::string dcs_id_string_monitor_raw = EPLJSONUtils::GetStringByName(settings, "dcs_id_string_monitor");
// Set boolean from checkbox using default false value if it doesn't exist in "settings".
const std::string string_monitor_vertical_spacing_raw =
EPLJSONUtils::GetStringByName(settings, "string_monitor_vertical_spacing");
string_monitor_passthrough_ = EPLJSONUtils::GetBoolByName(settings, "string_monitor_passthrough_check", true);
std::stringstream string_monitor_mapping_raw;
string_monitor_mapping_raw << EPLJSONUtils::GetStringByName(settings, "string_monitor_mapping");

string_monitor_is_set_ = !dcs_id_string_monitor_raw.empty();

string_monitor_is_set_ = title_monitor_settings["is_set"];
if (string_monitor_is_set_) {
if (is_integer(dcs_id_string_monitor_raw)) {
dcs_id_string_monitor_ = SimulatorAddress(std::stoi(dcs_id_string_monitor_raw));

} else {
if (dcs_id_string_monitor_raw == "INTEGER") {
dcs_id_string_monitor_ = SimulatorAddress(settings["string_monitor_address"],
settings["string_monitor_mask"],
settings["string_monitor_shift"]);
} else if (dcs_id_string_monitor_raw == "STRING") {
dcs_id_string_monitor_ =
SimulatorAddress(settings["string_monitor_address"], settings["string_monitor_max_length"]);
}
SimulatorAddress address;
if (title_monitor_settings["monitor_address"]["type"] == "STRING") {
address = SimulatorAddress{title_monitor_settings["monitor_address"][0]["address"],
title_monitor_settings["monitor_address"][0]["max_len"]};
} else if (title_monitor_settings["monitor_address"]["type"] == "INTEGER") {
address = SimulatorAddress{title_monitor_settings["monitor_address"]["address"],
title_monitor_settings["monitor_address"]["mask"],
title_monitor_settings["monitor_address"]["shift"]};
} else if (title_monitor_settings["monitor_address"]["type"] == "ADDRESS_ONLY") {
address = SimulatorAddress{title_monitor_settings["monitor_address"]["address"]};
}

if (is_integer(string_monitor_vertical_spacing_raw)) {
string_monitor_vertical_spacing_ = std::stoi(string_monitor_vertical_spacing_raw);
}
if (!string_monitor_passthrough_) {
modify_string_ = title_monitor_settings["modify_string"];
if (modify_string_) {
string_monitor_mapping_.clear();
std::optional<std::pair<std::string, std::string>> maybe_token_pair;
while (maybe_token_pair = pop_key_and_value(string_monitor_mapping_raw, ',', '=')) {
std::stringstream mapping;
mapping << title_monitor_settings["mapping"];
while (maybe_token_pair = pop_key_and_value(mapping, ',', '=')) {
string_monitor_mapping_[maybe_token_pair.value().first] = maybe_token_pair.value().second;
}
}
vertical_spacing_ =
title_monitor_settings.contains("vertical_spacing") ? title_monitor_settings["vertical_spacing"] : 0;
}
}

Expand All @@ -52,7 +43,7 @@ std::string TitleMonitor::determineTitle(SimulatorInterface *simulator_interface

if (string_monitor_is_set_) {
const std::optional<std::string> maybe_current_game_value =
simulator_interface->get_string_at_addr(dcs_id_string_monitor_);
simulator_interface->get_string_at_addr(monitor_address_);
if (maybe_current_game_value.has_value()) {
updated_title = convertGameStateToTitle(maybe_current_game_value.value());
}
Expand All @@ -64,18 +55,18 @@ std::string TitleMonitor::determineTitle(SimulatorInterface *simulator_interface
std::string TitleMonitor::convertGameStateToTitle(const std::string &current_game_value)
{
std::string title;
if (string_monitor_passthrough_) {
title = current_game_value;
} else {
if (modify_string_) {
title = string_monitor_mapping_[current_game_value];
} else {
title = current_game_value;
}
// Apply vertical spacing.
if (string_monitor_vertical_spacing_ < 0) {
for (int i = 0; i > string_monitor_vertical_spacing_; --i) {
if (vertical_spacing_ < 0) {
for (int i = 0; i > vertical_spacing_; --i) {
title = "\n" + title;
}
} else {
for (int i = 0; i < string_monitor_vertical_spacing_; ++i) {
for (int i = 0; i < vertical_spacing_; ++i) {
title = title + "\n";
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ class TitleMonitor

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

SimulatorAddress dcs_id_string_monitor_{0}; // Simulator address to monitor for context title.
int string_monitor_vertical_spacing_ = 0; // Vertical spacing (number of '\n') to include before or after title.
bool string_monitor_passthrough_ = true; // Flag set by user to passthrough string to title unaltered.
SimulatorAddress monitor_address_; // Simulator address to monitor for context title.
int vertical_spacing_ = 0; // Vertical spacing (number of '\n') to include before or after title.
bool modify_string_ = false; // Flag set if string should be modified before using as title.
std::unordered_map<std::string, std::string>
string_monitor_mapping_; // Map of received values to title text to display on context.
};
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,13 @@ interface ControlOutputString {
description: string,
max_length: number,
suffix: string,
<<<<<<< HEAD:Sources/frontend-react-js/src/api/DcsBios/ControlReferenceInterface.tsx
type: "string"
||||||| constructed merge base:Sources/frontend-react-js/src/components/control-reference/ControlReferenceInterface.tsx
type: string, // Will be "string"
=======
type: "string",
>>>>>>> New version of ButtonSettings and GlobalSettings structures:Sources/frontend-react-js/src/components/control-reference/ControlReferenceInterface.tsx
}

export type {
Expand Down
85 changes: 2 additions & 83 deletions Sources/frontend-react-js/src/api/Streamdeck/StreamdeckApi.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
*/

import { ModuleControlsJson } from "../DcsBios/ControlReferenceInterface";
import StreamdeckButtonSettings from "./StreamdeckButtonSettings";
import StreamdeckGlobalSettings from "./StreamdeckGlobalSettings";

export default interface StreamdeckApi {
commFns: StreamdeckCommFns;
Expand Down Expand Up @@ -38,86 +40,3 @@ export interface StreamdeckCommFns {
// Request reference data for an individual module.
requestModule(filename: string): void,
}

export interface StreamdeckButtonSettings {
// Simulator command settings
send_identifier: string;
send_address: string;
press_value: string;
release_value: string;
disable_release_check: boolean;
// Title Monitor settings
string_monitor_identifier: string;
dcs_id_string_monitor: string;
string_monitor_address: number;
string_monitor_mask: number;
string_monitor_shift: number;
string_monitor_max_length: number;
string_monitor_vertical_spacing: string;
string_monitor_passthrough_check: boolean;
string_monitor_mapping: string;
// State Monitor settings
compare_monitor_identifier: string;
dcs_id_compare_monitor: string;
compare_monitor_address: number;
compare_monitor_mask: number;
compare_monitor_shift: number;
compare_monitor_max_length: number;
dcs_id_compare_condition: "LESS_THAN" | "EQUAL_TO" | "GREATER_THAN";
dcs_id_comparison_value: string;
}

export function defaultButtonSettings(): StreamdeckButtonSettings {
return {
send_identifier: "",
send_address: "",
press_value: "1",
release_value: "0",
disable_release_check: false,
string_monitor_identifier: "",
dcs_id_string_monitor: "",
string_monitor_address: 0,
string_monitor_mask: 0,
string_monitor_shift: 0,
string_monitor_max_length: 0,
string_monitor_vertical_spacing: "0",
string_monitor_passthrough_check: true,
string_monitor_mapping: "",
compare_monitor_identifier: "",
dcs_id_compare_monitor: "",
compare_monitor_address: 0,
compare_monitor_mask: 0,
compare_monitor_shift: 0,
compare_monitor_max_length: 0,
dcs_id_compare_condition: "GREATER_THAN",
dcs_id_comparison_value: "0"
};
}

export interface StreamdeckGlobalSettings {
// General UI settings
autoOpenConfigureWindow: boolean;
// Connection settings to Simulator export.
ip_address: string,
listener_port: string,
send_port: string,
// Control reference query settings.
last_search_query: string,
last_selected_module: string,
dcs_install_path: string,
dcs_bios_install_path: string,
}

export function defaultGlobalSettings(): StreamdeckGlobalSettings {
return {
autoOpenConfigureWindow: false,
ip_address: "",
listener_port: "",
send_port: "",
last_search_query: "",
last_selected_module: "",
dcs_install_path: "",
dcs_bios_install_path: "C:\\Users\\username\\Saved Games\\DCS.openbeta\\Scripts\\DCS-BIOS"
};
}

Loading