Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,4 +69,6 @@ Every time you add something to the GDExtension you need to add to the class ref
3. Write documentation in the style of Godot, see [Godot's Writing Documentation: Class Reference Guides](https://docs.godotengine.org/en/stable/contributing/documentation/index.html#class-reference-guides).
4. Build with `scons`.

Windows note: doctool may not work in powershell/vscode terminal use command prompt directly.

If you change anything that causes new behavior in the GDExtension you should also change the corresponding class reference documentation.
2 changes: 1 addition & 1 deletion extension/deps/openvic-simulation
109 changes: 61 additions & 48 deletions extension/src/openvic-extension/classes/GFXPieChartTexture.hpp
Original file line number Diff line number Diff line change
@@ -1,30 +1,34 @@
#pragma once

#include <cstddef>
#include <functional>
#include <span>
#include <type_traits>

#include <godot_cpp/classes/image_texture.hpp>

#include <openvic-simulation/core/template/Concepts.hpp>
#include <openvic-simulation/interface/GFXSprite.hpp>
#include <openvic-simulation/types/Colour.hpp>
#include <openvic-simulation/types/ConstructorTags.hpp>
#include <openvic-simulation/types/IndexedFlatMap.hpp>
#include <openvic-simulation/types/FixedVector.hpp>
#include <openvic-simulation/utility/Logger.hpp>

#include "openvic-extension/core/Convert.hpp"
#include "openvic-extension/utility/AsFloat.hpp"
#include "openvic-extension/utility/AsReferenceWrapper.hpp"
#include "openvic-extension/utility/MapHelpers.hpp"
#include "openvic-simulation/core/template/Concepts.hpp"

namespace OpenVic {
template<typename MapType>
concept IsPieChartDistribution = (
/* tsl::ordered_map<KeyType const*, ValueType>, KeyType derived from HasIdentifierAndColour */
specialization_of<MapType, tsl::ordered_map>
/* IndexedFlatMap<KeyType, ValueType>, KeyType derived from HasIdentifierAndColour */
|| specialization_of<MapType, IndexedFlatMap>
)
&& has_get_identifier_and_colour<std::remove_pointer_t<map_key_t<MapType>>>
&& (
requires { static_cast<float>(std::declval<map_value_t<MapType>>()); }
template<typename T>
concept IsPieChartKey = has_get_identifier_and_colour<std::remove_pointer_t<T>>;
template<typename T>
concept IsPieChartValue = (
requires { static_cast<float>(std::declval<T>()); }
|| (
is_strongly_typed<map_value_t<MapType>>
&& requires { static_cast<float>(type_safe::get(std::declval<map_value_t<MapType>>())); }
is_strongly_typed<T>
&& requires { static_cast<float>(type_safe::get(std::declval<T>())); }
)
);

Expand Down Expand Up @@ -56,52 +60,38 @@ namespace OpenVic {
public:
/* Generate slice data from a distribution of objects satisfying HasGetIdentifierAndGetColour, sorted by their weight.
* The resulting Array of Dictionaries can be used as an argument for set_slices_array. */
template<IsPieChartDistribution MapType>
template<IsPieChartKey KeyType, IsPieChartValue ValueType>
static godot_pie_chart_data_t distribution_to_slices_array(
MapType const& distribution,
std::span<std::add_const_t<KeyType>> keys,
std::span<std::add_const_t<ValueType>> values,
NodeTools::Functor<
// return tooltip; args: key const*, identifier, weight, total weight
godot::String, std::remove_pointer_t<map_key_t<MapType>> const*, godot::String const&, float, float
godot::String, std::reference_wrapper<std::add_const_t<std::remove_pointer_t<KeyType>>>, godot::String const&, float, float
> auto make_tooltip,
godot::String const& identifier_suffix = {}
) {
using namespace godot;
assert(keys.size() == values.size());
using key_t = std::reference_wrapper<std::add_const_t<std::remove_pointer_t<KeyType>>>;
using entry_t = std::pair<
key_t,
float
>;

using key_type = std::remove_pointer_t<map_key_t<MapType>>;
using entry_t = std::pair<key_type const*, float>;

std::vector<entry_t> sorted_distribution;
if constexpr (specialization_of<MapType, IndexedFlatMap>) {
sorted_distribution.reserve(distribution.get_count());
} else {
sorted_distribution.reserve(distribution.size());
}
memory::FixedVector<entry_t> sorted_distribution { create_empty, keys.size() };

float total_weight = 0.0f;

for (auto [key_ref_or_ptr, non_float_value] : distribution) {
key_type const* key_ptr;
if constexpr (std::same_as<decltype(key_ptr), decltype(key_ref_or_ptr)>) {
key_ptr = key_ref_or_ptr;
} else {
key_ptr = &key_ref_or_ptr;
}

float value;
if constexpr (is_strongly_typed<decltype(non_float_value)>) {
value = static_cast<float>(type_safe::get(non_float_value));
} else {
value = static_cast<float>(non_float_value);
}
for (size_t i = 0; i < keys.size(); ++i) {
key_t key = as_reference_wrapper(keys[i]);
float value = as_float(values[i]);

if (value > 0.0f) {
sorted_distribution.emplace_back(key_ptr, value);
sorted_distribution.emplace_back(key, value);

total_weight += value;
} else if (value < 0.0f) {
spdlog::error_s(
"Negative distribution value {} for key \"{}\"",
value, *key_ptr
value, key.get()
);
}
}
Expand All @@ -114,31 +104,54 @@ namespace OpenVic {
std::sort(
sorted_distribution.begin(), sorted_distribution.end(),
[](entry_t const& lhs, entry_t const& rhs) -> bool {
return lhs.first < rhs.first;
return lhs.first.get().get_identifier() < rhs.first.get().get_identifier();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What was the original logic here?
Pointer sorting?
I don't think all values had an index to sort by.

}
);

godot_pie_chart_data_t array;
ERR_FAIL_COND_V(array.resize(sorted_distribution.size()) != OK, {});
ERR_FAIL_COND_V(array.resize(sorted_distribution.size()) != godot::OK, {});

for (size_t index = 0; index < array.size(); ++index) {
auto const& [key, value] = sorted_distribution[index];

String identifier = convert_to<String>(key->get_identifier());
godot::String identifier = convert_to<godot::String>(key.get().get_identifier());
identifier += identifier_suffix;

Dictionary sub_dict;
godot::Dictionary sub_dict;

sub_dict[_slice_tooltip_key()] = make_tooltip(key, identifier, value, total_weight);
sub_dict[_slice_identifier_key()] = std::move(identifier);
sub_dict[_slice_colour_key()] = convert_to<Color>(key->get_colour());
sub_dict[_slice_colour_key()] = convert_to<godot::Color>(key.get().get_colour());
sub_dict[_slice_weight_key()] = value;

array[index] = std::move(sub_dict);
}
return array;
}

// adapter for ordered maps
template<typename MapType>
static godot_pie_chart_data_t distribution_to_slices_array(
MapType const& distribution,
NodeTools::Functor<
godot::String, std::reference_wrapper<std::add_const_t<std::remove_pointer_t<map_key_t<MapType>>>>,
godot::String const&, float, float
> auto make_tooltip,
godot::String const& identifier_suffix = {}
) {
memory::FixedVector<map_key_t<MapType>> keys { create_empty, distribution.size() };
memory::FixedVector<map_value_t<MapType>> values { create_empty, distribution.size() };
for (auto const& [k,v] : distribution) {
keys.emplace_back(k);
values.emplace_back(v);
}
return distribution_to_slices_array<map_key_t<MapType>, map_value_t<MapType>>(
keys, values,
make_tooltip,
identifier_suffix
);
}

protected:
static void _bind_methods();

Expand Down
4 changes: 3 additions & 1 deletion extension/src/openvic-extension/core/Convert.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <concepts>
#include <string>
#include <string_view>
#include <type_traits>

#include <godot_cpp/core/defs.hpp>
#include <godot_cpp/variant/char_string.hpp>
Expand All @@ -11,10 +12,11 @@
#include <godot_cpp/variant/vector2.hpp>
#include <godot_cpp/variant/vector2i.hpp>

#include <openvic-simulation/core/memory/String.hpp>
#include <openvic-simulation/core/template/Concepts.hpp>
#include <openvic-simulation/core/Typedefs.hpp>
#include <openvic-simulation/types/Colour.hpp>
#include <openvic-simulation/types/Vector.hpp>
#include <openvic-simulation/utility/Containers.hpp>

namespace OpenVic {
template<typename To, typename From>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,13 @@
#include <godot_cpp/variant/packed_string_array.hpp>
#include <godot_cpp/variant/utility_functions.hpp>

#include <openvic-simulation/core/memory/String.hpp>
#include <openvic-simulation/core/memory/Vector.hpp>
#include <openvic-simulation/dataloader/ModManager.hpp>
#include <openvic-simulation/DefinitionManager.hpp>
#include <openvic-simulation/map/Crime.hpp>
#include <openvic-simulation/types/fixed_point/Math.hpp>
#include <openvic-simulation/types/TypedIndices.hpp>
#include <openvic-simulation/utility/Containers.hpp>
#include <openvic-simulation/utility/Logger.hpp>

#include "openvic-extension/core/Convert.hpp"
Expand Down Expand Up @@ -679,7 +681,7 @@ Error GameSingleton::_load_flag_sheet() {
ERR_FAIL_COND_V(flag_images.size() != flag_sheet_count, FAILED);

/* Calculate the width that will make the sheet as close to a square as possible (taking flag dimensions into account.) */
flag_sheet_dims.x = (fixed_point_t { static_cast<int32_t>(flag_images.size()) } * flag_dims.y / flag_dims.x).sqrt().ceil<int32_t>();
flag_sheet_dims.x = fp::sqrt(fixed_point_t { static_cast<int32_t>(flag_images.size()) } * flag_dims.y / flag_dims.x).ceil<int32_t>();

/* Calculated corresponding height (rounded up). */
flag_sheet_dims.y = (static_cast<int32_t>(flag_images.size()) + flag_sheet_dims.x - 1) / flag_sheet_dims.x;
Expand Down Expand Up @@ -756,6 +758,8 @@ Error GameSingleton::load_defines_compatibility_mode(PackedStringArray const& mo
err = FAILED;
}

MenuSingleton::get_singleton()->initialise();

return err;
}

Expand Down
37 changes: 21 additions & 16 deletions extension/src/openvic-extension/singletons/MapItemSingleton.cpp
Original file line number Diff line number Diff line change
@@ -1,27 +1,30 @@
#include "MapItemSingleton.hpp"

#include <cstdint>

#include <type_safe/strong_typedef.hpp>

#include <openvic-simulation/utility/Containers.hpp>
#include <godot_cpp/core/error_macros.hpp>
#include <godot_cpp/variant/packed_int32_array.hpp>
#include <godot_cpp/variant/packed_vector2_array.hpp>
#include <godot_cpp/variant/typed_array.hpp>
#include <godot_cpp/variant/vector2.hpp>

#include <openvic-simulation/core/memory/SmartPtr.hpp>
#include <openvic-simulation/country/CountryDefinition.hpp>
#include <openvic-simulation/country/CountryInstance.hpp>
#include <openvic-simulation/DefinitionManager.hpp>
#include <openvic-simulation/economy/BuildingType.hpp>
#include <openvic-simulation/interface/GFXObject.hpp>
#include <openvic-simulation/map/ProvinceDefinition.hpp>
#include <openvic-simulation/map/ProvinceInstance.hpp>
#include <openvic-simulation/map/State.hpp>
#include <openvic-simulation/types/Vector.hpp>

#include "godot_cpp/core/error_macros.hpp"
#include "godot_cpp/variant/packed_int32_array.hpp"
#include "godot_cpp/variant/packed_vector2_array.hpp"
#include "godot_cpp/variant/typed_array.hpp"
#include "godot_cpp/variant/vector2.hpp"
#include "openvic-extension/core/Convert.hpp"
#include "openvic-extension/singletons/GameSingleton.hpp"
#include "openvic-extension/core/Bind.hpp"
#include "openvic-extension/utility/Utilities.hpp"
#include "openvic-simulation/country/CountryDefinition.hpp"
#include "openvic-simulation/country/CountryInstance.hpp"
#include "openvic-simulation/DefinitionManager.hpp"
#include "openvic-simulation/economy/BuildingType.hpp"
#include "openvic-simulation/interface/GFXObject.hpp"
#include "openvic-simulation/map/ProvinceDefinition.hpp"
#include "openvic-simulation/map/ProvinceInstance.hpp"
#include "openvic-simulation/map/State.hpp"
#include "openvic-simulation/types/Vector.hpp"

using namespace godot;
using namespace OpenVic;
Expand Down Expand Up @@ -164,7 +167,9 @@ PackedVector2Array MapItemSingleton::get_capital_positions() const {

PackedVector2Array billboard_pos {};

billboard_pos.resize(country_instance_manager.get_country_instance_by_definition().get_count());
billboard_pos.resize(type_safe::get(
country_instance_manager.get_country_instances().size()
));

int64_t index = 0;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
#pragma once

#include <cstdint>

#include <godot_cpp/classes/object.hpp>
#include <godot_cpp/variant/packed_byte_array.hpp>

#include <openvic-simulation/interface/GFXObject.hpp>
#include <openvic-simulation/types/OrderedContainers.hpp>

Expand Down
Loading
Loading