Skip to content

Commit

Permalink
Merge pull request #146 from Nemrav/piechart2
Browse files Browse the repository at this point in the history
Add Piecharts (gd 4.1)
  • Loading branch information
Hop311 authored Aug 17, 2023
2 parents ff0d38b + 9a08652 commit aa9961b
Show file tree
Hide file tree
Showing 18 changed files with 538 additions and 80 deletions.
83 changes: 77 additions & 6 deletions extension/src/GameSingleton.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
#include "GameSingleton.hpp"

#include <cassert>

#include <godot_cpp/variant/utility_functions.hpp>

#include "openvic/utility/Logger.hpp"
Expand All @@ -11,10 +9,9 @@
using namespace godot;
using namespace OpenVic;

TerrainVariant::TerrainVariant(std::string const& new_identfier,
TerrainVariant::TerrainVariant(const std::string_view new_identfier,
colour_t new_colour, Ref<Image> const& new_image)
: HasIdentifier { new_identfier },
HasColour { new_colour, true },
: HasIdentifierAndColour { new_identfier, new_colour, true },
image { new_image } {}

Ref<Image> TerrainVariant::get_image() const {
Expand Down Expand Up @@ -75,6 +72,9 @@ void GameSingleton::_bind_methods() {
ClassDB::bind_static_method("GameSingleton", D_METHOD("get_province_info_region_key"), &GameSingleton::get_province_info_region_key);
ClassDB::bind_static_method("GameSingleton", D_METHOD("get_province_info_life_rating_key"), &GameSingleton::get_province_info_life_rating_key);
ClassDB::bind_static_method("GameSingleton", D_METHOD("get_province_info_total_population_key"), &GameSingleton::get_province_info_total_population_key);
ClassDB::bind_static_method("GameSingleton", D_METHOD("get_province_info_pop_types_key"), &GameSingleton::get_province_info_pop_types_key);
ClassDB::bind_static_method("GameSingleton", D_METHOD("get_province_info_pop_ideologies_key"), &GameSingleton::get_province_info_pop_ideologies_key);
ClassDB::bind_static_method("GameSingleton", D_METHOD("get_province_info_pop_cultures_key"), &GameSingleton::get_province_info_pop_cultures_key);
ClassDB::bind_static_method("GameSingleton", D_METHOD("get_province_info_rgo_key"), &GameSingleton::get_province_info_rgo_key);
ClassDB::bind_static_method("GameSingleton", D_METHOD("get_province_info_buildings_key"), &GameSingleton::get_province_info_buildings_key);

Expand All @@ -84,6 +84,25 @@ void GameSingleton::_bind_methods() {
ClassDB::bind_static_method("GameSingleton", D_METHOD("get_building_info_start_date_key"), &GameSingleton::get_building_info_start_date_key);
ClassDB::bind_static_method("GameSingleton", D_METHOD("get_building_info_end_date_key"), &GameSingleton::get_building_info_end_date_key);
ClassDB::bind_static_method("GameSingleton", D_METHOD("get_building_info_expansion_progress_key"), &GameSingleton::get_building_info_expansion_progress_key);

ClassDB::bind_static_method("GameSingleton", D_METHOD("get_piechart_info_size_key"), &GameSingleton::get_piechart_info_size_key);
ClassDB::bind_static_method("GameSingleton", D_METHOD("get_piechart_info_colour_key"), &GameSingleton::get_piechart_info_colour_key);

ClassDB::bind_static_method("GameSingleton", D_METHOD("draw_pie_chart", "image", "stopAngles", "colours", "radius",
"shadow_displacement", "shadow_tightness", "shadow_radius", "shadow_thickness",
"trim_colour", "trim_size", "gradient_falloff", "gradient_base",
"donut", "donut_inner_trim", "donut_inner_radius"), &GameSingleton::draw_pie_chart);
}

void GameSingleton::draw_pie_chart(Ref<Image> image,
Array const& stopAngles, Array const& colours, float radius,
Vector2 shadow_displacement, float shadow_tightness, float shadow_radius, float shadow_thickness,
Color trim_colour, float trim_size, float gradient_falloff, float gradient_base,
bool donut, bool donut_inner_trim, float donut_inner_radius) {

OpenVic::draw_pie_chart(image, stopAngles, colours, radius, shadow_displacement, shadow_tightness, shadow_radius, shadow_thickness,
trim_colour, trim_size, gradient_falloff, gradient_base,
donut, donut_inner_trim, donut_inner_radius);
}

GameSingleton* GameSingleton::get_singleton() {
Expand Down Expand Up @@ -153,11 +172,25 @@ Error GameSingleton::_load_hardcoded_defines() {
}
return HIGH_ALPHA_VALUE | val;
}
return HIGH_ALPHA_VALUE;
return NULL_COLOUR;
} },
{ "mapmode_population",
[](Map const& map, Province const& province) -> colour_t {
return HIGH_ALPHA_VALUE | (fraction_to_colour_byte(province.get_total_population(), map.get_highest_province_population() + 1, 0.1f, 1.0f) << 8);
} },
{ "mapmode_culture",
[](Map const& map, Province const& province) -> colour_t {
distribution_t const& cultures = province.get_culture_distribution();
if (!cultures.empty()) {
// This breaks if replaced with distribution_t::value_type, something
// about operator=(volatile const&) being deleted.
std::pair<HasIdentifierAndColour const*, float> culture = *cultures.begin();
for (distribution_t::value_type const p : cultures) {
if (p.second > culture.second) culture = p;
}
return HIGH_ALPHA_VALUE | culture.first->get_colour();
}
return NULL_COLOUR;
} }
};
for (mapmode_t const& mapmode : mapmodes)
Expand Down Expand Up @@ -208,6 +241,18 @@ StringName const& GameSingleton::get_province_info_total_population_key() {
static const StringName key = "total_population";
return key;
}
StringName const& GameSingleton::get_province_info_pop_types_key() {
static const StringName key = "pop_types";
return key;
}
StringName const& GameSingleton::get_province_info_pop_ideologies_key() {
static const StringName key = "pop_ideologies";
return key;
}
StringName const& GameSingleton::get_province_info_pop_cultures_key() {
static const StringName key = "pop_cultures";
return key;
}
StringName const& GameSingleton::get_province_info_rgo_key() {
static const StringName key = "rgo";
return key;
Expand Down Expand Up @@ -242,6 +287,26 @@ StringName const& GameSingleton::get_building_info_expansion_progress_key() {
return key;
}

StringName const& GameSingleton::get_piechart_info_size_key() {
static const StringName key = "size";
return key;
}
StringName const& GameSingleton::get_piechart_info_colour_key() {
static const StringName key = "colour";
return key;
}

Dictionary GameSingleton::_distribution_to_dictionary(distribution_t const& dist) const {
Dictionary dict;
for (distribution_t::value_type const& p : dist) {
Dictionary sub_dict;
sub_dict[get_piechart_info_size_key()] = p.second;
sub_dict[get_piechart_info_colour_key()] = to_godot_color(p.first->get_colour());
dict[std_to_godot_string(p.first->get_identifier())] = sub_dict;
}
return dict;
}

Dictionary GameSingleton::get_province_info_from_index(int32_t index) const {
Province const* province = game_manager.map.get_province_by_index(index);
if (province == nullptr) return {};
Expand All @@ -257,6 +322,12 @@ Dictionary GameSingleton::get_province_info_from_index(int32_t index) const {

ret[get_province_info_life_rating_key()] = province->get_life_rating();
ret[get_province_info_total_population_key()] = province->get_total_population();
distribution_t const& pop_types = province->get_pop_type_distribution();
if (!pop_types.empty()) ret[get_province_info_pop_types_key()] = _distribution_to_dictionary(pop_types);
//distribution_t const& ideologies = province->get_ideology_distribution();
//if (!ideologies.empty()) ret[get_province_info_pop_ideologies_key()] = _distribution_to_dictionary(ideologies);
distribution_t const& cultures = province->get_culture_distribution();
if (!cultures.empty()) ret[get_province_info_pop_cultures_key()] = _distribution_to_dictionary(cultures);

std::vector<Building> const& buildings = province->get_buildings();
if (!buildings.empty()) {
Expand Down
18 changes: 16 additions & 2 deletions extension/src/GameSingleton.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@
#include "openvic/GameManager.hpp"

namespace OpenVic {
struct TerrainVariant : HasIdentifier, HasColour {
struct TerrainVariant : HasIdentifierAndColour {
friend class GameSingleton;

private:
const godot::Ref<godot::Image> image;

TerrainVariant(std::string const& new_identfier, colour_t new_colour,
TerrainVariant(const std::string_view new_identfier, colour_t new_colour,
godot::Ref<godot::Image> const& new_image);
public:
static constexpr size_t MAX_INDEX = 1 << (8 * sizeof(Map::terrain_t));
Expand Down Expand Up @@ -64,10 +64,18 @@ namespace OpenVic {
godot::Error _update_colour_image();
void _on_state_updated();

godot::Dictionary _distribution_to_dictionary(distribution_t const& dist) const;

protected:
static void _bind_methods();

public:
static void draw_pie_chart(godot::Ref<godot::Image> image,
godot::Array const& stopAngles, godot::Array const& colours, float radius,
godot::Vector2 shadow_displacement, float shadow_tightness, float shadow_radius, float shadow_thickness,
godot::Color trim_colour, float trim_size, float gradient_falloff, float gradient_base,
bool donut, bool donut_inner_trim, float donut_inner_radius);

static GameSingleton* get_singleton();

GameSingleton();
Expand Down Expand Up @@ -106,6 +114,9 @@ namespace OpenVic {
static godot::StringName const& get_province_info_region_key();
static godot::StringName const& get_province_info_life_rating_key();
static godot::StringName const& get_province_info_total_population_key();
static godot::StringName const& get_province_info_pop_types_key();
static godot::StringName const& get_province_info_pop_ideologies_key();
static godot::StringName const& get_province_info_pop_cultures_key();
static godot::StringName const& get_province_info_rgo_key();
static godot::StringName const& get_province_info_buildings_key();

Expand All @@ -116,6 +127,9 @@ namespace OpenVic {
static godot::StringName const& get_building_info_end_date_key();
static godot::StringName const& get_building_info_expansion_progress_key();

static godot::StringName const& get_piechart_info_size_key();
static godot::StringName const& get_piechart_info_colour_key();

/* Get info to display in Province Overview Panel, packaged in
* a Dictionary using the StringNames above as keys.
*/
Expand Down
80 changes: 40 additions & 40 deletions extension/src/LoadGameCompatibility.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,57 +17,57 @@ Error GameSingleton::_load_province_identifier_file_compatibility_mode(String co
Error err = FileAccess::get_open_error();
if (err != OK || file.is_null()) {
UtilityFunctions::push_error("Failed to load compatibility mode province identifier file: ", file_path);
return err == OK ? FAILED : err;
}

int line_number = 0;
while (!file->eof_reached()) {
const PackedStringArray line = file->get_csv_line(";");
line_number++;
if (err == OK) err = FAILED;
} else {
int line_number = 0;
while (!file->eof_reached()) {
const PackedStringArray line = file->get_csv_line(";");
line_number++;

if (line.is_empty() || (line.size() == 1 && line[0].is_empty()))
continue;
if (line.is_empty() || (line.size() == 1 && line[0].is_empty()))
continue;

if (line_number < 2) continue; // skip header line
index_t id = NULL_INDEX;
colour_t colour = NULL_COLOUR;
if (line.size() > 0) {
if (line[0].is_empty()) {
id = game_manager.map.get_province_count() + 1;
} else if (line[0].is_valid_int()) {
const int64_t val = line[0].to_int();
if (val > NULL_INDEX && val <= MAX_INDEX) id = val;
}
for (int i = 1; i < 4; ++i) {
if (line.size() > i) {
if (line[i].is_valid_int()) {
const int64_t int_val = line[i].to_int();
if (int_val >= NULL_COLOUR && int_val <= FULL_COLOUR) {
colour = (colour << 8) | int_val;
continue;
}
} else if (line[i].is_valid_float()) {
const double double_val = line[i].to_float();
if (std::trunc(double_val) == double_val) {
const int64_t int_val = double_val;
if (line_number < 2) continue; // skip header line
index_t id = NULL_INDEX;
colour_t colour = NULL_COLOUR;
if (line.size() > 0) {
if (line[0].is_empty()) {
id = game_manager.map.get_province_count() + 1;
} else if (line[0].is_valid_int()) {
const int64_t val = line[0].to_int();
if (val > NULL_INDEX && val <= MAX_INDEX) id = val;
}
for (int i = 1; i < 4; ++i) {
if (line.size() > i) {
if (line[i].is_valid_int()) {
const int64_t int_val = line[i].to_int();
if (int_val >= NULL_COLOUR && int_val <= FULL_COLOUR) {
colour = (colour << 8) | int_val;
continue;
}
} else if (line[i].is_valid_float()) {
const double double_val = line[i].to_float();
if (std::trunc(double_val) == double_val) {
const int64_t int_val = double_val;
if (int_val >= NULL_COLOUR && int_val <= FULL_COLOUR) {
colour = (colour << 8) | int_val;
continue;
}
}
}
}
colour = NULL_COLOUR;
break;
}
colour = NULL_COLOUR;
break;
}
if (id == NULL_INDEX || colour == NULL_COLOUR) {
UtilityFunctions::push_error("Invalid province ID-colour entry \"", line, "\" on line ", line_number, " in file: ", file_path);
err = FAILED;
continue;
}
static const std::string province_prefix = "PROV";
if (game_manager.map.add_province(province_prefix + std::to_string(id), colour) != SUCCESS) err = FAILED;
}
if (id == NULL_INDEX || colour == NULL_COLOUR) {
UtilityFunctions::push_error("Invalid province ID-colour entry \"", line, "\" on line ", line_number, " in file: ", file_path);
err = FAILED;
continue;
}
static const std::string province_prefix = "PROV";
if (game_manager.map.add_province(province_prefix + std::to_string(id), colour) != SUCCESS) err = FAILED;
}
game_manager.map.lock_provinces();
return err;
Expand Down
12 changes: 8 additions & 4 deletions extension/src/LoadGameOpenVic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,11 @@ Error GameSingleton::_parse_region_entry(String const& identifier, Variant const
UtilityFunctions::push_error("Invalid province list for region \"", identifier, "\": ", entry);
return FAILED;
}
return ERR(game_manager.map.add_region(godot_to_std_string(identifier), province_identifiers));
std::vector<std::string_view> province_identifier_views;
for (std::string const& str : province_identifiers) {
province_identifier_views.push_back(str);
}
return ERR(game_manager.map.add_region(godot_to_std_string(identifier), province_identifier_views));
}

Error GameSingleton::_load_region_file(String const& file_path) {
Expand Down Expand Up @@ -271,7 +275,7 @@ Error GameSingleton::_load_map_images(String const& province_image_path, String

// Generate interleaved province and terrain ID image
if (game_manager.map.generate_province_shape_image(province_dims.x, province_dims.y, province_image->get_data().ptr(),
terrain_image->get_data().ptr(), terrain_variant_map) != SUCCESS) err = FAILED;
terrain_image->get_data().ptr(), terrain_variant_map, true) != SUCCESS) err = FAILED;

static constexpr int32_t GPU_DIM_LIMIT = 0x3FFF;
// For each dimension of the image, this finds the small number of equal subdivisions required get the individual texture dims under GPU_DIM_LIMIT
Expand Down Expand Up @@ -364,8 +368,8 @@ Error GameSingleton::_parse_good_entry(String const& identifier, Variant const&
if (var_overseas_maintenance.get_type() == Variant::BOOL) overseas_maintenance = var_overseas_maintenance;
else UtilityFunctions::push_error("Invalid good overseas maintenance bool value for ", identifier, ": ", var_overseas_maintenance);

return ERR(game_manager.good_manager.add_good(godot_to_std_string(identifier), godot_to_std_string(category),
colour, base_price, default_available, tradeable, currency, overseas_maintenance));
return ERR(game_manager.good_manager.add_good(godot_to_std_string(identifier), colour, godot_to_std_string(category),
base_price, default_available, tradeable, currency, overseas_maintenance));
}

Error GameSingleton::_load_goods(String const& defines_path, String const& icons_dir_path) {
Expand Down
Loading

0 comments on commit aa9961b

Please sign in to comment.