diff --git a/extension/doc_classes/MenuSingleton.xml b/extension/doc_classes/MenuSingleton.xml
index 99421d83..f78edf06 100644
--- a/extension/doc_classes/MenuSingleton.xml
+++ b/extension/doc_classes/MenuSingleton.xml
@@ -255,6 +255,11 @@
+
+
+
+
+
diff --git a/extension/src/openvic-extension/classes/GFXMaskedFlagTexture.cpp b/extension/src/openvic-extension/classes/GFXMaskedFlagTexture.cpp
index f01e1307..db10d46b 100644
--- a/extension/src/openvic-extension/classes/GFXMaskedFlagTexture.cpp
+++ b/extension/src/openvic-extension/classes/GFXMaskedFlagTexture.cpp
@@ -215,10 +215,19 @@ Error GFXMaskedFlagTexture::set_flag_country_name_and_type(
Error GFXMaskedFlagTexture::set_flag_country(CountryInstance* new_flag_country) {
if (new_flag_country == nullptr) {
+ flag_government_type_connection = {};
return set_flag_country_and_type(nullptr, {});
}
- GovernmentType const* government_type = new_flag_country->flag_government_type.get_untracked();
+ GovernmentType const* const government_type = new_flag_country->flag_government_type.get(
+ [this,new_flag_country](signal<>& changed) mutable -> void {
+ flag_government_type_connection = changed.connect_scoped(
+ [this,new_flag_country]() -> void {
+ set_flag_country(new_flag_country);
+ }
+ );
+ }
+ );
const StringName new_flag_type = government_type != nullptr
? StringName { Utilities::std_to_godot_string(government_type->get_flag_type()) }
@@ -232,13 +241,13 @@ Error GFXMaskedFlagTexture::set_flag_country_name(String const& new_flag_country
return set_flag_country(nullptr);
}
- GameSingleton* game_singleton = GameSingleton::get_singleton();
+ GameSingleton* const game_singleton = GameSingleton::get_singleton();
ERR_FAIL_NULL_V(game_singleton, FAILED);
- InstanceManager* instance_manager = game_singleton->get_instance_manager();
+ InstanceManager* const instance_manager = game_singleton->get_instance_manager();
ERR_FAIL_NULL_V(instance_manager, FAILED);
- CountryInstance* new_flag_country = instance_manager->get_country_instance_manager()
+ CountryInstance* const new_flag_country = instance_manager->get_country_instance_manager()
.get_country_instance_by_identifier(
Utilities::godot_to_std_string(new_flag_country_name)
);
diff --git a/extension/src/openvic-extension/classes/GFXMaskedFlagTexture.hpp b/extension/src/openvic-extension/classes/GFXMaskedFlagTexture.hpp
index 97489316..002f79b4 100644
--- a/extension/src/openvic-extension/classes/GFXMaskedFlagTexture.hpp
+++ b/extension/src/openvic-extension/classes/GFXMaskedFlagTexture.hpp
@@ -1,6 +1,7 @@
#pragma once
#include
+#include
#include "openvic-extension/classes/GFXButtonStateTexture.hpp"
@@ -9,8 +10,11 @@ namespace OpenVic {
struct CountryInstance;
class GFXMaskedFlagTexture : public GFXButtonStateHavingTexture {
+ private:
GDCLASS(GFXMaskedFlagTexture, GFXButtonStateHavingTexture)
+ scoped_connection flag_government_type_connection;
+
GFX::MaskedFlag const* PROPERTY(gfx_masked_flag, nullptr);
CountryDefinition const* PROPERTY(flag_country, nullptr);
godot::StringName PROPERTY(flag_type);
diff --git a/extension/src/openvic-extension/classes/GUILabel.cpp b/extension/src/openvic-extension/classes/GUILabel.cpp
index f1d33545..5bfdf971 100644
--- a/extension/src/openvic-extension/classes/GUILabel.cpp
+++ b/extension/src/openvic-extension/classes/GUILabel.cpp
@@ -18,6 +18,10 @@ using namespace OpenVic;
using namespace godot;
using namespace OpenVic::Utilities::literals;
+GUILabel::~GUILabel() {
+ disconnect_all();
+}
+
GUILabel::string_segment_t::string_segment_t(String&& new_text, Color const& new_colour, real_t new_width)
: text { std::move(new_text) }, colour { new_colour }, width { new_width } {}
@@ -594,7 +598,7 @@ std::pair GUILabel::generate_display_te
std::vector GUILabel::generate_lines_and_segments(
String const& display_text, colour_instructions_t const& colour_instructions
-) const {
+) {
static constexpr char RESET_COLOUR_CODE = '!';
std::vector unwrapped_lines;
@@ -641,7 +645,7 @@ std::vector GUILabel::generate_lines_and_segments(
void GUILabel::separate_lines(
String const& string, Color const& colour, std::vector& unwrapped_lines
-) const {
+) {
static const String NEWLINE_MARKER = "\n";
int64_t start_pos = 0;
@@ -664,7 +668,7 @@ void GUILabel::separate_lines(
void GUILabel::separate_currency_segments(
String const& string, Color const& colour, line_t& line
-) const {
+) {
int64_t start_pos = 0;
int64_t marker_pos;
@@ -694,28 +698,30 @@ GUILabel::flag_segment_t GUILabel::make_flag_segment(String const& identifier) {
InstanceManager* instance_manager = game_singleton.get_instance_manager();
- if (instance_manager != nullptr) {
- CountryInstance* country_instance =
- instance_manager->get_country_instance_manager().get_country_instance_by_identifier(
+ if (instance_manager == nullptr) {
+ CountryDefinition const* country_definition =
+ game_singleton.get_definition_manager().get_country_definition_manager().get_country_definition_by_identifier(
Utilities::godot_to_std_string(identifier)
);
- if (country_instance != nullptr) {
- country_index = country_instance->get_country_definition().get_index();
-
- GovernmentType const* government_type = country_instance->flag_government_type.get_untracked();
- if (government_type != nullptr) {
- flag_type = Utilities::std_to_godot_string(government_type->get_flag_type());
- }
+ if (country_definition != nullptr) {
+ country_index = country_definition->get_index();
}
} else {
- CountryDefinition const* country_definition =
- game_singleton.get_definition_manager().get_country_definition_manager().get_country_definition_by_identifier(
+ CountryInstance* const country_instance = instance_manager->get_country_instance_manager()
+ .get_country_instance_by_identifier(
Utilities::godot_to_std_string(identifier)
);
- if (country_definition != nullptr) {
- country_index = country_definition->get_index();
+ if (country_instance != nullptr) {
+ country_index = country_instance->get_country_definition().get_index();
+ DerivedState& flag_government_type_state = country_instance->flag_government_type;
+ GovernmentType const* const flag_government_type = flag_government_type_state.get([this](signal<>& changed) mutable -> void {
+ changed.connect(&GUILabel::on_flag_government_type_changed, this);
+ });
+ if (flag_government_type != nullptr) {
+ flag_type = Utilities::std_to_godot_string(flag_government_type->get_flag_type());
+ }
}
}
@@ -740,9 +746,14 @@ GUILabel::flag_segment_t GUILabel::make_flag_segment(String const& identifier) {
return flag_segment;
}
+void GUILabel::on_flag_government_type_changed() {
+ disconnect_all();
+ _queue_line_update();
+}
+
void GUILabel::separate_flag_segments(
String const& string, Color const& colour, line_t& line
-) const {
+) {
const auto push_string_segment = [this, &string, &colour, &line](int64_t start, int64_t end) -> void {
String substring = string.substr(start, end - start);
const real_t width = get_string_width(substring);
diff --git a/extension/src/openvic-extension/classes/GUILabel.hpp b/extension/src/openvic-extension/classes/GUILabel.hpp
index 0cf62629..0389e740 100644
--- a/extension/src/openvic-extension/classes/GUILabel.hpp
+++ b/extension/src/openvic-extension/classes/GUILabel.hpp
@@ -7,6 +7,7 @@
#include
#include
+#include
#include "openvic-extension/classes/GFXSpriteTexture.hpp"
#include "openvic-extension/classes/GUIHasTooltip.hpp"
@@ -17,7 +18,9 @@ namespace godot {
}
namespace OpenVic {
- class GUILabel : public godot::Control {
+ struct GovernmentType;
+
+ class GUILabel : public godot::Control, public observer {
GDCLASS(GUILabel, godot::Control)
GUI_TOOLTIP_DEFINITIONS
@@ -81,6 +84,7 @@ namespace OpenVic {
);
GUILabel();
+ ~GUILabel() override;
/* Reset gui_text to nullptr and reset current text. */
void clear();
@@ -124,6 +128,7 @@ namespace OpenVic {
void _queue_line_update();
void _update_lines();
+ void on_flag_government_type_changed();
godot::String generate_substituted_text(godot::String const& base_text) const;
std::pair generate_display_text_and_colour_instructions(
@@ -131,17 +136,17 @@ namespace OpenVic {
) const;
std::vector generate_lines_and_segments(
godot::String const& display_text, colour_instructions_t const& colour_instructions
- ) const;
+ );
void separate_lines(
godot::String const& string, godot::Color const& colour, std::vector& lines
- ) const;
+ );
void separate_currency_segments(
godot::String const& string, godot::Color const& colour, line_t& line
- ) const;
- static flag_segment_t make_flag_segment(godot::String const& identifier);
+ );
+ flag_segment_t make_flag_segment(godot::String const& identifier);
void separate_flag_segments(
godot::String const& string, godot::Color const& colour, line_t& line
- ) const;
+ );
std::vector wrap_lines(std::vector& unwrapped_lines) const;
void adjust_to_content_size();
};
diff --git a/extension/src/openvic-extension/classes/GUIScrollbar.cpp b/extension/src/openvic-extension/classes/GUIScrollbar.cpp
index 52d593d6..8a2747ec 100644
--- a/extension/src/openvic-extension/classes/GUIScrollbar.cpp
+++ b/extension/src/openvic-extension/classes/GUIScrollbar.cpp
@@ -299,7 +299,7 @@ void GUIScrollbar::emit_value_changed() {
return;
}
emit_signal(signal_value_changed(), value);
- value_changed();
+ scaled_value.set(_get_scaled_value(value));
}
void GUIScrollbar::reset() {
@@ -522,12 +522,8 @@ void GUIScrollbar::set_value_as_ratio(float new_ratio) {
set_value(step_count * new_ratio);
}
-fixed_point_t GUIScrollbar::get_value_scaled_fp() const {
- return _get_scaled_value(value);
-}
-
float GUIScrollbar::get_value_scaled() const {
- return get_value_scaled_fp().to_float();
+ return _get_scaled_value(value).to_float();
}
void GUIScrollbar::set_step_count(const int32_t new_step_count) {
@@ -592,12 +588,25 @@ void GUIScrollbar::set_range_limits_fp(
: std::optional{}
);
}
-void GUIScrollbar::set_range_limits_and_value_from_slider_value(ReadOnlyClampedValue& slider_value) {
+void GUIScrollbar::link_to(ReadOnlyClampedValue& clamped_value) {
+ clamped_value_connection.disconnect();
set_range_limits_fp(
- slider_value.get_min(),
- slider_value.get_max()
+ clamped_value.get_min(),
+ clamped_value.get_max()
);
- set_scaled_value(slider_value.get_value_untracked());
+ set_scaled_value(clamped_value.get_value(
+ [this](signal& dependency_changed) mutable -> void {
+ clamped_value_connection = std::move(dependency_changed.connect(
+ &GUIScrollbar::set_scaled_value,
+ this
+ ));
+ }
+ ));
+}
+
+void GUIScrollbar::unlink() {
+ clamped_value_connection.disconnect();
+ clamped_value_connection={};
}
void GUIScrollbar::set_length_override(real_t new_length_override) {
diff --git a/extension/src/openvic-extension/classes/GUIScrollbar.hpp b/extension/src/openvic-extension/classes/GUIScrollbar.hpp
index f20a15f6..34e17d0f 100644
--- a/extension/src/openvic-extension/classes/GUIScrollbar.hpp
+++ b/extension/src/openvic-extension/classes/GUIScrollbar.hpp
@@ -6,14 +6,14 @@
#include
#include
-#include
#include
+#include
#include "openvic-extension/classes/GFXSpriteTexture.hpp"
#include "openvic-extension/classes/GUIHasTooltip.hpp"
namespace OpenVic {
- struct SliderValue;
+ struct ReadOnlyClampedValue;
class GUIScrollbar : public godot::Control {
GDCLASS(GUIScrollbar, godot::Control)
@@ -47,6 +47,9 @@ namespace OpenVic {
int32_t scale_denominator = 1;
int32_t PROPERTY(step_count, 1);
int32_t PROPERTY(value, 0);
+ STATE_PROPERTY(fixed_point_t, scaled_value);
+
+ scoped_connection clamped_value_connection;
bool PROPERTY_CUSTOM_PREFIX(range_limited, is, false);
std::optional upper_range_limit;
@@ -91,7 +94,6 @@ namespace OpenVic {
public:
static godot::StringName const& signal_value_changed();
- mutable signal_property value_changed;
GUIScrollbar();
@@ -114,8 +116,6 @@ namespace OpenVic {
float get_value_as_ratio() const;
void set_value_as_ratio(float new_ratio);
-
- fixed_point_t get_value_scaled_fp() const;
float get_value_scaled() const;
void set_step_count(const int32_t new_step_count);
@@ -132,9 +132,10 @@ namespace OpenVic {
const std::optional new_lower_range_limit,
const std::optional new_upper_range_limit
);
- void set_range_limits_and_value_from_slider_value(
+ void link_to(
ReadOnlyClampedValue& slider_value
);
+ void unlink();
/* Override the main dimension of gui_scollbar's size with the specified length. */
void set_length_override(real_t new_length_override);
diff --git a/extension/src/openvic-extension/components/ReactiveComponent.cpp b/extension/src/openvic-extension/components/ReactiveComponent.cpp
new file mode 100644
index 00000000..5165f83d
--- /dev/null
+++ b/extension/src/openvic-extension/components/ReactiveComponent.cpp
@@ -0,0 +1,48 @@
+#include "ReactiveComponent.hpp"
+
+using namespace OpenVic;
+
+void ReactiveComponent::add_connection(connection conn) {
+ const std::lock_guard lock_guard { connections_lock };
+ connections.emplace_back(std::move(conn));
+}
+
+void ReactiveComponent::disconnect_all() {
+ const std::lock_guard lock_guard { connections_lock };
+ connections.clear();
+}
+
+void ReactiveComponent::update_if_dirty() {
+ if (!is_initialised) {
+ initialise();
+ is_initialised = true;
+ }
+
+ if (!is_dirty) {
+ return;
+ }
+
+ const std::lock_guard lock_guard { is_dirty_lock };
+ if (!is_dirty) {
+ return;
+ }
+
+ update();
+
+ is_dirty = false;
+}
+
+void ReactiveComponent::mark_dirty() {
+ if (is_dirty) {
+ return;
+ }
+
+ const std::lock_guard lock_guard { is_dirty_lock };
+ if (is_dirty) {
+ return;
+ }
+
+ disconnect_all();
+ is_dirty = true;
+ marked_dirty();
+}
\ No newline at end of file
diff --git a/extension/src/openvic-extension/components/ReactiveComponent.hpp b/extension/src/openvic-extension/components/ReactiveComponent.hpp
new file mode 100644
index 00000000..d513ccee
--- /dev/null
+++ b/extension/src/openvic-extension/components/ReactiveComponent.hpp
@@ -0,0 +1,64 @@
+#pragma once
+
+#include
+
+#include
+
+namespace OpenVic {
+ struct ReactiveComponent {
+ private:
+ memory::vector connections;
+ std::mutex connections_lock;
+ bool is_dirty = true;
+ bool is_initialised = false;
+ std::mutex is_dirty_lock;
+ protected:
+ ReactiveComponent() {}
+ virtual ~ReactiveComponent() {
+ disconnect_all();
+ }
+
+ constexpr bool has_no_connections() const {
+ return connections.empty();
+ }
+
+ void add_connection(connection conn);
+
+ template
+ auto connect_to_mark_dirty() {
+ return [this](signal& dependency_changed) mutable -> void {
+ connect_to_mark_dirty(dependency_changed);
+ };
+ }
+
+ template
+ auto connect_to_mark_dirty(signal& dependency_changed) {
+ add_connection(dependency_changed.connect([this](Args...) mutable -> void { mark_dirty(); }));
+ }
+
+ auto connect_property_to_mark_dirty() {
+ return [this](signal_property& dependency_changed) mutable -> void {
+ add_connection(dependency_changed.connect(&ReactiveComponent::mark_dirty, this));
+ };
+ }
+
+ template
+ auto connect_to_mark_dirty(signal_property& dependency_changed) {
+ add_connection(dependency_changed.connect([this](Args...) mutable -> void { mark_dirty(); }));
+ }
+
+ void disconnect_all();
+ virtual void initialise() {}
+ virtual void update() = 0;
+ public:
+ signal_property marked_dirty;
+
+ ReactiveComponent(ReactiveComponent&&) = delete;
+ ReactiveComponent(ReactiveComponent const&) = delete;
+ ReactiveComponent& operator=(ReactiveComponent&&) = delete;
+ ReactiveComponent& operator=(ReactiveComponent const&) = delete;
+
+ void update_if_dirty();
+ void mark_dirty();
+ };
+}
\ No newline at end of file
diff --git a/extension/src/openvic-extension/components/budget/AdministrationBudget.cpp b/extension/src/openvic-extension/components/budget/AdministrationBudget.cpp
index 52e0b077..9036667a 100644
--- a/extension/src/openvic-extension/components/budget/AdministrationBudget.cpp
+++ b/extension/src/openvic-extension/components/budget/AdministrationBudget.cpp
@@ -3,10 +3,12 @@
#include
#include
#include
+#include
#include "openvic-extension/classes/GUILabel.hpp"
#include "openvic-extension/classes/GUINode.hpp"
#include "openvic-extension/classes/GUIScrollbar.hpp"
+#include "openvic-extension/singletons/GameSingleton.hpp"
#include "openvic-extension/singletons/PlayerSingleton.hpp"
#include "openvic-extension/utility/Utilities.hpp"
#include "openvic-simulation/types/fixed_point/FixedPoint.hpp"
@@ -53,17 +55,14 @@ AdministrationBudget::AdministrationBudget(
administrative_efficiency_tooltip_args[4] = administrative_efficiency_label.tr("ADM_EXPLAIN_DESC");
}
-fixed_point_t AdministrationBudget::get_expenses() const {
- return std::max(fixed_point_t::_0, -get_balance());
-}
-
fixed_point_t AdministrationBudget::calculate_budget_and_update_custom(
CountryInstance& country,
const fixed_point_t scaled_value
) {
static const godot::StringName administrative_efficiency_template = "%s\n%s%s\n--------------\n%s%s%s%s";
-
- const fixed_point_t administrative_efficiency_from_administrators = country.get_administrative_efficiency_from_administrators_untracked();
+ const fixed_point_t administrative_efficiency_from_administrators = country.get_administrative_efficiency_from_administrators(
+ connect_to_mark_dirty()
+ );
administrative_efficiency_label.set_text(
Utilities::format(
"%s%%",
@@ -103,10 +102,10 @@ fixed_point_t AdministrationBudget::calculate_budget_and_update_custom(
"BUDGET_ADMIN_EFFICIENCY_DESC"
).replace(
Utilities::get_percentage_value_placeholder(),
- Utilities::fixed_point_to_string_dp(100 * country.get_administrator_percentage_untracked(), 1)
+ Utilities::fixed_point_to_string_dp(100 * country.get_administrator_percentage(connect_to_mark_dirty()), 1)
).replace(
"MAX",
- Utilities::fixed_point_to_string_dp(100 * country.desired_administrator_percentage.get_untracked(), 1)
+ Utilities::fixed_point_to_string_dp(100 * country.desired_administrator_percentage.get(connect_to_mark_dirty()), 1)
);
administrative_efficiency_tooltip_args[5] = administrative_efficiency_label.tr(
"COMWID_BASE"
@@ -115,6 +114,7 @@ fixed_point_t AdministrationBudget::calculate_budget_and_update_custom(
Utilities::percentage_to_string_dp(country_defines.get_max_bureaucracy_percentage(), 1)
);
+ add_connection(GameSingleton::get_singleton()->gamestate_updated.connect(&BudgetMenu::mark_dirty, this)); //for reforms
godot::String reforms_part = "";
for (auto const& [group, reform] : country.get_reforms()) {
if (!group.get_is_administrative() || reform == nullptr) {
@@ -146,13 +146,13 @@ fixed_point_t AdministrationBudget::calculate_budget_and_update_custom(
administrative_efficiency_template % administrative_efficiency_tooltip_args
);
- return scaled_value * country.get_projected_administration_spending_unscaled_by_slider_untracked();
+ return scaled_value * country.get_projected_administration_spending_unscaled_by_slider(connect_to_mark_dirty());
}
ReadOnlyClampedValue& AdministrationBudget::get_clamped_value(CountryInstance& country) const {
return country.get_administration_spending_slider_value();
}
-void AdministrationBudget::on_slider_value_changed(const fixed_point_t scaled_value) {
+void AdministrationBudget::on_slider_scaled_value_changed(const fixed_point_t scaled_value) {
PlayerSingleton::get_singleton()->set_administration_spending_slider_value(scaled_value);
}
\ No newline at end of file
diff --git a/extension/src/openvic-extension/components/budget/AdministrationBudget.hpp b/extension/src/openvic-extension/components/budget/AdministrationBudget.hpp
index 9f717255..e1d5880b 100644
--- a/extension/src/openvic-extension/components/budget/AdministrationBudget.hpp
+++ b/extension/src/openvic-extension/components/budget/AdministrationBudget.hpp
@@ -18,13 +18,11 @@ namespace OpenVic {
const fixed_point_t scaled_value
) override;
ReadOnlyClampedValue& get_clamped_value(CountryInstance& country) const override;
- void on_slider_value_changed(const fixed_point_t scaled_value) override;
-
+ void on_slider_scaled_value_changed(const fixed_point_t scaled_value) override;
public:
AdministrationBudget(
GUINode const& parent,
CountryDefines const& new_country_defines
);
- fixed_point_t get_expenses() const override;
};
}
\ No newline at end of file
diff --git a/extension/src/openvic-extension/components/budget/ArmyStockpileBudget.cpp b/extension/src/openvic-extension/components/budget/ArmyStockpileBudget.cpp
index 1d75bc29..cd798df4 100644
--- a/extension/src/openvic-extension/components/budget/ArmyStockpileBudget.cpp
+++ b/extension/src/openvic-extension/components/budget/ArmyStockpileBudget.cpp
@@ -22,10 +22,6 @@ ArmyStockpileBudget::ArmyStockpileBudget(GUINode const& parent):
slider.set_block_signals(false);
}
-fixed_point_t ArmyStockpileBudget::get_expenses() const {
- return std::max(fixed_point_t::_0, -get_balance());
-}
-
fixed_point_t ArmyStockpileBudget::calculate_budget_and_update_custom(
CountryInstance& country,
const fixed_point_t scaled_value
@@ -37,6 +33,6 @@ ReadOnlyClampedValue& ArmyStockpileBudget::get_clamped_value(CountryInstance& co
return country.get_army_spending_slider_value();
}
-void ArmyStockpileBudget::on_slider_value_changed(const fixed_point_t scaled_value) {
+void ArmyStockpileBudget::on_slider_scaled_value_changed(const fixed_point_t scaled_value) {
PlayerSingleton::get_singleton()->set_national_stockpile_army_spending_slider_value(scaled_value);
}
\ No newline at end of file
diff --git a/extension/src/openvic-extension/components/budget/ArmyStockpileBudget.hpp b/extension/src/openvic-extension/components/budget/ArmyStockpileBudget.hpp
index 97de4b6b..b5524748 100644
--- a/extension/src/openvic-extension/components/budget/ArmyStockpileBudget.hpp
+++ b/extension/src/openvic-extension/components/budget/ArmyStockpileBudget.hpp
@@ -11,10 +11,8 @@ namespace OpenVic {
const fixed_point_t scaled_value
) override;
ReadOnlyClampedValue& get_clamped_value(CountryInstance& country) const override;
- void on_slider_value_changed(const fixed_point_t scaled_value) override;
-
+ void on_slider_scaled_value_changed(const fixed_point_t scaled_value) override;
public:
ArmyStockpileBudget(GUINode const& parent);
- fixed_point_t get_expenses() const override;
};
}
\ No newline at end of file
diff --git a/extension/src/openvic-extension/components/budget/BudgetMenu.cpp b/extension/src/openvic-extension/components/budget/BudgetMenu.cpp
index 3aea1663..a86fd5ff 100644
--- a/extension/src/openvic-extension/components/budget/BudgetMenu.cpp
+++ b/extension/src/openvic-extension/components/budget/BudgetMenu.cpp
@@ -1,13 +1,15 @@
#include "BudgetMenu.hpp"
-#include
-
#include
#include
+#include
#include "openvic-extension/classes/GUILabel.hpp"
#include "openvic-extension/classes/GUINode.hpp"
+#include "openvic-extension/components/budget/BudgetMenuExpenses.hpp"
+#include "openvic-extension/components/budget/BudgetMenuIncome.hpp"
+#include "openvic-extension/singletons/GameSingleton.hpp"
#include "openvic-extension/singletons/PlayerSingleton.hpp"
#include "openvic-extension/utility/Utilities.hpp"
@@ -19,62 +21,29 @@ BudgetMenu::BudgetMenu(
ModifierEffectCache const& modifier_effect_cache,
CountryDefines const& country_defines
) : cash_stockpile_label{*parent.get_gui_label_from_nodepath("./country_budget/total_funds_val")},
- gold_income_label{*parent.get_gui_label_from_nodepath("./country_budget/gold_inc")},
projected_balance_label{*parent.get_gui_label_from_nodepath("./country_budget/balance")},
- projected_expenses_label{*parent.get_gui_label_from_nodepath("./country_budget/total_exp")},
- projected_income_label{*parent.get_gui_label_from_nodepath("./country_budget/total_inc")},
- administration_budget{parent,country_defines},
diplomatic_budget{parent},
- education_budget{parent},
- military_budget{parent},
- national_stockpile_budget{parent},
- social_budget{parent},
tariff_budget{parent,country_defines},
- projected_income_template{generate_projected_income_template(strata_keys.size())}
- {
- tax_budgets.reserve(strata_keys.size());
- connections.reserve(7 + strata_keys.size());
- connections.push_back(administration_budget.balance_changed.connect(&BudgetMenu::update_projected_expenses_and_balance, this));
- connections.push_back(diplomatic_budget.balance_changed.connect(&BudgetMenu::update_all_projections, this));
- connections.push_back(education_budget.balance_changed.connect(&BudgetMenu::update_projected_expenses_and_balance, this));
- connections.push_back(military_budget.balance_changed.connect(&BudgetMenu::update_projected_expenses_and_balance, this));
- connections.push_back(national_stockpile_budget.balance_changed.connect(&BudgetMenu::update_projected_expenses_and_balance, this));
- connections.push_back(social_budget.balance_changed.connect(&BudgetMenu::update_projected_expenses_and_balance, this));
- connections.push_back(tariff_budget.balance_changed.connect(&BudgetMenu::update_all_projections, this));
- for (Strata const& strata : strata_keys) {
- StrataTaxBudget& strata_tax_budget = tax_budgets.emplace_back(parent, strata, modifier_effect_cache);
- connections.push_back(strata_tax_budget.balance_changed.connect(&BudgetMenu::update_projected_income_and_balance, this));
- }
-
- GUILabel::set_text_and_tooltip(
- parent, "./country_budget/gold_desc",
- "GOLD","precious_metal_desc"
- );
- GUILabel::set_text_and_tooltip(
- parent, "./country_budget/ind_sub_desc",
- "BUDGET_INDUSTRIAL_SUBSIDIES","IND_SUP_DESC"
- );
+ expenses_component{parent, country_defines, diplomatic_budget, tariff_budget},
+ income_component{parent, strata_keys, modifier_effect_cache, diplomatic_budget, tariff_budget}
+{
+ GUILabel::set_text_and_tooltip(
+ parent, "./country_budget/ind_sub_desc",
+ "BUDGET_INDUSTRIAL_SUBSIDIES","IND_SUP_DESC"
+ );
+}
- projected_income_args.resize(5 + strata_keys.size());
- projected_expenses_args.resize(8);
+void BudgetMenu::update() {
+ CountryInstance* const player_country_ptr = PlayerSingleton::get_singleton()->get_player_country(
+ connect_to_mark_dirty()
+ );
+ if (player_country_ptr == nullptr) {
+ return;
}
+ CountryInstance& country = *player_country_ptr;
-void BudgetMenu::update_projected_balance() {
- CountryInstance const* const country_ptr = PlayerSingleton::get_singleton()->get_player_country();
- ERR_FAIL_NULL(country_ptr);
- CountryInstance const& country = *country_ptr;
- fixed_point_t projected_balance = country.get_gold_income_untracked()
- + administration_budget.get_balance()
- + diplomatic_budget.get_balance()
- + education_budget.get_balance()
- + military_budget.get_balance()
- + national_stockpile_budget.get_balance()
- + social_budget.get_balance()
- + tariff_budget.get_balance();
-
- for (StrataTaxBudget const& strata_tax_budget : tax_budgets) {
- projected_balance += strata_tax_budget.get_balance();
- }
+ const fixed_point_t projected_balance = income_component.get_projected_income(connect_property_to_mark_dirty())
+ - expenses_component.get_projected_expenses(connect_property_to_mark_dirty());
projected_balance_label.set_text(
Utilities::format(
@@ -83,169 +52,12 @@ void BudgetMenu::update_projected_balance() {
Utilities::cash_to_string_dp_dynamic(projected_balance)
)
);
-}
-
-void BudgetMenu::update_projected_expenses() {
- static const godot::StringName projected_expenses_template = "%s\n--------------\n%s\n%s\n%s\n%s\n%s\n%s%s";
- const fixed_point_t projected_expenses = administration_budget.get_expenses()
- + diplomatic_budget.get_expenses()
- + education_budget.get_expenses()
- + military_budget.get_expenses()
- + national_stockpile_budget.get_expenses()
- + social_budget.get_expenses()
- + tariff_budget.get_expenses();
- //TODO: + import subsidies?
- //TODO: + factory subsidies
- //TODO: + interest
- const fixed_point_t interest_expenses = 0;
-
- projected_expenses_label.set_text(
- Utilities::cash_to_string_dp_dynamic(projected_expenses)
- );
- projected_expenses_args[0] = projected_expenses_label.tr("BUDGET_TOTAL_EXPENSE").replace(
- Utilities::get_short_value_placeholder(),
- Utilities::float_to_string_dp(projected_expenses, 3)
- );
- projected_expenses_args[1] = education_budget.generate_expenses_summary_text(projected_expenses_label);
- projected_expenses_args[2] = administration_budget.generate_expenses_summary_text(projected_expenses_label);
- projected_expenses_args[3] = social_budget.generate_expenses_summary_text(projected_expenses_label);
- projected_expenses_args[4] = military_budget.generate_expenses_summary_text(projected_expenses_label);
- projected_expenses_args[5] = projected_expenses_label.tr("BUDGET_INTEREST").replace(
- Utilities::get_short_value_placeholder(),
- Utilities::float_to_string_dp(interest_expenses, 1)
- );
- projected_expenses_args[6] = national_stockpile_budget.generate_expenses_summary_text(projected_expenses_label);
- projected_expenses_args[7] = diplomatic_budget.generate_expenses_summary_text(projected_expenses_label);
- projected_expenses_label.set_tooltip_string(
- projected_expenses_template % projected_expenses_args
- );
-}
-
-void BudgetMenu::update_projected_expenses_and_balance() {
- update_projected_expenses();
- update_projected_balance();
-}
-
-void BudgetMenu::update_projected_income() {
- CountryInstance const* const country_ptr = PlayerSingleton::get_singleton()->get_player_country();
- ERR_FAIL_NULL(country_ptr);
- CountryInstance const& country = *country_ptr;
- size_t i = 1;
-
- fixed_point_t projected_income_excluding_tariffs = 0;
- for (StrataTaxBudget const& strata_tax_budget : tax_budgets) {
- const fixed_point_t strata_tax = strata_tax_budget.get_income();
- projected_income_excluding_tariffs += strata_tax;
- projected_income_args[i++] = strata_tax_budget.generate_income_summary_text(projected_income_label);
- }
-
- projected_income_args[i++] = tariff_budget.generate_income_summary_text(projected_income_label);
- const fixed_point_t stockpile_income = 0; //TODO stockpile sales
- projected_income_excluding_tariffs += stockpile_income;
- projected_income_args[i++] = projected_income_label.tr("BUDGET_EXPORTS").replace(
- Utilities::get_short_value_placeholder(),
- Utilities::float_to_string_dp(stockpile_income, 1)
- );
-
- const fixed_point_t gold_income = country.get_gold_income_untracked();
- projected_income_excluding_tariffs += gold_income;
- projected_income_args[i++] = projected_income_label.tr("BUDGET_GOLD").replace(
- Utilities::get_short_value_placeholder(),
- Utilities::float_to_string_dp(gold_income, 1)
- );
- projected_income_args[i++] = diplomatic_budget.generate_income_summary_text(projected_income_label);
-
- const fixed_point_t projected_income = projected_income_excluding_tariffs + tariff_budget.get_income();
- projected_income_args[0] = projected_income_label.tr("BUDGET_TOTAL_INCOME").replace(
- Utilities::get_short_value_placeholder(),
- Utilities::float_to_string_dp(projected_income, 3)
- );
- projected_income_label.set_text(
- Utilities::cash_to_string_dp_dynamic(projected_income_excluding_tariffs)
- );
- projected_income_label.set_tooltip_string(
- projected_income_template % projected_income_args
- );
-
- //TODO stockpile sold to construction projects
-}
-
-void BudgetMenu::update_projected_income_and_balance() {
- update_projected_income();
- update_projected_balance();
-}
-
-void BudgetMenu::update_all_projections() {
- update_projected_balance();
- update_projected_expenses();
- update_projected_income();
-}
-
-#define DO_FOR_ALL_COMPONENTS(F) \
- administration_budget.F; \
- diplomatic_budget.F; \
- education_budget.F; \
- military_budget.F; \
- national_stockpile_budget.F; \
- social_budget.F; \
- tariff_budget.F; \
- for (StrataTaxBudget& strata_tax_budget : tax_budgets) { \
- strata_tax_budget.F; \
- }
-
-void BudgetMenu::update() {
- CountryInstance* const country_ptr = PlayerSingleton::get_singleton()->get_player_country();
- ERR_FAIL_NULL(country_ptr);
- CountryInstance& country = *country_ptr;
-
- //this will trigger a lot of signals we should ignore
- for (connection& c : connections) {
- c.block();
- };
- DO_FOR_ALL_COMPONENTS(full_update(country))
- for (connection& c : connections) {
- c.unblock();
- };
- update_all_projections();
-
- const fixed_point_t gold_income = country.get_gold_income_untracked();
- gold_income_label.set_text(
- Utilities::format_with_currency(
- Utilities::float_to_string_dp(gold_income, 1)
- )
- );
- gold_income_label.set_tooltip_string(
- gold_income_label.tr("BUDGET_GOLD_INCOME_DESC")
- //TODO add separator & list all province names + income if gold_income > 0
- );
+ add_connection(GameSingleton::get_singleton()->gamestate_updated.connect(&BudgetMenu::mark_dirty, this)); //for cash stockpile
const fixed_point_t cash_stockpile = country.get_cash_stockpile();
cash_stockpile_label.set_text(
Utilities::format_with_currency(
Utilities::float_to_string_suffixed(cash_stockpile)
)
);
-}
-
-godot::StringName BudgetMenu::generate_projected_income_template(const size_t tax_budgets_size) {
- static const std::string_view projected_income_template_start = "%s\n--------------";
- static const std::string_view projected_income_template_dynamic_part = "\n%s";
-
- memory::string projected_income_template;
- projected_income_template.reserve(
- projected_income_template_start.size()
- + projected_income_template_dynamic_part.size() * (tax_budgets_size + 3)
- );
-
- projected_income_template.append(projected_income_template_start);
- for (size_t i = 0; i < tax_budgets_size; ++i) {
- projected_income_template.append(projected_income_template_dynamic_part);
- }
- projected_income_template += "\n%s\n%s\n%s%s";
- return godot::StringName(
- projected_income_template.data(),
- false
- );
-}
-
-#undef DO_FOR_ALL_COMPONENTS
\ No newline at end of file
+}
\ No newline at end of file
diff --git a/extension/src/openvic-extension/components/budget/BudgetMenu.hpp b/extension/src/openvic-extension/components/budget/BudgetMenu.hpp
index d05bf938..11d09970 100644
--- a/extension/src/openvic-extension/components/budget/BudgetMenu.hpp
+++ b/extension/src/openvic-extension/components/budget/BudgetMenu.hpp
@@ -5,48 +5,31 @@
#include
#include
+#include "openvic-extension/components/budget/BudgetMenuExpenses.hpp"
+#include "openvic-extension/components/budget/BudgetMenuIncome.hpp"
#include "openvic-extension/components/budget/AdministrationBudget.hpp"
#include "openvic-extension/components/budget/DiplomaticBudget.hpp"
-#include "openvic-extension/components/budget/EducationBudget.hpp"
-#include "openvic-extension/components/budget/MilitaryBudget.hpp"
#include "openvic-extension/components/budget/NationalStockpileBudget.hpp"
-#include "openvic-extension/components/budget/SocialBudget.hpp"
#include "openvic-extension/components/budget/StrataTaxBudget.hpp"
#include "openvic-extension/components/budget/TariffBudget.hpp"
+#include "openvic-extension/components/ReactiveComponent.hpp"
namespace OpenVic {
struct CountryInstance;
struct GUINode;
struct GUILabel;
- struct BudgetMenu {
+ struct BudgetMenu : public ReactiveComponent {
private:
- static godot::StringName generate_projected_income_template(const size_t tax_budgets_size);
-
- const godot::StringName projected_income_template;
- godot::Array projected_income_args;
- godot::Array projected_expenses_args;
- memory::vector connections;
GUILabel& cash_stockpile_label;
- GUILabel& gold_income_label;
GUILabel& projected_balance_label;
- GUILabel& projected_expenses_label;
- GUILabel& projected_income_label;
- AdministrationBudget administration_budget;
DiplomaticBudget diplomatic_budget;
- EducationBudget education_budget;
- MilitaryBudget military_budget;
- NationalStockpileBudget national_stockpile_budget;
- SocialBudget social_budget;
TariffBudget tariff_budget;
- memory::vector tax_budgets;
- void update_projected_balance();
- void update_projected_expenses();
- void update_projected_expenses_and_balance();
- void update_projected_income();
- void update_projected_income_and_balance();
- void update_all_projections();
+ BudgetMenuExpenses expenses_component;
+ BudgetMenuIncome income_component;
+
+ void update() override;
public:
BudgetMenu(
GUINode const& parent,
@@ -54,6 +37,5 @@ namespace OpenVic {
ModifierEffectCache const& modifier_effect_cache,
CountryDefines const& country_defines
);
- void update();
};
}
\ No newline at end of file
diff --git a/extension/src/openvic-extension/components/budget/BudgetMenuExpenses.cpp b/extension/src/openvic-extension/components/budget/BudgetMenuExpenses.cpp
new file mode 100644
index 00000000..af717b54
--- /dev/null
+++ b/extension/src/openvic-extension/components/budget/BudgetMenuExpenses.cpp
@@ -0,0 +1,100 @@
+#include "BudgetMenuExpenses.hpp"
+
+#include
+
+#include "openvic-extension/classes/GUILabel.hpp"
+#include "openvic-extension/classes/GUINode.hpp"
+#include "openvic-extension/components/budget/DiplomaticBudget.hpp"
+#include "openvic-extension/components/budget/TariffBudget.hpp"
+#include "openvic-extension/utility/Utilities.hpp"
+
+using namespace OpenVic;
+
+BudgetMenuExpenses::BudgetMenuExpenses(
+ GUINode const& parent,
+ CountryDefines const& country_defines,
+ DiplomaticBudget& new_diplomatic_budget,
+ TariffBudget& new_tariff_budget
+) : projected_expenses_label{*parent.get_gui_label_from_nodepath("./country_budget/total_exp")},
+ administration_budget{parent,country_defines},
+ diplomatic_budget{new_diplomatic_budget},
+ education_budget{parent},
+ military_budget{parent},
+ national_stockpile_budget{parent},
+ social_budget{parent},
+ tariff_budget{new_tariff_budget}
+ {
+ GUILabel::set_text_and_tooltip(
+ parent, "./country_budget/ind_sub_desc",
+ "BUDGET_INDUSTRIAL_SUBSIDIES","IND_SUP_DESC"
+ );
+ projected_expenses_args.resize(8);
+ }
+
+void BudgetMenuExpenses::update() {
+ static const godot::StringName projected_expenses_template = "%s\n--------------\n%s\n%s\n%s\n%s\n%s\n%s%s";
+
+ const fixed_point_t administration_expenses = administration_budget.get_balance(connect_property_to_mark_dirty());
+ const fixed_point_t diplomatic_expenses = diplomatic_budget.get_balance(connect_property_to_mark_dirty());
+ const fixed_point_t education_expenses = education_budget.get_balance(connect_property_to_mark_dirty());
+ const fixed_point_t military_expenses = military_budget.get_balance(connect_property_to_mark_dirty());
+ const fixed_point_t national_stockpile_expenses= national_stockpile_budget.get_balance(connect_property_to_mark_dirty());
+ const fixed_point_t social_expenses = social_budget.get_balance(connect_property_to_mark_dirty());
+ const fixed_point_t tariff_expenses = -std::min(
+ tariff_budget.get_balance(connect_property_to_mark_dirty()),
+ fixed_point_t::_0
+ );
+ const fixed_point_t projected_expenses_total = administration_expenses
+ + diplomatic_expenses
+ + education_expenses
+ + military_expenses
+ + national_stockpile_expenses
+ + social_expenses
+ + tariff_expenses;
+ //TODO: + import subsidies?
+ //TODO: + factory subsidies
+ //TODO: + interest
+ const fixed_point_t interest_expenses = 0;
+
+ projected_expenses_label.set_text(
+ Utilities::cash_to_string_dp_dynamic(projected_expenses_total)
+ );
+
+ projected_expenses_args[0] = projected_expenses_label.tr("BUDGET_TOTAL_EXPENSE").replace(
+ Utilities::get_short_value_placeholder(),
+ Utilities::float_to_string_dp(projected_expenses_total, 3)
+ );
+ projected_expenses_args[1] = education_budget.generate_expenses_summary_text(
+ education_expenses,
+ projected_expenses_label
+ );
+ projected_expenses_args[2] = administration_budget.generate_expenses_summary_text(
+ administration_expenses,
+ projected_expenses_label
+ );
+ projected_expenses_args[3] = social_budget.generate_expenses_summary_text(
+ social_expenses,
+ projected_expenses_label
+ );
+ projected_expenses_args[4] = military_budget.generate_expenses_summary_text(
+ military_expenses,
+ projected_expenses_label
+ );
+ projected_expenses_args[5] = projected_expenses_label.tr("BUDGET_INTEREST").replace(
+ Utilities::get_short_value_placeholder(),
+ Utilities::float_to_string_dp(interest_expenses, 1)
+ );
+ projected_expenses_args[6] = national_stockpile_budget.generate_expenses_summary_text(
+ national_stockpile_expenses,
+ projected_expenses_label
+ );
+ projected_expenses_args[7] = diplomatic_budget.generate_expenses_summary_text(
+ diplomatic_expenses,
+ projected_expenses_label
+ );
+ projected_expenses_label.set_tooltip_string(
+ projected_expenses_template % projected_expenses_args
+ );
+
+ _projected_expenses = projected_expenses_total;
+}
\ No newline at end of file
diff --git a/extension/src/openvic-extension/components/budget/BudgetMenuExpenses.hpp b/extension/src/openvic-extension/components/budget/BudgetMenuExpenses.hpp
new file mode 100644
index 00000000..f05c9c5a
--- /dev/null
+++ b/extension/src/openvic-extension/components/budget/BudgetMenuExpenses.hpp
@@ -0,0 +1,53 @@
+#pragma once
+
+#include
+
+#include
+#include
+
+#include "openvic-extension/components/budget/AdministrationBudget.hpp"
+#include "openvic-extension/components/budget/EducationBudget.hpp"
+#include "openvic-extension/components/budget/MilitaryBudget.hpp"
+#include "openvic-extension/components/budget/NationalStockpileBudget.hpp"
+#include "openvic-extension/components/budget/SocialBudget.hpp"
+#include "openvic-extension/components/ReactiveComponent.hpp"
+
+namespace OpenVic {
+ struct CountryInstance;
+ struct DiplomaticBudget;
+ struct GUINode;
+ struct GUILabel;
+ struct TariffBudget;
+
+ struct BudgetMenuExpenses : public ReactiveComponent {
+ private:
+ godot::Array projected_expenses_args;
+ GUILabel& projected_expenses_label;
+ AdministrationBudget administration_budget;
+ DiplomaticBudget& diplomatic_budget;
+ EducationBudget education_budget;
+ MilitaryBudget military_budget;
+ NationalStockpileBudget national_stockpile_budget;
+ SocialBudget social_budget;
+ TariffBudget& tariff_budget;
+
+ fixed_point_t _projected_expenses;
+
+ void update() override;
+ public:
+ BudgetMenuExpenses(
+ GUINode const& parent,
+ CountryDefines const& country_defines,
+ DiplomaticBudget& new_diplomatic_budget,
+ TariffBudget& new_tariff_budget
+ );
+
+ template
+ requires std::invocable&>
+ [[nodiscard]] fixed_point_t get_projected_expenses(ConnectTemplateType&& connect) {
+ connect(marked_dirty);
+ update_if_dirty();
+ return _projected_expenses;
+ }
+ };
+}
\ No newline at end of file
diff --git a/extension/src/openvic-extension/components/budget/BudgetMenuIncome.cpp b/extension/src/openvic-extension/components/budget/BudgetMenuIncome.cpp
new file mode 100644
index 00000000..ad3d75f6
--- /dev/null
+++ b/extension/src/openvic-extension/components/budget/BudgetMenuIncome.cpp
@@ -0,0 +1,142 @@
+#include "BudgetMenuIncome.hpp"
+
+#include
+
+#include
+#include
+#include
+
+#include "openvic-extension/classes/GUILabel.hpp"
+#include "openvic-extension/classes/GUINode.hpp"
+#include "openvic-extension/singletons/PlayerSingleton.hpp"
+#include "openvic-extension/utility/Utilities.hpp"
+
+using namespace OpenVic;
+
+BudgetMenuIncome::BudgetMenuIncome(
+ GUINode const& parent,
+ utility::forwardable_span strata_keys,
+ ModifierEffectCache const& modifier_effect_cache,
+ DiplomaticBudget& new_diplomatic_budget,
+ TariffBudget& new_tariff_budget
+) : gold_income_label{*parent.get_gui_label_from_nodepath("./country_budget/gold_inc")},
+ projected_income_label{*parent.get_gui_label_from_nodepath("./country_budget/total_inc")},
+ diplomatic_budget{new_diplomatic_budget},
+ tariff_budget{new_tariff_budget},
+ projected_income_template{generate_projected_income_template(strata_keys.size())},
+ tax_budgets(strata_keys.size(), [
+ strata_keys,
+ parent_ptr=&parent,
+ modifier_effect_cache_ptr=&modifier_effect_cache
+ ](const size_t i)->auto {
+ return std::make_tuple(parent_ptr, &strata_keys[i], modifier_effect_cache_ptr);
+ })
+ {
+ GUILabel::set_text_and_tooltip(
+ parent, "./country_budget/gold_desc",
+ "GOLD","precious_metal_desc"
+ );
+
+ projected_income_args.resize(5 + strata_keys.size());
+ }
+
+void BudgetMenuIncome::update() {
+ CountryInstance* const player_country_ptr = PlayerSingleton::get_singleton()->get_player_country(
+ connect_to_mark_dirty()
+ );
+ if (player_country_ptr == nullptr) {
+ return;
+ }
+ CountryInstance& country = *player_country_ptr;
+
+ const fixed_point_t gold_income = country.get_gold_income(connect_to_mark_dirty());
+ gold_income_label.set_text(
+ Utilities::format_with_currency(
+ Utilities::float_to_string_dp(gold_income, 1)
+ )
+ );
+ gold_income_label.set_tooltip_string(
+ gold_income_label.tr("BUDGET_GOLD_INCOME_DESC")
+ //TODO add separator & list all province names + income if gold_income > 0
+ );
+
+ size_t i = 1;
+
+ fixed_point_t projected_income_excluding_tariffs = 0;
+ for (StrataTaxBudget& strata_tax_budget : tax_budgets) {
+ const fixed_point_t strata_tax = strata_tax_budget.get_balance(connect_property_to_mark_dirty());
+ projected_income_excluding_tariffs += strata_tax;
+ projected_income_args[i++] = strata_tax_budget.generate_income_summary_text(
+ strata_tax,
+ projected_income_label
+ );
+ }
+
+ const fixed_point_t tariff_income = std::max(
+ fixed_point_t::_0,
+ tariff_budget.get_balance(connect_property_to_mark_dirty())
+ );
+
+ projected_income_args[i++] = tariff_budget.generate_income_summary_text(
+ tariff_income,
+ projected_income_label
+ );
+ const fixed_point_t stockpile_income = 0; //TODO stockpile sales
+ projected_income_excluding_tariffs += stockpile_income;
+ projected_income_args[i++] = projected_income_label.tr("BUDGET_EXPORTS").replace(
+ Utilities::get_short_value_placeholder(),
+ Utilities::float_to_string_dp(stockpile_income, 1)
+ );
+
+ projected_income_excluding_tariffs += gold_income;
+ projected_income_args[i++] = projected_income_label.tr("BUDGET_GOLD").replace(
+ Utilities::get_short_value_placeholder(),
+ Utilities::float_to_string_dp(gold_income, 1)
+ );
+
+ const fixed_point_t diplomatic_income = std::max( //not counted in projected_income
+ fixed_point_t::_0,
+ diplomatic_budget.get_balance(connect_property_to_mark_dirty())
+ );
+ projected_income_args[i++] = diplomatic_budget.generate_income_summary_text(
+ diplomatic_income,
+ projected_income_label
+ );
+
+ const fixed_point_t projected_income_including_tariffs = projected_income_excluding_tariffs + tariff_income;
+ projected_income_args[0] = projected_income_label.tr("BUDGET_TOTAL_INCOME").replace(
+ Utilities::get_short_value_placeholder(),
+ Utilities::float_to_string_dp(projected_income_including_tariffs, 3)
+ );
+ projected_income_label.set_text(
+ Utilities::cash_to_string_dp_dynamic(projected_income_excluding_tariffs)
+ );
+ projected_income_label.set_tooltip_string(
+ projected_income_template % projected_income_args
+ );
+
+ //TODO stockpile sold to construction projects
+
+ _projected_income = projected_income_including_tariffs;
+}
+
+godot::StringName BudgetMenuIncome::generate_projected_income_template(const size_t tax_budgets_size) {
+ static const std::string_view projected_income_template_start = "%s\n--------------";
+ static const std::string_view projected_income_template_dynamic_part = "\n%s";
+
+ memory::string projected_income_template;
+ projected_income_template.reserve(
+ projected_income_template_start.size()
+ + projected_income_template_dynamic_part.size() * (tax_budgets_size + 3)
+ );
+
+ projected_income_template.append(projected_income_template_start);
+ for (size_t i = 0; i < tax_budgets_size; ++i) {
+ projected_income_template.append(projected_income_template_dynamic_part);
+ }
+ projected_income_template += "\n%s\n%s\n%s%s";
+ return godot::StringName(
+ projected_income_template.data(),
+ false
+ );
+}
\ No newline at end of file
diff --git a/extension/src/openvic-extension/components/budget/BudgetMenuIncome.hpp b/extension/src/openvic-extension/components/budget/BudgetMenuIncome.hpp
new file mode 100644
index 00000000..a92998b0
--- /dev/null
+++ b/extension/src/openvic-extension/components/budget/BudgetMenuIncome.hpp
@@ -0,0 +1,52 @@
+#pragma once
+
+#include
+#include
+
+#include
+#include
+#include
+
+#include "openvic-extension/components/budget/StrataTaxBudget.hpp"
+#include "openvic-extension/components/ReactiveComponent.hpp"
+
+namespace OpenVic {
+ struct CountryInstance;
+ struct DiplomaticBudget;
+ struct GUINode;
+ struct GUILabel;
+ struct TariffBudget;
+
+ struct BudgetMenuIncome : public ReactiveComponent {
+ private:
+ static godot::StringName generate_projected_income_template(const size_t tax_budgets_size);
+
+ const godot::StringName projected_income_template;
+ godot::Array projected_income_args;
+ GUILabel& gold_income_label;
+ GUILabel& projected_income_label;
+ DiplomaticBudget& diplomatic_budget;
+ TariffBudget& tariff_budget;
+ memory::FixedVector tax_budgets;
+
+ fixed_point_t _projected_income;
+
+ void update() override;
+ public:
+ BudgetMenuIncome(
+ GUINode const& parent,
+ utility::forwardable_span strata_keys,
+ ModifierEffectCache const& modifier_effect_cache,
+ DiplomaticBudget& new_diplomatic_budget,
+ TariffBudget& new_tariff_budget
+ );
+
+ template
+ requires std::invocable&>
+ [[nodiscard]] fixed_point_t get_projected_income(ConnectTemplateType&& connect) {
+ connect(marked_dirty);
+ update_if_dirty();
+ return _projected_income;
+ }
+ };
+}
\ No newline at end of file
diff --git a/extension/src/openvic-extension/components/budget/ConstructionStockpileBudget.cpp b/extension/src/openvic-extension/components/budget/ConstructionStockpileBudget.cpp
index 6eca2cc2..0453af5d 100644
--- a/extension/src/openvic-extension/components/budget/ConstructionStockpileBudget.cpp
+++ b/extension/src/openvic-extension/components/budget/ConstructionStockpileBudget.cpp
@@ -22,10 +22,6 @@ ConstructionStockpileBudget::ConstructionStockpileBudget(GUINode const& parent):
slider.set_block_signals(false);
}
-fixed_point_t ConstructionStockpileBudget::get_expenses() const {
- return std::max(fixed_point_t::_0, -get_balance());
-}
-
fixed_point_t ConstructionStockpileBudget::calculate_budget_and_update_custom(
CountryInstance& country,
const fixed_point_t scaled_value
@@ -37,6 +33,6 @@ ReadOnlyClampedValue& ConstructionStockpileBudget::get_clamped_value(CountryInst
return country.get_construction_spending_slider_value();
}
-void ConstructionStockpileBudget::on_slider_value_changed(const fixed_point_t scaled_value) {
+void ConstructionStockpileBudget::on_slider_scaled_value_changed(const fixed_point_t scaled_value) {
PlayerSingleton::get_singleton()->set_national_stockpile_construction_spending_slider_value(scaled_value);
}
\ No newline at end of file
diff --git a/extension/src/openvic-extension/components/budget/ConstructionStockpileBudget.hpp b/extension/src/openvic-extension/components/budget/ConstructionStockpileBudget.hpp
index 643e7f5a..38422c2a 100644
--- a/extension/src/openvic-extension/components/budget/ConstructionStockpileBudget.hpp
+++ b/extension/src/openvic-extension/components/budget/ConstructionStockpileBudget.hpp
@@ -11,10 +11,8 @@ namespace OpenVic {
const fixed_point_t scaled_value
) override;
ReadOnlyClampedValue& get_clamped_value(CountryInstance& country) const override;
- void on_slider_value_changed(const fixed_point_t scaled_value) override;
-
+ void on_slider_scaled_value_changed(const fixed_point_t scaled_value) override;
public:
ConstructionStockpileBudget(GUINode const& parent);
- fixed_point_t get_expenses() const override;
};
}
\ No newline at end of file
diff --git a/extension/src/openvic-extension/components/budget/DiplomaticBudget.cpp b/extension/src/openvic-extension/components/budget/DiplomaticBudget.cpp
index 2c27f6ac..f360213c 100644
--- a/extension/src/openvic-extension/components/budget/DiplomaticBudget.cpp
+++ b/extension/src/openvic-extension/components/budget/DiplomaticBudget.cpp
@@ -6,6 +6,7 @@
#include "openvic-extension/classes/GUILabel.hpp"
#include "openvic-extension/classes/GUINode.hpp"
+#include "openvic-extension/singletons/PlayerSingleton.hpp"
#include "openvic-extension/utility/Utilities.hpp"
using namespace OpenVic;
@@ -37,17 +38,26 @@ fixed_point_t DiplomaticBudget::get_expenses() const {
) \
: ""
-void DiplomaticBudget::full_update(CountryInstance& country) {
+void DiplomaticBudget::update() {
+ CountryInstance* const player_country_ptr = PlayerSingleton::get_singleton()->get_player_country(
+ connect_to_mark_dirty()
+ );
+ if (player_country_ptr == nullptr) {
+ return;
+ }
+ CountryInstance& country = *player_country_ptr;
+ const CountryInstance::index_t index = country.get_index();
+
//TODO get from sim once sim has it
- reparations_income = fixed_point_t::_0_50;
- war_subsidies_income = fixed_point_t::_1;
- reparations_expenses = fixed_point_t::_1;
- war_subsidies_expenses = fixed_point_t::_0_50;
+ reparations_income = index+fixed_point_t::_0_50;
+ war_subsidies_income = index+fixed_point_t::_1;
+ reparations_expenses = index+fixed_point_t::_1;
+ war_subsidies_expenses = index+fixed_point_t::_0_50;
const fixed_point_t diplomatic_balance = reparations_income
+ war_subsidies_income
- reparations_expenses
- war_subsidies_expenses;
- set_balance(diplomatic_balance);
+ _balance = diplomatic_balance;
balance_label.set_text(
Utilities::format(
@@ -72,7 +82,10 @@ void DiplomaticBudget::full_update(CountryInstance& country) {
#undef TOOLTIP_TEXT_PART
-godot::String DiplomaticBudget::generate_income_summary_text(godot::Object const& translation_object) const {
+godot::String DiplomaticBudget::generate_income_summary_text(
+ const fixed_point_t income, //ignored as this is special
+ godot::Object const& translation_object
+) const {
//war_subsidies_income are excluded here in Victoria 2
return reparations_income > 0
? "\n"+translation_object.tr(
@@ -84,7 +97,10 @@ godot::String DiplomaticBudget::generate_income_summary_text(godot::Object const
: "";
}
-godot::String DiplomaticBudget::generate_expenses_summary_text(godot::Object const& translation_object) const {
+godot::String DiplomaticBudget::generate_expenses_summary_text(
+ const fixed_point_t expenses, //ignored as this is special
+ godot::Object const& translation_object
+) const {
//war_subsidies_expenses are excluded here in Victoria 2
return reparations_expenses > 0
? "\n"+translation_object.tr(
diff --git a/extension/src/openvic-extension/components/budget/DiplomaticBudget.hpp b/extension/src/openvic-extension/components/budget/DiplomaticBudget.hpp
index bfc2a6b0..bbb5623c 100644
--- a/extension/src/openvic-extension/components/budget/DiplomaticBudget.hpp
+++ b/extension/src/openvic-extension/components/budget/DiplomaticBudget.hpp
@@ -2,16 +2,20 @@
#include
-#include "openvic-extension/components/budget/abstract/BudgetComponent.hpp"
+#include
+#include
+
#include "openvic-extension/components/budget/abstract/BudgetIncomeComponent.hpp"
#include "openvic-extension/components/budget/abstract/BudgetExpenseComponent.hpp"
+#include "openvic-extension/components/ReactiveComponent.hpp"
namespace OpenVic {
+ struct CountryInstance;
struct GUILabel;
struct GUINode;
struct DiplomaticBudget :
- public BudgetComponent,
+ public ReactiveComponent,
public BudgetExpenseComponent,
public BudgetIncomeComponent {
private:
@@ -22,17 +26,33 @@ namespace OpenVic {
fixed_point_t reparations_expenses;
fixed_point_t war_subsidies_income;
fixed_point_t war_subsidies_expenses;
- public:
- fixed_point_t get_income() const override;
- fixed_point_t get_expenses() const override;
+ fixed_point_t _balance;
+ fixed_point_t get_income() const;
+ fixed_point_t get_expenses() const;
+ protected:
+ void update() override;
+ public:
DiplomaticBudget(GUINode const& parent);
- void full_update(CountryInstance& country) override;
- godot::String generate_income_summary_text(godot::Object const& translation_object) const override;
- godot::String generate_expenses_summary_text(godot::Object const& translation_object) const override;
+ godot::String generate_income_summary_text(
+ const fixed_point_t income,
+ godot::Object const& translation_object
+ ) const override;
+ godot::String generate_expenses_summary_text(
+ const fixed_point_t expenses,
+ godot::Object const& translation_object
+ ) const override;
godot::String generate_balance_summary_income_text(godot::Object const& translation_object) const;
godot::String generate_balance_summary_expenses_text(godot::Object const& translation_object) const;
+
+ template
+ requires std::invocable&>
+ [[nodiscard]] fixed_point_t get_balance(ConnectTemplateType&& connect) {
+ connect(marked_dirty);
+ update_if_dirty();
+ return _balance;
+ }
};
}
\ No newline at end of file
diff --git a/extension/src/openvic-extension/components/budget/EducationBudget.cpp b/extension/src/openvic-extension/components/budget/EducationBudget.cpp
index 11159277..e6ccb252 100644
--- a/extension/src/openvic-extension/components/budget/EducationBudget.cpp
+++ b/extension/src/openvic-extension/components/budget/EducationBudget.cpp
@@ -39,21 +39,17 @@ EducationBudget::EducationBudget(GUINode const& parent):
}
}
-fixed_point_t EducationBudget::get_expenses() const {
- return std::max(fixed_point_t::_0, -get_balance());
-}
-
fixed_point_t EducationBudget::calculate_budget_and_update_custom(
CountryInstance& country,
const fixed_point_t scaled_value
) {
- return scaled_value * country.get_projected_education_spending_unscaled_by_slider_untracked();
+ return scaled_value * country.get_projected_education_spending_unscaled_by_slider(connect_to_mark_dirty());
}
ReadOnlyClampedValue& EducationBudget::get_clamped_value(CountryInstance& country) const {
return country.get_education_spending_slider_value();
}
-void EducationBudget::on_slider_value_changed(const fixed_point_t scaled_value) {
+void EducationBudget::on_slider_scaled_value_changed(const fixed_point_t scaled_value) {
PlayerSingleton::get_singleton()->set_education_spending_slider_value(scaled_value);
}
\ No newline at end of file
diff --git a/extension/src/openvic-extension/components/budget/EducationBudget.hpp b/extension/src/openvic-extension/components/budget/EducationBudget.hpp
index fd60c3ef..5f044958 100644
--- a/extension/src/openvic-extension/components/budget/EducationBudget.hpp
+++ b/extension/src/openvic-extension/components/budget/EducationBudget.hpp
@@ -11,10 +11,8 @@ namespace OpenVic {
const fixed_point_t scaled_value
) override;
ReadOnlyClampedValue& get_clamped_value(CountryInstance& country) const override;
- void on_slider_value_changed(const fixed_point_t scaled_value) override;
-
+ void on_slider_scaled_value_changed(const fixed_point_t scaled_value) override;
public:
EducationBudget(GUINode const& parent);
- fixed_point_t get_expenses() const override;
};
}
\ No newline at end of file
diff --git a/extension/src/openvic-extension/components/budget/MilitaryBudget.cpp b/extension/src/openvic-extension/components/budget/MilitaryBudget.cpp
index f76a5266..7183ba71 100644
--- a/extension/src/openvic-extension/components/budget/MilitaryBudget.cpp
+++ b/extension/src/openvic-extension/components/budget/MilitaryBudget.cpp
@@ -5,6 +5,7 @@
#include "openvic-extension/classes/GUILabel.hpp"
#include "openvic-extension/classes/GUIScrollbar.hpp"
#include "openvic-extension/singletons/PlayerSingleton.hpp"
+#include "openvic-simulation/types/fixed_point/FixedPoint.hpp"
using namespace OpenVic;
@@ -39,21 +40,17 @@ MilitaryBudget::MilitaryBudget(GUINode const& parent):
}
}
-fixed_point_t MilitaryBudget::get_expenses() const {
- return std::max(fixed_point_t::_0, -get_balance());
-}
-
fixed_point_t MilitaryBudget::calculate_budget_and_update_custom(
CountryInstance& country,
const fixed_point_t scaled_value
) {
- return scaled_value * country.get_projected_military_spending_unscaled_by_slider_untracked();
+ return scaled_value * country.get_projected_military_spending_unscaled_by_slider(connect_to_mark_dirty());
}
ReadOnlyClampedValue& MilitaryBudget::get_clamped_value(CountryInstance& country) const {
return country.get_military_spending_slider_value();
}
-void MilitaryBudget::on_slider_value_changed(const fixed_point_t scaled_value) {
+void MilitaryBudget::on_slider_scaled_value_changed(const fixed_point_t scaled_value) {
PlayerSingleton::get_singleton()->set_military_spending_slider_value(scaled_value);
}
\ No newline at end of file
diff --git a/extension/src/openvic-extension/components/budget/MilitaryBudget.hpp b/extension/src/openvic-extension/components/budget/MilitaryBudget.hpp
index 59d3a0aa..542ff851 100644
--- a/extension/src/openvic-extension/components/budget/MilitaryBudget.hpp
+++ b/extension/src/openvic-extension/components/budget/MilitaryBudget.hpp
@@ -11,10 +11,8 @@ namespace OpenVic {
const fixed_point_t scaled_value
) override;
ReadOnlyClampedValue& get_clamped_value(CountryInstance& country) const override;
- void on_slider_value_changed(const fixed_point_t scaled_value) override;
-
+ void on_slider_scaled_value_changed(const fixed_point_t scaled_value) override;
public:
MilitaryBudget(GUINode const& parent);
- fixed_point_t get_expenses() const override;
};
}
\ No newline at end of file
diff --git a/extension/src/openvic-extension/components/budget/NationalStockpileBudget.cpp b/extension/src/openvic-extension/components/budget/NationalStockpileBudget.cpp
index 42ef08fc..4f801fd5 100644
--- a/extension/src/openvic-extension/components/budget/NationalStockpileBudget.cpp
+++ b/extension/src/openvic-extension/components/budget/NationalStockpileBudget.cpp
@@ -21,46 +21,24 @@ NationalStockpileBudget::NationalStockpileBudget(GUINode const& parent):
army_stockpile_budget{parent},
navy_stockpile_budget{parent},
construction_stockpile_budget{parent}
-{
- connections[0] = army_stockpile_budget.balance_changed.connect(&NationalStockpileBudget::on_slider_value_changed, this);
- connections[1] = navy_stockpile_budget.balance_changed.connect(&NationalStockpileBudget::on_slider_value_changed, this);
- connections[2] = construction_stockpile_budget.balance_changed.connect(&NationalStockpileBudget::on_slider_value_changed, this);
-
+{
GUILabel::set_text_and_tooltip(
parent, "./country_budget/nat_stock_desc",
"BUDGET_NATIONAL_STOCKPILE","NAT_STOCK_DESC"
);
}
-fixed_point_t NationalStockpileBudget::get_expenses() const {
- return std::max(fixed_point_t::_0, -get_balance());
-}
-
-void NationalStockpileBudget::on_slider_value_changed() {
- CountryInstance* const country_ptr = PlayerSingleton::get_singleton()->get_player_country();
- ERR_FAIL_NULL(country_ptr);
- update_labels(*country_ptr);
-}
-
-void NationalStockpileBudget::full_update(CountryInstance& country) {\
- for (connection& c : connections) {
- c.block();
- };
- army_stockpile_budget.full_update(country);
- navy_stockpile_budget.full_update(country);
- construction_stockpile_budget.full_update(country);
- for (connection& c : connections) {
- c.unblock();
- };
-
- update_labels(country);
-}
+void NationalStockpileBudget::update() {
+ CountryInstance* const player_country_ptr = PlayerSingleton::get_singleton()->get_player_country_untracked();
+ if (player_country_ptr == nullptr) {
+ return;
+ }
+ CountryInstance& country = *player_country_ptr;
-void NationalStockpileBudget::update_labels(CountryInstance& country) {
- const fixed_point_t military_balance = army_stockpile_budget.get_balance()
- + navy_stockpile_budget.get_balance();
- const fixed_point_t balance = military_balance
- + construction_stockpile_budget.get_balance();
+ const fixed_point_t military_balance = army_stockpile_budget.get_balance(connect_property_to_mark_dirty())
+ + navy_stockpile_budget.get_balance(connect_property_to_mark_dirty());
+ const fixed_point_t new_balance = military_balance
+ + construction_stockpile_budget.get_balance(connect_property_to_mark_dirty());
military_costs_label.set_text(
Utilities::cash_to_string_dp_dynamic(-military_balance)
@@ -72,8 +50,8 @@ void NationalStockpileBudget::update_labels(CountryInstance& country) {
Utilities::cash_to_string_dp_dynamic(3) //TODO
);
expenses_label.set_text(
- Utilities::cash_to_string_dp_dynamic(-balance)
+ Utilities::cash_to_string_dp_dynamic(-new_balance)
);
- set_balance(balance);
+ _balance = new_balance;
}
\ No newline at end of file
diff --git a/extension/src/openvic-extension/components/budget/NationalStockpileBudget.hpp b/extension/src/openvic-extension/components/budget/NationalStockpileBudget.hpp
index 11cd3e51..d3b9a2e7 100644
--- a/extension/src/openvic-extension/components/budget/NationalStockpileBudget.hpp
+++ b/extension/src/openvic-extension/components/budget/NationalStockpileBudget.hpp
@@ -1,18 +1,19 @@
#pragma once
-#include "openvic-extension/components/budget/abstract/BudgetComponent.hpp"
+#include
+
#include "openvic-extension/components/budget/ArmyStockpileBudget.hpp"
#include "openvic-extension/components/budget/ConstructionStockpileBudget.hpp"
#include "openvic-extension/components/budget/NavyStockpileBudget.hpp"
+#include "openvic-extension/components/ReactiveComponent.hpp"
namespace OpenVic {
struct GUILabel;
struct GUINode;
struct GUIScrollbar;
- struct NationalStockpileBudget : public BudgetComponent, public BudgetExpenseComponent {
+ struct NationalStockpileBudget : public ReactiveComponent, public BudgetExpenseComponent {
private:
- connection connections[3];
GUILabel& military_costs_label;
GUILabel& todays_actual_stockpile_spending_label;
GUILabel& overseas_costs_label;
@@ -20,12 +21,17 @@ namespace OpenVic {
ArmyStockpileBudget army_stockpile_budget;
NavyStockpileBudget navy_stockpile_budget;
ConstructionStockpileBudget construction_stockpile_budget;
- void on_slider_value_changed();
- void update_labels(CountryInstance& country);
-
+ fixed_point_t _balance;
public:
NationalStockpileBudget(GUINode const& parent);
- fixed_point_t get_expenses() const override;
- void full_update(CountryInstance& country) override;
+ void update() override;
+
+ template
+ requires std::invocable&>
+ [[nodiscard]] fixed_point_t get_balance(ConnectTemplateType&& connect) {
+ connect(marked_dirty);
+ update_if_dirty();
+ return _balance;
+ }
};
}
\ No newline at end of file
diff --git a/extension/src/openvic-extension/components/budget/NavyStockpileBudget.cpp b/extension/src/openvic-extension/components/budget/NavyStockpileBudget.cpp
index 1e63eebe..85cbbfd2 100644
--- a/extension/src/openvic-extension/components/budget/NavyStockpileBudget.cpp
+++ b/extension/src/openvic-extension/components/budget/NavyStockpileBudget.cpp
@@ -22,10 +22,6 @@ NavyStockpileBudget::NavyStockpileBudget(GUINode const& parent):
slider.set_block_signals(false);
}
-fixed_point_t NavyStockpileBudget::get_expenses() const {
- return std::max(fixed_point_t::_0, -get_balance());
-}
-
fixed_point_t NavyStockpileBudget::calculate_budget_and_update_custom(
CountryInstance& country,
const fixed_point_t scaled_value
@@ -37,6 +33,6 @@ ReadOnlyClampedValue& NavyStockpileBudget::get_clamped_value(CountryInstance& co
return country.get_navy_spending_slider_value();
}
-void NavyStockpileBudget::on_slider_value_changed(const fixed_point_t scaled_value) {
+void NavyStockpileBudget::on_slider_scaled_value_changed(const fixed_point_t scaled_value) {
PlayerSingleton::get_singleton()->set_national_stockpile_navy_spending_slider_value(scaled_value);
}
\ No newline at end of file
diff --git a/extension/src/openvic-extension/components/budget/NavyStockpileBudget.hpp b/extension/src/openvic-extension/components/budget/NavyStockpileBudget.hpp
index 1143f729..c74d2a4a 100644
--- a/extension/src/openvic-extension/components/budget/NavyStockpileBudget.hpp
+++ b/extension/src/openvic-extension/components/budget/NavyStockpileBudget.hpp
@@ -11,10 +11,8 @@ namespace OpenVic {
const fixed_point_t scaled_value
) override;
ReadOnlyClampedValue& get_clamped_value(CountryInstance& country) const override;
- void on_slider_value_changed(const fixed_point_t scaled_value) override;
-
+ void on_slider_scaled_value_changed(const fixed_point_t scaled_value) override;
public:
NavyStockpileBudget(GUINode const& parent);
- fixed_point_t get_expenses() const override;
};
}
\ No newline at end of file
diff --git a/extension/src/openvic-extension/components/budget/SocialBudget.cpp b/extension/src/openvic-extension/components/budget/SocialBudget.cpp
index ade6d6fe..36ca8d37 100644
--- a/extension/src/openvic-extension/components/budget/SocialBudget.cpp
+++ b/extension/src/openvic-extension/components/budget/SocialBudget.cpp
@@ -43,22 +43,24 @@ SocialBudget::SocialBudget(GUINode const& parent):
}
}
-fixed_point_t SocialBudget::get_expenses() const {
- return std::max(fixed_point_t::_0, -get_balance());
-}
-
fixed_point_t SocialBudget::calculate_budget_and_update_custom(
CountryInstance& country,
const fixed_point_t scaled_value
) {
- const fixed_point_t pensions = scaled_value * country.get_projected_pensions_spending_unscaled_by_slider_untracked();
+ const fixed_point_t pensions = scaled_value * country.get_projected_pensions_spending_unscaled_by_slider(
+ connect_to_mark_dirty()
+ );
pensions_label.set_text(
Utilities::cash_to_string_dp_dynamic(pensions)
);
- const fixed_point_t unemployment_subsidies = scaled_value * country.get_projected_unemployment_subsidies_spending_unscaled_by_slider_untracked();
+
+ const fixed_point_t unemployment_subsidies = scaled_value * country.get_projected_unemployment_subsidies_spending_unscaled_by_slider(
+ connect_to_mark_dirty()
+ );
unemployment_subsidies_label.set_text(
Utilities::cash_to_string_dp_dynamic(unemployment_subsidies)
);
+
return pensions + unemployment_subsidies;
}
@@ -66,6 +68,6 @@ ReadOnlyClampedValue& SocialBudget::get_clamped_value(CountryInstance& country)
return country.get_social_spending_slider_value();
}
-void SocialBudget::on_slider_value_changed(const fixed_point_t scaled_value) {
+void SocialBudget::on_slider_scaled_value_changed(const fixed_point_t scaled_value) {
PlayerSingleton::get_singleton()->set_social_spending_slider_value(scaled_value);
}
\ No newline at end of file
diff --git a/extension/src/openvic-extension/components/budget/SocialBudget.hpp b/extension/src/openvic-extension/components/budget/SocialBudget.hpp
index 167f9221..edc92bd8 100644
--- a/extension/src/openvic-extension/components/budget/SocialBudget.hpp
+++ b/extension/src/openvic-extension/components/budget/SocialBudget.hpp
@@ -13,10 +13,8 @@ namespace OpenVic {
const fixed_point_t scaled_value
) override;
ReadOnlyClampedValue& get_clamped_value(CountryInstance& country) const override;
- void on_slider_value_changed(const fixed_point_t scaled_value) override;
-
+ void on_slider_scaled_value_changed(const fixed_point_t scaled_value) override;
public:
SocialBudget(GUINode const& parent);
- fixed_point_t get_expenses() const override;
};
}
\ No newline at end of file
diff --git a/extension/src/openvic-extension/components/budget/StrataTaxBudget.cpp b/extension/src/openvic-extension/components/budget/StrataTaxBudget.cpp
index 9b300f68..c4ee97a1 100644
--- a/extension/src/openvic-extension/components/budget/StrataTaxBudget.cpp
+++ b/extension/src/openvic-extension/components/budget/StrataTaxBudget.cpp
@@ -15,19 +15,19 @@
using namespace OpenVic;
StrataTaxBudget::StrataTaxBudget(
- GUINode const& parent,
- Strata const& new_strata,
- ModifierEffectCache const& new_modifier_effect_cache
+ GUINode const* parent,
+ Strata const* new_strata,
+ ModifierEffectCache const* new_modifier_effect_cache
): SliderBudgetComponent(
- parent,
- generate_slider_tooltip_localisation_key(new_strata),
+ *parent,
+ generate_slider_tooltip_localisation_key(*new_strata),
BALANCE,
- Utilities::format("./country_budget/tax_%d_slider", static_cast(new_strata.get_index())),
- Utilities::format("./country_budget/tax_%d_inc", static_cast(new_strata.get_index()))
+ Utilities::format("./country_budget/tax_%d_slider", static_cast(new_strata->get_index())),
+ Utilities::format("./country_budget/tax_%d_inc", static_cast(new_strata->get_index()))
),
- BudgetIncomeComponent(generate_summary_localisation_key(new_strata), 1),
- strata{new_strata},
- modifier_effect_cache{new_modifier_effect_cache}
+ BudgetIncomeComponent(generate_summary_localisation_key(*new_strata), 1),
+ strata{*new_strata},
+ modifier_effect_cache{*new_modifier_effect_cache}
{
slider.set_block_signals(true);
slider.set_step_count(100);
@@ -35,9 +35,9 @@ StrataTaxBudget::StrataTaxBudget(
slider.set_block_signals(false);
GUILabel::set_text_and_tooltip(
- parent,
- Utilities::format("./country_budget/tax_%d_desc", static_cast(new_strata.get_index())),
- generate_slider_tooltip_localisation_key(new_strata),
+ *parent,
+ Utilities::format("./country_budget/tax_%d_desc", static_cast(new_strata->get_index())),
+ generate_slider_tooltip_localisation_key(*new_strata),
Utilities::format(
"TAX_%s_DESC",
(godot::String::utf8(
@@ -48,24 +48,20 @@ StrataTaxBudget::StrataTaxBudget(
);
}
-fixed_point_t StrataTaxBudget::get_income() const {
- return std::max(fixed_point_t::_0, get_balance());
-}
-
fixed_point_t StrataTaxBudget::calculate_budget_and_update_custom(
CountryInstance& country,
const fixed_point_t scaled_value
) {
return scaled_value
* country.get_taxable_income_by_strata(strata)
- * country.get_tax_efficiency_untracked();
+ * country.get_tax_efficiency(connect_to_mark_dirty());
}
ReadOnlyClampedValue& StrataTaxBudget::get_clamped_value(CountryInstance& country) const {
return country.get_tax_rate_slider_value_by_strata(strata);
}
-void StrataTaxBudget::on_slider_value_changed(const fixed_point_t scaled_value) {
+void StrataTaxBudget::on_slider_scaled_value_changed(const fixed_point_t scaled_value) {
PlayerSingleton::get_singleton()->set_strata_tax_rate_slider_value(
strata,
scaled_value
@@ -105,7 +101,7 @@ void StrataTaxBudget::update_slider_tooltip(
const godot::String localised_strata_tax = slider.tr(slider_tooltip_localisation_key);
- const fixed_point_t tax_efficiency = country.get_tax_efficiency_untracked();
+ const fixed_point_t tax_efficiency = country.get_tax_efficiency(connect_to_mark_dirty());
const godot::String tax_efficiency_text = slider.tr(tax_efficiency_localisation_key).replace(
Utilities::get_long_value_placeholder(),
Utilities::float_to_string_dp(100 * tax_efficiency, 2)
diff --git a/extension/src/openvic-extension/components/budget/StrataTaxBudget.hpp b/extension/src/openvic-extension/components/budget/StrataTaxBudget.hpp
index c53df96e..f556fb05 100644
--- a/extension/src/openvic-extension/components/budget/StrataTaxBudget.hpp
+++ b/extension/src/openvic-extension/components/budget/StrataTaxBudget.hpp
@@ -20,19 +20,16 @@ namespace OpenVic {
const fixed_point_t scaled_value
) override;
ReadOnlyClampedValue& get_clamped_value(CountryInstance& country) const override;
- void on_slider_value_changed(const fixed_point_t scaled_value) override;
+ void on_slider_scaled_value_changed(const fixed_point_t scaled_value) override;
void update_slider_tooltip(
CountryInstance& country,
const fixed_point_t scaled_value
) override;
-
public:
StrataTaxBudget(
- GUINode const& parent,
- Strata const& new_strata,
- ModifierEffectCache const& new_modifier_effect_cache
+ GUINode const* parent,
+ Strata const* new_strata,
+ ModifierEffectCache const* new_modifier_effect_cache
);
- StrataTaxBudget(StrataTaxBudget&&) = default;
- fixed_point_t get_income() const override;
};
}
\ No newline at end of file
diff --git a/extension/src/openvic-extension/components/budget/TariffBudget.cpp b/extension/src/openvic-extension/components/budget/TariffBudget.cpp
index b9fb8ead..ef93b098 100644
--- a/extension/src/openvic-extension/components/budget/TariffBudget.cpp
+++ b/extension/src/openvic-extension/components/budget/TariffBudget.cpp
@@ -2,6 +2,7 @@
#include
#include
+#include
#include "openvic-extension/classes/GUILabel.hpp"
#include "openvic-extension/classes/GUINode.hpp"
@@ -46,28 +47,20 @@ TariffBudget::TariffBudget(
);
}
-fixed_point_t TariffBudget::get_expenses() const {
- return std::max(fixed_point_t::_0, -get_balance());
-}
-
-fixed_point_t TariffBudget::get_income() const {
- return std::max(fixed_point_t::_0, get_balance());
-}
-
fixed_point_t TariffBudget::calculate_budget_and_update_custom(
CountryInstance& country,
const fixed_point_t scaled_value
) {
return scaled_value
- * country.get_yesterdays_import_value_untracked()
- * country.tariff_efficiency.get_untracked();
+ * country.get_yesterdays_import_value(connect_to_mark_dirty())
+ * country.tariff_efficiency.get(connect_to_mark_dirty());
}
ReadOnlyClampedValue& TariffBudget::get_clamped_value(CountryInstance& country) const {
return country.get_tariff_rate_slider_value();
}
-void TariffBudget::on_slider_value_changed(const fixed_point_t scaled_value) {
+void TariffBudget::on_slider_scaled_value_changed(const fixed_point_t scaled_value) {
PlayerSingleton::get_singleton()->set_tariff_rate_slider_value(scaled_value);
}
@@ -95,7 +88,7 @@ void TariffBudget::update_slider_tooltip(
"Y"+Utilities::get_percentage_value_placeholder(),
//not percentage_to_string_dp as localisation text contains the %
prefix+Utilities::fixed_point_to_string_dp(
- 100 * scaled_value * country.tariff_efficiency.get_untracked(),
+ 100 * scaled_value * country.tariff_efficiency.get(connect_to_mark_dirty()),
1
)
);
@@ -104,7 +97,7 @@ void TariffBudget::update_slider_tooltip(
Utilities::get_percentage_value_placeholder(),
//not percentage_to_string_dp as localisation text contains the %
Utilities::fixed_point_to_string_dp(
- 100 * country.get_administrative_efficiency_from_administrators_untracked(),
+ 100 * country.get_administrative_efficiency_from_administrators(connect_to_mark_dirty()),
1
)
);
diff --git a/extension/src/openvic-extension/components/budget/TariffBudget.hpp b/extension/src/openvic-extension/components/budget/TariffBudget.hpp
index a3304d87..b75d0890 100644
--- a/extension/src/openvic-extension/components/budget/TariffBudget.hpp
+++ b/extension/src/openvic-extension/components/budget/TariffBudget.hpp
@@ -21,15 +21,12 @@ namespace OpenVic {
const fixed_point_t scaled_value
) override;
ReadOnlyClampedValue& get_clamped_value(CountryInstance& country) const override;
- void on_slider_value_changed(const fixed_point_t scaled_value) override;
-
+ void on_slider_scaled_value_changed(const fixed_point_t scaled_value) override;
public:
TariffBudget(
GUINode const& parent,
CountryDefines const& country_defines
);
- fixed_point_t get_expenses() const override;
- fixed_point_t get_income() const override;
void update_slider_tooltip(
CountryInstance& country,
const fixed_point_t scaled_value
diff --git a/extension/src/openvic-extension/components/budget/abstract/BudgetComponent.cpp b/extension/src/openvic-extension/components/budget/abstract/BudgetComponent.cpp
deleted file mode 100644
index 532b4b20..00000000
--- a/extension/src/openvic-extension/components/budget/abstract/BudgetComponent.cpp
+++ /dev/null
@@ -1,16 +0,0 @@
-#include "BudgetComponent.hpp"
-
-using namespace OpenVic;
-
-fixed_point_t BudgetComponent::get_balance() const {
- return balance;
-}
-
-void BudgetComponent::set_balance(const fixed_point_t new_balance) {
- if (balance == new_balance) {;
- return;
- }
-
- balance = new_balance;
- balance_changed();
-}
\ No newline at end of file
diff --git a/extension/src/openvic-extension/components/budget/abstract/BudgetComponent.hpp b/extension/src/openvic-extension/components/budget/abstract/BudgetComponent.hpp
deleted file mode 100644
index 8e7b7a69..00000000
--- a/extension/src/openvic-extension/components/budget/abstract/BudgetComponent.hpp
+++ /dev/null
@@ -1,21 +0,0 @@
-#pragma once
-
-#include
-#include
-
-namespace OpenVic {
- struct CountryInstance;
-
- struct BudgetComponent {
- private:
- fixed_point_t balance = 0;
-
- protected:
- void set_balance(const fixed_point_t balance);
-
- public:
- signal_property balance_changed;
- fixed_point_t get_balance() const;
- virtual void full_update(CountryInstance& country) = 0;
- };
-}
\ No newline at end of file
diff --git a/extension/src/openvic-extension/components/budget/abstract/BudgetExpenseComponent.cpp b/extension/src/openvic-extension/components/budget/abstract/BudgetExpenseComponent.cpp
index dbec463e..d447445c 100644
--- a/extension/src/openvic-extension/components/budget/abstract/BudgetExpenseComponent.cpp
+++ b/extension/src/openvic-extension/components/budget/abstract/BudgetExpenseComponent.cpp
@@ -11,9 +11,9 @@ BudgetExpenseComponent::BudgetExpenseComponent(
expenses_summary_decimal_places{new_expenses_summary_decimal_places} {}
godot::String BudgetExpenseComponent::generate_expenses_summary_text(
+ const fixed_point_t expenses,
godot::Object const& translation_object
) const {
- const fixed_point_t expenses = get_expenses();
return translation_object.tr(expenses_summary_localisation_key).replace(
Utilities::get_short_value_placeholder(),
expenses_summary_decimal_places < 0
@@ -22,9 +22,12 @@ godot::String BudgetExpenseComponent::generate_expenses_summary_text(
);
}
-godot::String BudgetExpenseComponent::generate_balance_expenses_summary_text(godot::Object const& translation_object) const {
+godot::String BudgetExpenseComponent::generate_balance_expenses_summary_text(
+ const fixed_point_t expenses,
+ godot::Object const& translation_object
+) const {
static const godot::StringName red_minus = "R-";
- const fixed_point_t expenses = get_expenses(); //TODO use yesterdays value
+ //TODO use yesterdays value
return translation_object.tr(expenses_summary_localisation_key).replace(
"Y$VAL$",
red_minus + Utilities::float_to_string_dp(expenses, expenses_summary_decimal_places)
diff --git a/extension/src/openvic-extension/components/budget/abstract/BudgetExpenseComponent.hpp b/extension/src/openvic-extension/components/budget/abstract/BudgetExpenseComponent.hpp
index 18dab83d..2ffa73cc 100644
--- a/extension/src/openvic-extension/components/budget/abstract/BudgetExpenseComponent.hpp
+++ b/extension/src/openvic-extension/components/budget/abstract/BudgetExpenseComponent.hpp
@@ -21,8 +21,13 @@ namespace OpenVic {
const int32_t new_expenses_summary_decimal_places = -1
);
public:
- virtual fixed_point_t get_expenses() const = 0;
- virtual godot::String generate_expenses_summary_text(godot::Object const& translation_object) const;
- virtual godot::String generate_balance_expenses_summary_text(godot::Object const& translation_object) const;
+ virtual godot::String generate_expenses_summary_text(
+ const fixed_point_t expenses,
+ godot::Object const& translation_object
+ ) const;
+ virtual godot::String generate_balance_expenses_summary_text(
+ const fixed_point_t expenses,
+ godot::Object const& translation_object
+ ) const;
};
}
\ No newline at end of file
diff --git a/extension/src/openvic-extension/components/budget/abstract/BudgetIncomeComponent.cpp b/extension/src/openvic-extension/components/budget/abstract/BudgetIncomeComponent.cpp
index 77dae159..b625bdce 100644
--- a/extension/src/openvic-extension/components/budget/abstract/BudgetIncomeComponent.cpp
+++ b/extension/src/openvic-extension/components/budget/abstract/BudgetIncomeComponent.cpp
@@ -11,9 +11,9 @@ BudgetIncomeComponent::BudgetIncomeComponent(
income_summary_decimal_places{new_income_summary_decimal_places} {}
godot::String BudgetIncomeComponent::generate_income_summary_text(
+ const fixed_point_t income,
godot::Object const& translation_object
) const {
- const fixed_point_t income = get_income();
return translation_object.tr(income_summary_localisation_key).replace(
Utilities::get_short_value_placeholder(),
income_summary_decimal_places < 0
@@ -22,9 +22,12 @@ godot::String BudgetIncomeComponent::generate_income_summary_text(
);
}
-godot::String BudgetIncomeComponent::generate_balance_income_summary_text(godot::Object const& translation_object) const {
+godot::String BudgetIncomeComponent::generate_balance_income_summary_text(
+ const fixed_point_t income,
+ godot::Object const& translation_object
+) const {
static const godot::StringName green_plus = "G+";
- const fixed_point_t income = get_income(); //TODO use yesterdays value
+ //TODO use yesterdays value
return translation_object.tr(income_summary_localisation_key).replace(
"Y$VAL$",
green_plus + Utilities::float_to_string_dp(income, income_summary_decimal_places)
diff --git a/extension/src/openvic-extension/components/budget/abstract/BudgetIncomeComponent.hpp b/extension/src/openvic-extension/components/budget/abstract/BudgetIncomeComponent.hpp
index 9f4bd422..bf6f2ff6 100644
--- a/extension/src/openvic-extension/components/budget/abstract/BudgetIncomeComponent.hpp
+++ b/extension/src/openvic-extension/components/budget/abstract/BudgetIncomeComponent.hpp
@@ -21,8 +21,13 @@ namespace OpenVic {
const int32_t new_income_summary_decimal_places = -1
);
public:
- virtual fixed_point_t get_income() const = 0;
- virtual godot::String generate_income_summary_text(godot::Object const& translation_object) const;
- virtual godot::String generate_balance_income_summary_text(godot::Object const& translation_object) const;
+ virtual godot::String generate_income_summary_text(
+ const fixed_point_t income,
+ godot::Object const& translation_object
+ ) const;
+ virtual godot::String generate_balance_income_summary_text(
+ const fixed_point_t income,
+ godot::Object const& translation_object
+ ) const;
};
}
\ No newline at end of file
diff --git a/extension/src/openvic-extension/components/budget/abstract/SliderBudgetComponent.cpp b/extension/src/openvic-extension/components/budget/abstract/SliderBudgetComponent.cpp
index 1249a12d..18ec01f8 100644
--- a/extension/src/openvic-extension/components/budget/abstract/SliderBudgetComponent.cpp
+++ b/extension/src/openvic-extension/components/budget/abstract/SliderBudgetComponent.cpp
@@ -3,11 +3,14 @@
#include
#include
+#include
+#include
#include "openvic-extension/classes/GUILabel.hpp"
#include "openvic-extension/classes/GUINode.hpp"
#include "openvic-extension/classes/GUIScrollbar.hpp"
#include "openvic-extension/singletons/PlayerSingleton.hpp"
+#include "openvic-simulation/types/Signal.hpp"
using namespace OpenVic;
@@ -32,31 +35,52 @@ SliderBudgetComponent::SliderBudgetComponent(
},
slider{*parent.get_gui_scrollbar_from_nodepath(slider_path)}
{
- slider.set_block_signals(true);
- slider.set_step_count(100);
- slider.set_scale(0, 1, 100);
- slider.set_block_signals(false);
- slider.value_changed.connect(&SliderBudgetComponent::_on_slider_value_changed, this);
+ slider_scaled_value_cached = slider.get_scaled_value(
+ [this](signal& slider_scaled_value_changed) mutable -> void {
+ slider_scaled_value_connection = std::move(
+ slider_scaled_value_changed.connect(&SliderBudgetComponent::_on_slider_scaled_value_changed, this)
+ );
+ }
+ );
+ player_country_cached = PlayerSingleton::get_singleton()->get_player_country(
+ [this](signal& player_country_changed) mutable ->void {
+ player_country_connection = std::move(
+ player_country_changed.connect(&SliderBudgetComponent::_on_player_country_changed, this)
+ );
+ }
+ );
}
-void SliderBudgetComponent::_on_slider_value_changed() {
- const fixed_point_t scaled_value = slider.get_value_scaled_fp();
- on_slider_value_changed(scaled_value);
- CountryInstance* const country_ptr = PlayerSingleton::get_singleton()->get_player_country();
- ERR_FAIL_NULL(country_ptr);
- update_labels(*country_ptr, scaled_value);
+void SliderBudgetComponent::initialise() {
+ _on_player_country_changed(player_country_cached);
}
-void SliderBudgetComponent::full_update(CountryInstance& country) {
- ReadOnlyClampedValue& clamped_value = get_clamped_value(country);
+void SliderBudgetComponent::_on_player_country_changed(CountryInstance* new_player_country) {
+ player_country_cached = new_player_country;
+ if (new_player_country == nullptr) {
+ slider.unlink();
+ } else {
+ ReadOnlyClampedValue& clamped_value = get_clamped_value(*new_player_country);
+ slider.set_block_signals(true);
+ slider.link_to(clamped_value);
+ slider.set_block_signals(false);
+ slider_scaled_value_cached = clamped_value.get_value_untracked();
+ }
+ mark_dirty();
+}
- slider.set_block_signals(true);
- slider.set_range_limits_and_value_from_slider_value(clamped_value);
- slider.set_block_signals(false);
- update_labels(country, clamped_value.get_value_untracked());
+void SliderBudgetComponent::_on_slider_scaled_value_changed(const fixed_point_t scaled_value) {
+ slider_scaled_value_cached = scaled_value;
+ on_slider_scaled_value_changed(scaled_value);
+ mark_dirty();
}
-void SliderBudgetComponent::update_labels(CountryInstance& country, const fixed_point_t scaled_value) {
+void SliderBudgetComponent::update() {
+ if (player_country_cached == nullptr) {
+ return;
+ }
+ CountryInstance& country = *player_country_cached;
+ const fixed_point_t scaled_value = slider_scaled_value_cached;
const fixed_point_t budget = calculate_budget_and_update_custom(country, scaled_value);
if (budget_label != nullptr) {
budget_label->set_text(
@@ -72,10 +96,9 @@ void SliderBudgetComponent::update_labels(CountryInstance& country, const fixed_
update_slider_tooltip(country, scaled_value);
- const fixed_point_t balance = budget_type == EXPENSES
+ _balance = budget_type == EXPENSES
? -budget
: budget;
- set_balance(balance);
}
void SliderBudgetComponent::update_slider_tooltip(
diff --git a/extension/src/openvic-extension/components/budget/abstract/SliderBudgetComponent.hpp b/extension/src/openvic-extension/components/budget/abstract/SliderBudgetComponent.hpp
index 8982b27f..286ee456 100644
--- a/extension/src/openvic-extension/components/budget/abstract/SliderBudgetComponent.hpp
+++ b/extension/src/openvic-extension/components/budget/abstract/SliderBudgetComponent.hpp
@@ -3,7 +3,9 @@
#include
#include
-#include "openvic-extension/components/budget/abstract/BudgetComponent.hpp"
+#include
+
+#include "openvic-extension/components/ReactiveComponent.hpp"
namespace OpenVic {
struct CountryInstance;
@@ -17,13 +19,19 @@ namespace OpenVic {
EXPENSES
};
- struct SliderBudgetComponent : public BudgetComponent {
+ struct SliderBudgetComponent : public ReactiveComponent {
private:
- //multiplies balance by -1 for balance_label
- const BudgetType budget_type;
+ const BudgetType budget_type; //multiplies balance by -1 for balance_label
GUILabel* const percent_label;
- void _on_slider_value_changed();
- void update_labels(CountryInstance& country, const fixed_point_t scaled_value);
+ fixed_point_t _balance;
+
+ scoped_connection player_country_connection;
+ CountryInstance* player_country_cached;
+ void _on_player_country_changed(CountryInstance* const player_country);
+
+ scoped_connection slider_scaled_value_connection;
+ fixed_point_t slider_scaled_value_cached;
+ void _on_slider_scaled_value_changed(const fixed_point_t scaled_value);
protected:
const godot::String slider_tooltip_localisation_key;
GUIScrollbar& slider;
@@ -38,18 +46,26 @@ namespace OpenVic {
godot::NodePath const& percent_label_path = {}
);
+ void initialise() override;
+ virtual void update_slider_tooltip(
+ CountryInstance& country,
+ const fixed_point_t scaled_value
+ );
+
virtual fixed_point_t calculate_budget_and_update_custom(
CountryInstance& country,
const fixed_point_t scaled_value
) = 0;
virtual ReadOnlyClampedValue& get_clamped_value(CountryInstance& country) const = 0;
- virtual void on_slider_value_changed(const fixed_point_t scaled_value) = 0;
- virtual void update_slider_tooltip(
- CountryInstance& country,
- const fixed_point_t scaled_value
- );
-
+ virtual void on_slider_scaled_value_changed(const fixed_point_t scaled_value) = 0;
+ void update() override;
public:
- void full_update(CountryInstance& country) override;
+ template
+ requires std::invocable&>
+ [[nodiscard]] fixed_point_t get_balance(ConnectTemplateType&& connect) {
+ connect(marked_dirty);
+ update_if_dirty();
+ return _balance;
+ }
};
}
\ No newline at end of file
diff --git a/extension/src/openvic-extension/singletons/GameSingleton.cpp b/extension/src/openvic-extension/singletons/GameSingleton.cpp
index e6cab201..32ac058e 100644
--- a/extension/src/openvic-extension/singletons/GameSingleton.cpp
+++ b/extension/src/openvic-extension/singletons/GameSingleton.cpp
@@ -155,7 +155,7 @@ Error GameSingleton::setup_game(int32_t bookmark_index) {
PlayerSingleton& player_singleton = *PlayerSingleton::get_singleton();
player_singleton.set_player_country(starting_country);
- ERR_FAIL_NULL_V(player_singleton.get_player_country(), FAILED);
+ ERR_FAIL_NULL_V(player_singleton.get_player_country_untracked(), FAILED);
// TODO - remove this test starting research
for (Technology const& technology :
@@ -288,7 +288,7 @@ Error GameSingleton::_update_colour_image() {
PlayerSingleton const& player_singleton = *PlayerSingleton::get_singleton();
if (instance_manager != nullptr &&
!get_definition_manager().get_mapmode_manager().generate_mapmode_colours(
- instance_manager->get_map_instance(), mapmode, player_singleton.get_player_country(),
+ instance_manager->get_map_instance(), mapmode, player_singleton.get_player_country_untracked(),
player_singleton.get_selected_province(), colour_data_array.ptrw()
)) {
err = FAILED;
diff --git a/extension/src/openvic-extension/singletons/MenuSingleton.cpp b/extension/src/openvic-extension/singletons/MenuSingleton.cpp
index bb00571b..69fc1e8c 100644
--- a/extension/src/openvic-extension/singletons/MenuSingleton.cpp
+++ b/extension/src/openvic-extension/singletons/MenuSingleton.cpp
@@ -88,8 +88,8 @@ String MenuSingleton::_get_state_name(State const& state) const {
}
String MenuSingleton::_get_country_name(CountryInstance const& country) const {
- GovernmentType const* government_type = country.get_government_type_untracked();
- if (government_type != nullptr) {
+ GovernmentType const* const government_type = country.get_government_type_untracked();
+ if (government_type != nullptr && !government_type->get_identifier().empty()) {
const String government_name_key = Utilities::std_to_godot_string(StringUtils::append_string_views(
country.get_identifier(), "_", government_type->get_identifier()
));
@@ -106,9 +106,9 @@ String MenuSingleton::_get_country_name(CountryInstance const& country) const {
String MenuSingleton::_get_country_adjective(CountryInstance const& country) const {
static constexpr std::string_view adjective = "_ADJ";
+ GovernmentType const* const government_type = country.get_government_type_untracked();
- GovernmentType const* government_type = country.get_government_type_untracked();
- if (government_type != nullptr) {
+ if (government_type != nullptr && !government_type->get_identifier().empty()) {
const String government_adjective_key = Utilities::std_to_godot_string(StringUtils::append_string_views(
country.get_identifier(), "_", government_type->get_identifier(), adjective
));
@@ -295,7 +295,7 @@ String MenuSingleton::_make_rules_tooltip(RuleSet const& rules) const {
}
String MenuSingleton::_make_mobilisation_impact_tooltip() const {
- CountryInstance const* country = PlayerSingleton::get_singleton()->get_player_country();
+ CountryInstance const* const country = PlayerSingleton::get_singleton()->get_player_country_untracked();
if (country == nullptr) {
return {};
@@ -446,6 +446,7 @@ void MenuSingleton::_bind_methods() {
/* BUDGET MENU */
OV_BIND_METHOD(MenuSingleton::link_budget_menu_to_cpp, { "godot_budget_menu" });
+ OV_BIND_METHOD(MenuSingleton::update_budget_menu_cpp);
/* Find/Search Panel */
OV_BIND_METHOD(MenuSingleton::generate_search_cache);
@@ -1132,7 +1133,7 @@ int32_t MenuSingleton::get_rgo_owner_pop_icon_index() const {
/* TOPBAR */
Dictionary MenuSingleton::get_topbar_info() const {
- CountryInstance* country = PlayerSingleton::get_singleton()->get_player_country();
+ CountryInstance* const country = PlayerSingleton::get_singleton()->get_player_country_untracked();
if (country == nullptr) {
return {};
}
@@ -1270,7 +1271,7 @@ Dictionary MenuSingleton::get_topbar_info() const {
static const StringName research_points_key = "research_points";
static const StringName research_points_tooltip_key = "research_points_tooltip";
- Technology const* current_research = country->get_current_research_untracked();
+ Technology const* const current_research = country->get_current_research_untracked();
if (current_research != nullptr) {
static const StringName research_localisation_key = "TECHNOLOGYVIEW_RESEARCH_TOOLTIP";
static const String tech_replace_key = "$TECH$";
@@ -1539,11 +1540,6 @@ String MenuSingleton::get_longform_date() const {
void MenuSingleton::link_budget_menu_to_cpp(GUINode const* const godot_budget_menu) {
ERR_FAIL_NULL(godot_budget_menu);
GameSingleton& game_singleton = *GameSingleton::get_singleton();
- BudgetMenu* old_instance = budget_menu.get();
- if (old_instance != nullptr) {
- game_singleton.gamestate_updated.disconnect(&BudgetMenu::update, old_instance);
- }
-
auto const& strata_keys = game_singleton.get_definition_manager().get_pop_manager().get_stratas();
ModifierEffectCache const& modifier_effect_cache = game_singleton.get_definition_manager().get_modifier_manager().get_modifier_effect_cache();
CountryDefines const& country_defines = game_singleton.get_definition_manager().get_define_manager().get_country_defines();
@@ -1553,7 +1549,10 @@ void MenuSingleton::link_budget_menu_to_cpp(GUINode const* const godot_budget_me
modifier_effect_cache,
country_defines
);
- game_singleton.gamestate_updated.connect(&BudgetMenu::update, budget_menu.get());
+}
+
+void MenuSingleton::update_budget_menu_cpp() const {
+ budget_menu->update_if_dirty();
}
/* Find/Search Panel */
diff --git a/extension/src/openvic-extension/singletons/MenuSingleton.hpp b/extension/src/openvic-extension/singletons/MenuSingleton.hpp
index 0ceb0b34..f26a18e7 100644
--- a/extension/src/openvic-extension/singletons/MenuSingleton.hpp
+++ b/extension/src/openvic-extension/singletons/MenuSingleton.hpp
@@ -287,6 +287,7 @@ namespace OpenVic {
/* BUDGET MENU */
void link_budget_menu_to_cpp(GUINode const* const godot_budget_menu);
+ void update_budget_menu_cpp() const;
/* Find/Search Panel */
// TODO - update on country government type change and state creation/destruction
diff --git a/extension/src/openvic-extension/singletons/MilitaryMenu.cpp b/extension/src/openvic-extension/singletons/MilitaryMenu.cpp
index cea34ab0..11370ea0 100644
--- a/extension/src/openvic-extension/singletons/MilitaryMenu.cpp
+++ b/extension/src/openvic-extension/singletons/MilitaryMenu.cpp
@@ -302,7 +302,7 @@ Dictionary MenuSingleton::make_in_progress_unit_dict() const {
// TODO - remove test data, read actual in-progress units from SIM
UnitType const* unit_type = definition_manager.get_military_manager().get_unit_type_manager().get_unit_type_by_index(0);
- ProvinceInstance const* location = PlayerSingleton::get_singleton()->get_player_country()->get_capital();
+ ProvinceInstance const* location = PlayerSingleton::get_singleton()->get_player_country_untracked()->get_capital();
const Date eta { 1900 };
const fixed_point_t progress = fixed_point_t::_0_50;
const ordered_map> required_goods {
@@ -360,7 +360,7 @@ Dictionary MenuSingleton::get_military_menu_info() {
StaticModifierCache const& static_modifier_cache = definition_manager.get_modifier_manager().get_static_modifier_cache();
IssueManager const& issue_manager = definition_manager.get_politics_manager().get_issue_manager();
- CountryInstance const* country = PlayerSingleton::get_singleton()->get_player_country();
+ CountryInstance const* country = PlayerSingleton::get_singleton()->get_player_country_untracked();
if (country == nullptr) {
return {};
}
diff --git a/extension/src/openvic-extension/singletons/PlayerSingleton.cpp b/extension/src/openvic-extension/singletons/PlayerSingleton.cpp
index fc1e6b63..21b382a2 100644
--- a/extension/src/openvic-extension/singletons/PlayerSingleton.cpp
+++ b/extension/src/openvic-extension/singletons/PlayerSingleton.cpp
@@ -2,6 +2,7 @@
#include
#include
+#include
#include "openvic-extension/classes/GUIScrollbar.hpp"
#include "openvic-extension/singletons/GameSingleton.hpp"
@@ -64,7 +65,7 @@ PlayerSingleton* PlayerSingleton::get_singleton() {
return singleton;
}
-PlayerSingleton::PlayerSingleton() {
+PlayerSingleton::PlayerSingleton() : player_country{nullptr} {
ERR_FAIL_COND(singleton != nullptr);
singleton = this;
}
@@ -76,7 +77,8 @@ PlayerSingleton::~PlayerSingleton() {
// Player country
void PlayerSingleton::set_player_country(CountryInstance* new_player_country) {
- if (OV_unlikely(player_country == new_player_country)) {
+ CountryInstance* const old_player_country = player_country.get_untracked();
+ if (OV_unlikely(old_player_country == new_player_country)) {
return;
}
@@ -84,23 +86,23 @@ void PlayerSingleton::set_player_country(CountryInstance* new_player_country) {
InstanceManager* instance_manager = game_singleton.get_instance_manager();
ERR_FAIL_NULL(instance_manager);
- if (player_country != nullptr) {
+ if (old_player_country != nullptr) {
instance_manager->queue_game_action(
game_action_type_t::GAME_ACTION_SET_AI,
- std::pair { player_country->get_index(), true }
+ std::pair { old_player_country->get_index(), true }
);
}
- player_country = new_player_country;
-
- if (player_country != nullptr) {
+ if (new_player_country != nullptr) {
instance_manager->queue_game_action(
game_action_type_t::GAME_ACTION_SET_AI,
- std::pair { player_country->get_index(), false }
+ std::pair { new_player_country->get_index(), false }
);
}
- Logger::info("Set player country to: ", player_country != nullptr ? player_country->get_identifier() : "");
+ player_country.set(new_player_country);
+
+ Logger::info("Set player country to: ", new_player_country != nullptr ? new_player_country->get_identifier() : "");
game_singleton._on_gamestate_updated();
}
@@ -116,8 +118,9 @@ void PlayerSingleton::set_player_country_by_province_number(int32_t province_num
}
Vector2 PlayerSingleton::get_player_country_capital_position() const {
- if (player_country != nullptr) {
- ProvinceInstance const* capital = player_country->get_capital();
+ CountryInstance const* const current_player_country = player_country.get_untracked();
+ if (current_player_country != nullptr) {
+ ProvinceInstance const* capital = current_player_country->get_capital();
if (capital != nullptr) {
return GameSingleton::get_singleton()->get_billboard_pos(capital->get_province_definition());
@@ -213,12 +216,13 @@ void PlayerSingleton::expand_selected_province_building(int32_t building_index)
// Budget
#define SET_SLIDER_GAME_ACTION(value_name, game_action_name) \
void PlayerSingleton::set_##value_name##_slider_value(fixed_point_t const value) const { \
- if (player_country == nullptr) { \
+ CountryInstance const* const current_player_country = player_country.get_untracked(); \
+ if (current_player_country == nullptr) { \
return; \
} \
GameSingleton::get_singleton()->get_instance_manager()->queue_game_action( \
game_action_type_t::GAME_ACTION_SET_##game_action_name, \
- std::pair { player_country->get_index(), value } \
+ std::pair { current_player_country->get_index(), value } \
); \
}
@@ -234,12 +238,11 @@ SET_SLIDER_GAME_ACTION(tariff_rate, TARIFF_RATE)
#undef SET_SLIDER_GAME_ACTION
void PlayerSingleton::set_strata_tax_rate_slider_value(Strata const& strata, fixed_point_t const value) const {
- if (player_country == nullptr) {
- return;
- }
+ CountryInstance const* const current_player_country = player_country.get_untracked();
+ ERR_FAIL_NULL(current_player_country);
GameSingleton::get_singleton()->get_instance_manager()->queue_game_action(
game_action_type_t::GAME_ACTION_SET_STRATA_TAX,
- std::tuple { player_country->get_index(), strata.get_index(), value }
+ std::tuple { current_player_country->get_index(), strata.get_index(), value }
);
}
@@ -251,28 +254,30 @@ void PlayerSingleton::set_strata_tax_rate_slider_value(Strata const& strata, fix
// Trade
void PlayerSingleton::set_good_automated(int32_t good_index, bool is_automated) const {
- ERR_FAIL_NULL(player_country);
+ CountryInstance const* const current_player_country = player_country.get_untracked();
+ ERR_FAIL_NULL(current_player_country);
InstanceManager* instance_manager = GameSingleton::get_singleton()->get_instance_manager();
ERR_FAIL_NULL(instance_manager);
instance_manager->queue_game_action(
game_action_type_t::GAME_ACTION_SET_GOOD_AUTOMATED,
- std::tuple { player_country->get_index(), good_index, is_automated }
+ std::tuple { current_player_country->get_index(), good_index, is_automated }
);
}
void PlayerSingleton::set_good_trade_order(int32_t good_index, bool is_selling, GUIScrollbar const* amount_slider) const {
+ CountryInstance const* const current_player_country = player_country.get_untracked();
+ ERR_FAIL_NULL(current_player_country);
ERR_FAIL_NULL(amount_slider);
- ERR_FAIL_NULL(player_country);
InstanceManager* instance_manager = GameSingleton::get_singleton()->get_instance_manager();
ERR_FAIL_NULL(instance_manager);
instance_manager->queue_game_action(
game_action_type_t::GAME_ACTION_SET_GOOD_TRADE_ORDER, std::tuple {
- player_country->get_index(), good_index, is_selling,
- MenuSingleton::calculate_trade_menu_stockpile_cutoff_amount_fp(amount_slider->get_value_scaled_fp())
+ current_player_country->get_index(), good_index, is_selling,
+ MenuSingleton::calculate_trade_menu_stockpile_cutoff_amount_fp(amount_slider->get_scaled_value_untracked())
}
);
}
@@ -281,14 +286,15 @@ void PlayerSingleton::set_good_trade_order(int32_t good_index, bool is_selling,
// Military
void PlayerSingleton::create_leader(bool is_general) const {
- ERR_FAIL_NULL(player_country);
+ CountryInstance const* const current_player_country = player_country.get_untracked();
+ ERR_FAIL_NULL(current_player_country);
InstanceManager* instance_manager = GameSingleton::get_singleton()->get_instance_manager();
ERR_FAIL_NULL(instance_manager);
instance_manager->queue_game_action(
game_action_type_t::GAME_ACTION_CREATE_LEADER,
- std::pair { player_country->get_index(), is_general }
+ std::pair { current_player_country->get_index(), is_general }
);
}
@@ -303,37 +309,40 @@ void PlayerSingleton::set_can_use_leader(uint64_t leader_id, bool can_use) const
}
void PlayerSingleton::set_auto_create_leaders(bool value) const {
- ERR_FAIL_NULL(player_country);
+ CountryInstance const* const current_player_country = player_country.get_untracked();
+ ERR_FAIL_NULL(current_player_country);
InstanceManager* instance_manager = GameSingleton::get_singleton()->get_instance_manager();
ERR_FAIL_NULL(instance_manager);
instance_manager->queue_game_action(
game_action_type_t::GAME_ACTION_SET_AUTO_CREATE_LEADERS,
- std::pair { player_country->get_index(), value }
+ std::pair { current_player_country->get_index(), value }
);
}
void PlayerSingleton::set_auto_assign_leaders(bool value) const {
- ERR_FAIL_NULL(player_country);
+ CountryInstance const* const current_player_country = player_country.get_untracked();
+ ERR_FAIL_NULL(current_player_country);
InstanceManager* instance_manager = GameSingleton::get_singleton()->get_instance_manager();
ERR_FAIL_NULL(instance_manager);
instance_manager->queue_game_action(
game_action_type_t::GAME_ACTION_SET_AUTO_ASSIGN_LEADERS,
- std::pair { player_country->get_index(), value }
+ std::pair { current_player_country->get_index(), value }
);
}
void PlayerSingleton::set_mobilise(bool value) const {
- ERR_FAIL_NULL(player_country);
+ CountryInstance const* const current_player_country = player_country.get_untracked();
+ ERR_FAIL_NULL(current_player_country);
InstanceManager* instance_manager = GameSingleton::get_singleton()->get_instance_manager();
ERR_FAIL_NULL(instance_manager);
instance_manager->queue_game_action(
game_action_type_t::GAME_ACTION_SET_MOBILISE,
- std::pair { player_country->get_index(), value }
+ std::pair { current_player_country->get_index(), value }
);
}
diff --git a/extension/src/openvic-extension/singletons/PlayerSingleton.hpp b/extension/src/openvic-extension/singletons/PlayerSingleton.hpp
index c04ec1cb..9c17d5ff 100644
--- a/extension/src/openvic-extension/singletons/PlayerSingleton.hpp
+++ b/extension/src/openvic-extension/singletons/PlayerSingleton.hpp
@@ -5,6 +5,7 @@
#include
#include
#include
+#include
namespace OpenVic {
struct CountryInstance;
@@ -16,7 +17,7 @@ namespace OpenVic {
static inline PlayerSingleton* singleton = nullptr;
- CountryInstance* player_country = nullptr;
+ STATE_PROPERTY(CountryInstance*, player_country);
ProvinceInstance const* PROPERTY(selected_province, nullptr);
static godot::StringName const& _signal_province_selected();
@@ -31,12 +32,6 @@ namespace OpenVic {
~PlayerSingleton();
// Player country
- [[nodiscard]] constexpr CountryInstance* get_player_country() {
- return player_country;
- }
- [[nodiscard]] constexpr CountryInstance const* get_player_country() const {
- return player_country;
- }
void set_player_country(CountryInstance* new_player_country);
void set_player_country_by_province_number(int32_t province_number);
godot::Vector2 get_player_country_capital_position() const;
diff --git a/extension/src/openvic-extension/singletons/TradeMenu.cpp b/extension/src/openvic-extension/singletons/TradeMenu.cpp
index cfa6f2b9..e943c7fb 100644
--- a/extension/src/openvic-extension/singletons/TradeMenu.cpp
+++ b/extension/src/openvic-extension/singletons/TradeMenu.cpp
@@ -26,7 +26,7 @@ Dictionary MenuSingleton::get_trade_menu_good_categories_info() const {
GoodInstanceManager const& good_instance_manager = instance_manager->get_good_instance_manager();
GoodDefinitionManager const& good_definition_manager = good_instance_manager.get_good_definition_manager();
- CountryInstance const* country = PlayerSingleton::get_singleton()->get_player_country();
+ CountryInstance const* country = PlayerSingleton::get_singleton()->get_player_country_untracked();
Dictionary ret;
@@ -130,7 +130,7 @@ Dictionary MenuSingleton::get_trade_menu_trade_details_info(
instance_manager->get_good_instance_manager().get_good_instance_by_index(trade_detail_good_index);
ERR_FAIL_NULL_V(good_instance, {});
- CountryInstance const* country = PlayerSingleton::get_singleton()->get_player_country();
+ CountryInstance const* country = PlayerSingleton::get_singleton()->get_player_country_untracked();
Dictionary ret;
@@ -197,7 +197,7 @@ Dictionary MenuSingleton::get_trade_menu_tables_info() const {
ERR_FAIL_NULL_V(instance_manager, {});
GoodInstanceManager const& good_instance_manager = instance_manager->get_good_instance_manager();
- CountryInstance const* country = PlayerSingleton::get_singleton()->get_player_country();
+ CountryInstance const* country = PlayerSingleton::get_singleton()->get_player_country_untracked();
Dictionary ret;
@@ -327,5 +327,5 @@ Dictionary MenuSingleton::get_trade_menu_tables_info() const {
float MenuSingleton::calculate_trade_menu_stockpile_cutoff_amount(GUIScrollbar const* slider) {
ERR_FAIL_NULL_V(slider, 0.0f);
- return calculate_trade_menu_stockpile_cutoff_amount_fp(slider->get_value_scaled_fp());
+ return calculate_trade_menu_stockpile_cutoff_amount_fp(slider->get_scaled_value_untracked());
}
diff --git a/game/src/UI/Session/BudgetMenu.gd b/game/src/UI/Session/BudgetMenu.gd
index c6462456..34ed9988 100644
--- a/game/src/UI/Session/BudgetMenu.gd
+++ b/game/src/UI/Session/BudgetMenu.gd
@@ -74,6 +74,10 @@ func _ready() -> void:
_update_info()
+func _process(_delta : float) -> void:
+ if visible:
+ MenuSingleton.update_budget_menu_cpp()
+
func _notification(what : int) -> void:
match what:
NOTIFICATION_TRANSLATION_CHANGED: