diff options
author | Hop311 <Hop3114@gmail.com> | 2024-08-30 23:30:12 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-08-30 23:30:12 +0200 |
commit | 2e0bc5b556b9c6df46a8cdd48d3f109e0ac76b63 (patch) | |
tree | 2c521b99fe6cd0a7fd5d6a29e55645b3415792b3 /extension/src/openvic-extension/classes/GFXPieChartTexture.cpp | |
parent | f54e454afb90f8868e7c62529e2a388fdaadf20b (diff) | |
parent | bdc2ba527bc02e7cdf977f6040f2ca85aa4f9a94 (diff) |
Merge pull request #253 from OpenVicProject/tooltip
Tooltips
Diffstat (limited to 'extension/src/openvic-extension/classes/GFXPieChartTexture.cpp')
-rw-r--r-- | extension/src/openvic-extension/classes/GFXPieChartTexture.cpp | 97 |
1 files changed, 53 insertions, 44 deletions
diff --git a/extension/src/openvic-extension/classes/GFXPieChartTexture.cpp b/extension/src/openvic-extension/classes/GFXPieChartTexture.cpp index 417566d..5d955a3 100644 --- a/extension/src/openvic-extension/classes/GFXPieChartTexture.cpp +++ b/extension/src/openvic-extension/classes/GFXPieChartTexture.cpp @@ -7,6 +7,7 @@ using namespace godot; using namespace OpenVic; +using namespace OpenVic::Utilities::literals; StringName const& GFXPieChartTexture::_slice_identifier_key() { static const StringName slice_identifier_key = "identifier"; @@ -21,7 +22,35 @@ StringName const& GFXPieChartTexture::_slice_weight_key() { return slice_weight_key; } -static constexpr float TWO_PI = 2.0f * std::numbers::pi_v<float>; +GFXPieChartTexture::slice_t const* GFXPieChartTexture::get_slice(Vector2 const& position) const { + if (slices.empty() || position.length_squared() > 1.0_real) { + return nullptr; + } + + static constexpr float TWO_PI = 2.0f * std::numbers::pi_v<float>; + + /* 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(-position.y, position.x); + if (theta < 0.0f) { + theta += TWO_PI; + } + + /* Rescale angle so that total_weight is a full rotation. */ + theta *= total_weight / TWO_PI; + + /* Find the slice theta lies in. */ + for (slice_t const& slice : slices) { + theta -= slice.weight; + + if (theta <= 0.0f) { + return &slice; + } + } + + /* Default to the first slice in case theta never reaches 0 due to floating point inaccuracy. */ + return &slices.front(); +} Error GFXPieChartTexture::_generate_pie_chart_image() { ERR_FAIL_NULL_V(gfx_pie_chart, FAILED); @@ -30,60 +59,37 @@ Error GFXPieChartTexture::_generate_pie_chart_image() { 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(); + const int32_t pie_chart_radius = gfx_pie_chart->get_size(); + const int32_t pie_chart_diameter = 2 * pie_chart_radius; /* 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; + const bool can_update = pie_chart_image.is_valid() && pie_chart_image->get_width() == pie_chart_diameter + && pie_chart_image->get_height() == pie_chart_diameter; if (!can_update) { - pie_chart_image = Image::create(pie_chart_size, pie_chart_size, false, Image::FORMAT_RGBA8); + pie_chart_image = Image::create(pie_chart_diameter, pie_chart_diameter, 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) { - - /* 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 += TWO_PI; - } - - /* Rescale angle so that total_weight is a full rotation. */ - theta *= total_weight / TWO_PI; + for (Vector2i point { 0, 0 }; point.y < pie_chart_diameter; ++point.y) { - /* Default to the first colour in case theta never reaches 0 due to floating point inaccuracy. */ - Color colour = slices.front().first; + for (point.x = 0; point.x < pie_chart_diameter; ++point.x) { - /* Find the slice theta lies in. */ - for (slice_t const& slice : slices) { - theta -= slice.second; + Vector2 offset = point; + // Move to the centre of the pixel + offset += Vector2 { 0.5_real, 0.5_real }; + // Normalise to [0, 2] + offset /= pie_chart_radius; + // Translate to [-1, 1] + offset -= Vector2 { 1.0_real, 1.0_real }; - if (theta <= 0.0f) { - colour = slice.first; - break; - } - } + slice_t const* slice = get_slice(offset); - pie_chart_image->set_pixelv(point, colour); - } else { - pie_chart_image->set_pixelv(point, background_colour); - } + pie_chart_image->set_pixelv(point, slice != nullptr ? slice->colour : background_colour); } } } else { @@ -107,12 +113,15 @@ Error GFXPieChartTexture::set_slices_array(godot_pie_chart_data_t const& new_sli for (int32_t i = 0; i < new_slices.size(); ++i) { Dictionary const& slice_dict = new_slices[i]; ERR_CONTINUE_MSG( - !slice_dict.has(_slice_colour_key()) || !slice_dict.has(_slice_weight_key()), + !slice_dict.has(_slice_identifier_key()) || !slice_dict.has(_slice_colour_key()) + || !slice_dict.has(_slice_weight_key()), vformat("Invalid slice keys at index %d", i) ); - const slice_t slice = std::make_pair(slice_dict[_slice_colour_key()], slice_dict[_slice_weight_key()]); - if (slice.second > 0.0f) { - total_weight += slice.second; + const slice_t slice { + slice_dict[_slice_identifier_key()], slice_dict[_slice_colour_key()], slice_dict[_slice_weight_key()] + }; + if (slice.weight > 0.0f) { + total_weight += slice.weight; slices.push_back(slice); } } |