aboutsummaryrefslogtreecommitdiff
path: root/extension
diff options
context:
space:
mode:
Diffstat (limited to 'extension')
m---------extension/deps/openvic-simulation0
-rw-r--r--extension/src/openvic-extension/classes/GFXPieChartTexture.cpp40
-rw-r--r--extension/src/openvic-extension/classes/GFXPieChartTexture.hpp10
-rw-r--r--extension/src/openvic-extension/utility/UITools.cpp14
4 files changed, 49 insertions, 15 deletions
diff --git a/extension/deps/openvic-simulation b/extension/deps/openvic-simulation
-Subproject 2c892c99a6647be15ef23cabf6cc40f08769283
+Subproject c11d262a4d2c987c8cf8e0d4b24929cbe56bb28
diff --git a/extension/src/openvic-extension/classes/GFXPieChartTexture.cpp b/extension/src/openvic-extension/classes/GFXPieChartTexture.cpp
index f4c7851..10a2cb5 100644
--- a/extension/src/openvic-extension/classes/GFXPieChartTexture.cpp
+++ b/extension/src/openvic-extension/classes/GFXPieChartTexture.cpp
@@ -23,7 +23,7 @@ StringName const& GFXPieChartTexture::_slice_weight_key() {
return slice_weight_key;
}
-static constexpr float PI = std::numbers::pi_v<float>;
+static constexpr float TWO_PI = 2.0f * std::numbers::pi_v<float>;
Error GFXPieChartTexture::_generate_pie_chart_image() {
ERR_FAIL_NULL_V(gfx_pie_chart, FAILED);
@@ -31,40 +31,57 @@ Error GFXPieChartTexture::_generate_pie_chart_image() {
gfx_pie_chart->get_size() <= 0, FAILED,
vformat("Invalid GFX::PieChart size for GFXPieChartTexture - %d", gfx_pie_chart->get_size())
);
+
const int32_t pie_chart_size = 2 * gfx_pie_chart->get_size();
+
/* Whether we've already set the ImageTexture to an image of the right dimensions,
* and so can update it without creating and setting a new image, or not. */
const bool can_update = pie_chart_image.is_valid() && pie_chart_image->get_width() == pie_chart_size
&& pie_chart_image->get_height() == pie_chart_size;
+
if (!can_update) {
pie_chart_image = Image::create(pie_chart_size, pie_chart_size, false, Image::FORMAT_RGBA8);
ERR_FAIL_NULL_V(pie_chart_image, FAILED);
}
static const Color background_colour { 0.0f, 0.0f, 0.0f, 0.0f };
+
if (!slices.empty()) {
const float pie_chart_radius = gfx_pie_chart->get_size();
+
const Vector2 centre_translation = Vector2 { 0.5f, 0.5f } - static_cast<Vector2>(pie_chart_image->get_size()) * 0.5f;
+
for (Vector2i point { 0, 0 }; point.y < pie_chart_image->get_height(); ++point.y) {
+
for (point.x = 0; point.x < pie_chart_image->get_width(); ++point.x) {
+
const Vector2 offset = centre_translation + point;
+
if (offset.length() <= pie_chart_radius) {
- float theta = 0.5f * PI + atan2(offset.y, offset.x);
+
+ /* Calculate the anti-clockwise angle between the point and the centre of the image.
+ * The y coordinate is negated as the image coordinate system's y increases downwards. */
+ float theta = atan2(-offset.y, offset.x);
if (theta < 0.0f) {
- theta += 2.0f * PI;
+ theta += TWO_PI;
}
+
/* Rescale angle so that total_weight is a full rotation. */
- theta *= total_weight / (2.0f * PI);
+ theta *= total_weight / TWO_PI;
+
+ /* Default to the first colour in case theta never reaches 0 due to floating point inaccuracy. */
Color colour = slices.front().first;
+
/* Find the slice theta lies in. */
for (slice_t const& slice : slices) {
- if (theta <= slice.second) {
+ theta -= slice.second;
+
+ if (theta <= 0.0f) {
colour = slice.first;
break;
- } else {
- theta -= slice.second;
}
}
+
pie_chart_image->set_pixelv(point, colour);
} else {
pie_chart_image->set_pixelv(point, background_colour);
@@ -72,7 +89,9 @@ Error GFXPieChartTexture::_generate_pie_chart_image() {
}
}
} else {
+
pie_chart_image->fill(background_colour);
+
}
if (can_update) {
@@ -80,10 +99,11 @@ Error GFXPieChartTexture::_generate_pie_chart_image() {
} else {
set_image(pie_chart_image);
}
+
return OK;
}
-Error GFXPieChartTexture::set_slices_array(TypedArray<Dictionary> const& new_slices) {
+Error GFXPieChartTexture::set_slices_array(godot_pie_chart_data_t const& new_slices) {
slices.clear();
total_weight = 0.0f;
for (int32_t i = 0; i < new_slices.size(); ++i) {
@@ -92,7 +112,9 @@ Error GFXPieChartTexture::set_slices_array(TypedArray<Dictionary> const& new_sli
!slice_dict.has(_slice_colour_key()) || !slice_dict.has(_slice_weight_key()), vformat("Invalid slice keys at index %d", i)
);
slice_t slice = std::make_pair(slice_dict[_slice_colour_key()], slice_dict[_slice_weight_key()]);
- ERR_CONTINUE_MSG(slice.second <= 0.0f, vformat("Invalid slice values at index %d", i));
+ ERR_CONTINUE_MSG(
+ slice.second <= 0.0f, vformat("Invalid slice values at index %d \"%s\"", i, slice_dict[_slice_identifier_key()])
+ );
total_weight += slice.second;
slices.emplace_back(std::move(slice));
}
diff --git a/extension/src/openvic-extension/classes/GFXPieChartTexture.hpp b/extension/src/openvic-extension/classes/GFXPieChartTexture.hpp
index f8279e4..abeca1e 100644
--- a/extension/src/openvic-extension/classes/GFXPieChartTexture.hpp
+++ b/extension/src/openvic-extension/classes/GFXPieChartTexture.hpp
@@ -29,15 +29,17 @@ namespace OpenVic {
public:
GFXPieChartTexture();
+ using godot_pie_chart_data_t = godot::TypedArray<godot::Dictionary>;
+
/* Set slices given an Array of Dictionaries, each with the following key-value entries:
* - colour: Color
* - weight: float */
- godot::Error set_slices_array(godot::TypedArray<godot::Dictionary> const& new_slices);
+ godot::Error set_slices_array(godot_pie_chart_data_t const& new_slices);
/* Generate slice data from a distribution of HasIdentifierAndColour derived objects, sorted by their weight.
* The resulting Array of Dictionaries can be used as an argument for set_slices_array. */
template<std::derived_from<HasIdentifierAndColour> T>
- static godot::TypedArray<godot::Dictionary> distribution_to_slices_array(fixed_point_map_t<T const*> const& dist) {
+ static godot_pie_chart_data_t distribution_to_slices_array(fixed_point_map_t<T const*> const& dist) {
using namespace godot;
using entry_t = std::pair<T const*, fixed_point_t>;
std::vector<entry_t> sorted_dist;
@@ -49,9 +51,9 @@ namespace OpenVic {
sorted_dist.push_back(entry);
}
std::sort(sorted_dist.begin(), sorted_dist.end(), [](entry_t const& lhs, entry_t const& rhs) -> bool {
- return lhs.second < rhs.second;
+ return lhs.first < rhs.first;
});
- TypedArray<Dictionary> array;
+ godot_pie_chart_data_t array;
for (auto const& [key, val] : sorted_dist) {
Dictionary sub_dict;
sub_dict[_slice_identifier_key()] = Utilities::std_view_to_godot_string(key->get_identifier());
diff --git a/extension/src/openvic-extension/utility/UITools.cpp b/extension/src/openvic-extension/utility/UITools.cpp
index c00b64d..23dcced 100644
--- a/extension/src/openvic-extension/utility/UITools.cpp
+++ b/extension/src/openvic-extension/utility/UITools.cpp
@@ -177,8 +177,13 @@ static bool generate_icon(generate_gui_args_t&& args) {
godot_progress_bar, false, vformat("Failed to create TextureProgressBar for GUI icon %s", icon_name)
);
+ static constexpr double MIN_VALUE = 0.0, MAX_VALUE = 1.0;
+ static constexpr uint32_t STEPS = 100;
+
godot_progress_bar->set_nine_patch_stretch(true);
- godot_progress_bar->set_max(1.0);
+ godot_progress_bar->set_step((MAX_VALUE - MIN_VALUE) / STEPS);
+ godot_progress_bar->set_min(MIN_VALUE);
+ godot_progress_bar->set_max(MAX_VALUE);
GFX::ProgressBar const* progress_bar = icon.get_sprite()->cast_to<GFX::ProgressBar>();
@@ -435,7 +440,12 @@ static bool generate_text(generate_gui_args_t&& args) {
ERR_FAIL_NULL_V_MSG(godot_label, false, vformat("Failed to create Label for GUI text %s", text_name));
godot_label->set_text(std_view_to_godot_string(text.get_text()));
- godot_label->set_custom_minimum_size(Utilities::to_godot_fvec2(text.get_max_size()));
+
+ static const Vector2 default_padding { 1.0f, 0.0f };
+ const Vector2 border_size = Utilities::to_godot_fvec2(text.get_border_size()) + default_padding;
+ const Vector2 max_size = Utilities::to_godot_fvec2(text.get_max_size());
+ godot_label->set_position(godot_label->get_position() + border_size);
+ godot_label->set_custom_minimum_size(max_size - 2 * border_size);
using enum GUI::AlignedElement::format_t;
static const ordered_map<GUI::AlignedElement::format_t, HorizontalAlignment> format_map {