Skip to content

Commit 41ac5c4

Browse files
dependabot[bot]wvpm
authored andcommitted
New reactive budget menu
1 parent 9678ee2 commit 41ac5c4

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+887
-589
lines changed

extension/doc_classes/MenuSingleton.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,11 @@
255255
<description>
256256
</description>
257257
</method>
258+
<method name="update_budget_menu_cpp" qualifiers="const">
259+
<return type="void" />
260+
<description>
261+
</description>
262+
</method>
258263
<method name="update_search_results">
259264
<return type="void" />
260265
<param index="0" name="text" type="String" />

extension/src/openvic-extension/classes/GFXMaskedFlagTexture.cpp

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -213,12 +213,22 @@ Error GFXMaskedFlagTexture::set_flag_country_name_and_type(
213213
return set_flag_country_and_type(new_flag_country, new_flag_type);
214214
}
215215

216+
Error GFXMaskedFlagTexture::set_flag_country(CountryInstance* new_flag_country) {
216217
Error GFXMaskedFlagTexture::set_flag_country(CountryInstance* new_flag_country) {
217218
if (new_flag_country == nullptr) {
219+
flag_government_type_connection = {};
218220
return set_flag_country_and_type(nullptr, {});
219221
}
220222

221-
GovernmentType const* government_type = new_flag_country->flag_government_type.get_untracked();
223+
GovernmentType const* const government_type = new_flag_country->flag_government_type.get(
224+
[this,new_flag_country](signal<>& changed) mutable -> void {
225+
flag_government_type_connection = changed.connect_scoped(
226+
[this,new_flag_country]() -> void {
227+
set_flag_country(new_flag_country);
228+
}
229+
);
230+
}
231+
);
222232

223233
const StringName new_flag_type = government_type != nullptr
224234
? StringName { Utilities::std_to_godot_string(government_type->get_flag_type()) }
@@ -232,13 +242,13 @@ Error GFXMaskedFlagTexture::set_flag_country_name(String const& new_flag_country
232242
return set_flag_country(nullptr);
233243
}
234244

235-
GameSingleton* game_singleton = GameSingleton::get_singleton();
245+
GameSingleton* const game_singleton = GameSingleton::get_singleton();
236246
ERR_FAIL_NULL_V(game_singleton, FAILED);
237247

238-
InstanceManager* instance_manager = game_singleton->get_instance_manager();
248+
InstanceManager* const instance_manager = game_singleton->get_instance_manager();
239249
ERR_FAIL_NULL_V(instance_manager, FAILED);
240250

241-
CountryInstance* new_flag_country = instance_manager->get_country_instance_manager()
251+
CountryInstance* const new_flag_country = instance_manager->get_country_instance_manager()
242252
.get_country_instance_by_identifier(
243253
Utilities::godot_to_std_string(new_flag_country_name)
244254
);

extension/src/openvic-extension/classes/GFXMaskedFlagTexture.hpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#pragma once
22

33
#include <openvic-simulation/interface/GFXSprite.hpp>
4+
#include <openvic-simulation/types/Signal.hpp>
45

56
#include "openvic-extension/classes/GFXButtonStateTexture.hpp"
67

@@ -9,8 +10,11 @@ namespace OpenVic {
910
struct CountryInstance;
1011

1112
class GFXMaskedFlagTexture : public GFXButtonStateHavingTexture {
13+
private:
1214
GDCLASS(GFXMaskedFlagTexture, GFXButtonStateHavingTexture)
1315

16+
scoped_connection flag_government_type_connection;
17+
1418
GFX::MaskedFlag const* PROPERTY(gfx_masked_flag, nullptr);
1519
CountryDefinition const* PROPERTY(flag_country, nullptr);
1620
godot::StringName PROPERTY(flag_type);

extension/src/openvic-extension/classes/GUILabel.cpp

Lines changed: 31 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ using namespace OpenVic;
1818
using namespace godot;
1919
using namespace OpenVic::Utilities::literals;
2020

21+
GUILabel::~GUILabel() {
22+
disconnect_all();
23+
}
24+
2125
GUILabel::string_segment_t::string_segment_t(String&& new_text, Color const& new_colour, real_t new_width)
2226
: text { std::move(new_text) }, colour { new_colour }, width { new_width } {}
2327

@@ -594,7 +598,7 @@ std::pair<String, GUILabel::colour_instructions_t> GUILabel::generate_display_te
594598

595599
std::vector<GUILabel::line_t> GUILabel::generate_lines_and_segments(
596600
String const& display_text, colour_instructions_t const& colour_instructions
597-
) const {
601+
) {
598602
static constexpr char RESET_COLOUR_CODE = '!';
599603

600604
std::vector<line_t> unwrapped_lines;
@@ -641,7 +645,7 @@ std::vector<GUILabel::line_t> GUILabel::generate_lines_and_segments(
641645

642646
void GUILabel::separate_lines(
643647
String const& string, Color const& colour, std::vector<line_t>& unwrapped_lines
644-
) const {
648+
) {
645649
static const String NEWLINE_MARKER = "\n";
646650

647651
int64_t start_pos = 0;
@@ -664,7 +668,7 @@ void GUILabel::separate_lines(
664668

665669
void GUILabel::separate_currency_segments(
666670
String const& string, Color const& colour, line_t& line
667-
) const {
671+
) {
668672
int64_t start_pos = 0;
669673
int64_t marker_pos;
670674

@@ -688,34 +692,38 @@ void GUILabel::separate_currency_segments(
688692

689693
GUILabel::flag_segment_t GUILabel::make_flag_segment(String const& identifier) {
690694
GameSingleton& game_singleton = *GameSingleton::get_singleton();
695+
GameSingleton& game_singleton = *GameSingleton::get_singleton();
691696

692697
int32_t country_index = -1;
693698
StringName flag_type;
694699

700+
InstanceManager* instance_manager = game_singleton.get_instance_manager();
695701
InstanceManager* instance_manager = game_singleton.get_instance_manager();
696702

697-
if (instance_manager != nullptr) {
698-
CountryInstance* country_instance =
699-
instance_manager->get_country_instance_manager().get_country_instance_by_identifier(
703+
if (instance_manager == nullptr) {
704+
CountryDefinition const* country_definition =
705+
game_singleton.get_definition_manager().get_country_definition_manager().get_country_definition_by_identifier(
700706
Utilities::godot_to_std_string(identifier)
701707
);
702708

703-
if (country_instance != nullptr) {
704-
country_index = country_instance->get_country_definition().get_index();
705-
706-
GovernmentType const* government_type = country_instance->flag_government_type.get_untracked();
707-
if (government_type != nullptr) {
708-
flag_type = Utilities::std_to_godot_string(government_type->get_flag_type());
709-
}
709+
if (country_definition != nullptr) {
710+
country_index = country_definition->get_index();
710711
}
711712
} else {
712-
CountryDefinition const* country_definition =
713-
game_singleton.get_definition_manager().get_country_definition_manager().get_country_definition_by_identifier(
713+
CountryInstance* const country_instance = instance_manager->get_country_instance_manager()
714+
.get_country_instance_by_identifier(
714715
Utilities::godot_to_std_string(identifier)
715716
);
716717

717-
if (country_definition != nullptr) {
718-
country_index = country_definition->get_index();
718+
if (country_instance != nullptr) {
719+
country_index = country_instance->get_country_definition().get_index();
720+
DerivedState<GovernmentType const*>& flag_government_type_state = country_instance->flag_government_type;
721+
GovernmentType const* const flag_government_type = flag_government_type_state.get([this](signal<>& changed) mutable -> void {
722+
changed.connect(&GUILabel::on_flag_government_type_changed, this);
723+
});
724+
if (flag_government_type != nullptr) {
725+
flag_type = Utilities::std_to_godot_string(flag_government_type->get_flag_type());
726+
}
719727
}
720728
}
721729

@@ -740,9 +748,14 @@ GUILabel::flag_segment_t GUILabel::make_flag_segment(String const& identifier) {
740748
return flag_segment;
741749
}
742750

751+
void GUILabel::on_flag_government_type_changed() {
752+
disconnect_all();
753+
_queue_line_update();
754+
}
755+
743756
void GUILabel::separate_flag_segments(
744757
String const& string, Color const& colour, line_t& line
745-
) const {
758+
) {
746759
const auto push_string_segment = [this, &string, &colour, &line](int64_t start, int64_t end) -> void {
747760
String substring = string.substr(start, end - start);
748761
const real_t width = get_string_width(substring);

extension/src/openvic-extension/classes/GUILabel.hpp

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <godot_cpp/classes/style_box_texture.hpp>
88

99
#include <openvic-simulation/interface/GUI.hpp>
10+
#include <openvic-simulation/types/Signal.hpp>
1011

1112
#include "openvic-extension/classes/GFXSpriteTexture.hpp"
1213
#include "openvic-extension/classes/GUIHasTooltip.hpp"
@@ -17,7 +18,9 @@ namespace godot {
1718
}
1819

1920
namespace OpenVic {
20-
class GUILabel : public godot::Control {
21+
struct GovernmentType;
22+
23+
class GUILabel : public godot::Control, public observer {
2124
GDCLASS(GUILabel, godot::Control)
2225

2326
GUI_TOOLTIP_DEFINITIONS
@@ -81,6 +84,7 @@ namespace OpenVic {
8184
);
8285

8386
GUILabel();
87+
~GUILabel() override;
8488

8589
/* Reset gui_text to nullptr and reset current text. */
8690
void clear();
@@ -124,24 +128,25 @@ namespace OpenVic {
124128

125129
void _queue_line_update();
126130
void _update_lines();
131+
void on_flag_government_type_changed();
127132

128133
godot::String generate_substituted_text(godot::String const& base_text) const;
129134
std::pair<godot::String, colour_instructions_t> generate_display_text_and_colour_instructions(
130135
godot::String const& substituted_text
131136
) const;
132137
std::vector<line_t> generate_lines_and_segments(
133138
godot::String const& display_text, colour_instructions_t const& colour_instructions
134-
) const;
139+
);
135140
void separate_lines(
136141
godot::String const& string, godot::Color const& colour, std::vector<line_t>& lines
137-
) const;
142+
);
138143
void separate_currency_segments(
139144
godot::String const& string, godot::Color const& colour, line_t& line
140-
) const;
141-
static flag_segment_t make_flag_segment(godot::String const& identifier);
145+
);
146+
flag_segment_t make_flag_segment(godot::String const& identifier);
142147
void separate_flag_segments(
143148
godot::String const& string, godot::Color const& colour, line_t& line
144-
) const;
149+
);
145150
std::vector<line_t> wrap_lines(std::vector<line_t>& unwrapped_lines) const;
146151
void adjust_to_content_size();
147152
};

extension/src/openvic-extension/classes/GUIScrollbar.cpp

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,7 @@ void GUIScrollbar::emit_value_changed() {
299299
return;
300300
}
301301
emit_signal(signal_value_changed(), value);
302-
value_changed();
302+
scaled_value.set(_get_scaled_value(value));
303303
}
304304

305305
void GUIScrollbar::reset() {
@@ -522,12 +522,8 @@ void GUIScrollbar::set_value_as_ratio(float new_ratio) {
522522
set_value(step_count * new_ratio);
523523
}
524524

525-
fixed_point_t GUIScrollbar::get_value_scaled_fp() const {
526-
return _get_scaled_value(value);
527-
}
528-
529525
float GUIScrollbar::get_value_scaled() const {
530-
return get_value_scaled_fp().to_float();
526+
return _get_scaled_value(value).to_float();
531527
}
532528

533529
void GUIScrollbar::set_step_count(const int32_t new_step_count) {
@@ -592,12 +588,25 @@ void GUIScrollbar::set_range_limits_fp(
592588
: std::optional<fixed_point_t>{}
593589
);
594590
}
595-
void GUIScrollbar::set_range_limits_and_value_from_slider_value(ReadOnlyClampedValue& slider_value) {
591+
void GUIScrollbar::link_to(ReadOnlyClampedValue& clamped_value) {
592+
clamped_value_connection.disconnect();
596593
set_range_limits_fp(
597-
slider_value.get_min(),
598-
slider_value.get_max()
594+
clamped_value.get_min(),
595+
clamped_value.get_max()
599596
);
600-
set_scaled_value(slider_value.get_value_untracked());
597+
set_scaled_value(clamped_value.get_value(
598+
[this](signal<fixed_point_t>& dependency_changed) mutable -> void {
599+
clamped_value_connection = std::move(dependency_changed.connect(
600+
&GUIScrollbar::set_scaled_value,
601+
this
602+
));
603+
}
604+
));
605+
}
606+
607+
void GUIScrollbar::unlink() {
608+
clamped_value_connection.disconnect();
609+
clamped_value_connection={};
601610
}
602611

603612
void GUIScrollbar::set_length_override(real_t new_length_override) {

extension/src/openvic-extension/classes/GUIScrollbar.hpp

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,14 @@
66
#include <godot_cpp/classes/input_event.hpp>
77

88
#include <openvic-simulation/interface/GUI.hpp>
9-
#include <openvic-simulation/types/Signal.hpp>
109
#include <openvic-simulation/types/fixed_point/FixedPoint.hpp>
10+
#include <openvic-simulation/utility/reactive/MutableState.hpp>
1111

1212
#include "openvic-extension/classes/GFXSpriteTexture.hpp"
1313
#include "openvic-extension/classes/GUIHasTooltip.hpp"
1414

1515
namespace OpenVic {
16-
struct SliderValue;
16+
struct ReadOnlyClampedValue;
1717

1818
class GUIScrollbar : public godot::Control {
1919
GDCLASS(GUIScrollbar, godot::Control)
@@ -47,6 +47,9 @@ namespace OpenVic {
4747
int32_t scale_denominator = 1;
4848
int32_t PROPERTY(step_count, 1);
4949
int32_t PROPERTY(value, 0);
50+
STATE_PROPERTY(fixed_point_t, scaled_value);
51+
52+
scoped_connection clamped_value_connection;
5053

5154
bool PROPERTY_CUSTOM_PREFIX(range_limited, is, false);
5255
std::optional<int32_t> upper_range_limit;
@@ -91,7 +94,6 @@ namespace OpenVic {
9194

9295
public:
9396
static godot::StringName const& signal_value_changed();
94-
mutable signal_property<GUIScrollbar> value_changed;
9597

9698
GUIScrollbar();
9799

@@ -114,8 +116,6 @@ namespace OpenVic {
114116

115117
float get_value_as_ratio() const;
116118
void set_value_as_ratio(float new_ratio);
117-
118-
fixed_point_t get_value_scaled_fp() const;
119119
float get_value_scaled() const;
120120

121121
void set_step_count(const int32_t new_step_count);
@@ -132,9 +132,10 @@ namespace OpenVic {
132132
const std::optional<fixed_point_t> new_lower_range_limit,
133133
const std::optional<fixed_point_t> new_upper_range_limit
134134
);
135-
void set_range_limits_and_value_from_slider_value(
135+
void link_to(
136136
ReadOnlyClampedValue& slider_value
137137
);
138+
void unlink();
138139

139140
/* Override the main dimension of gui_scollbar's size with the specified length. */
140141
void set_length_override(real_t new_length_override);
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
#include "ReactiveComponent.hpp"
2+
3+
using namespace OpenVic;
4+
5+
void ReactiveComponent::add_connection(connection conn) {
6+
const std::lock_guard<std::mutex> lock_guard { connections_lock };
7+
connections.emplace_back(std::move(conn));
8+
}
9+
10+
void ReactiveComponent::disconnect_all() {
11+
const std::lock_guard<std::mutex> lock_guard { connections_lock };
12+
connections.clear();
13+
}
14+
15+
void ReactiveComponent::update_if_dirty() {
16+
if (!is_initialised) {
17+
initialise();
18+
is_initialised = true;
19+
}
20+
21+
if (!is_dirty) {
22+
return;
23+
}
24+
25+
const std::lock_guard<std::mutex> lock_guard { is_dirty_lock };
26+
if (!is_dirty) {
27+
return;
28+
}
29+
30+
update();
31+
32+
is_dirty = false;
33+
}
34+
35+
void ReactiveComponent::mark_dirty() {
36+
if (is_dirty) {
37+
return;
38+
}
39+
40+
const std::lock_guard<std::mutex> lock_guard { is_dirty_lock };
41+
if (is_dirty) {
42+
return;
43+
}
44+
45+
disconnect_all();
46+
is_dirty = true;
47+
marked_dirty();
48+
}

0 commit comments

Comments
 (0)