Skip to content

Commit

Permalink
Add map billboards
Browse files Browse the repository at this point in the history
Billboards for nation capitals and mapmodes
  • Loading branch information
Nemrav committed Nov 30, 2024
1 parent 745f337 commit 68ba1b2
Show file tree
Hide file tree
Showing 14 changed files with 623 additions and 5 deletions.
6 changes: 4 additions & 2 deletions extension/src/openvic-extension/classes/GUILabel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "openvic-extension/singletons/AssetManager.hpp"
#include "openvic-extension/utility/ClassBindings.hpp"
#include "openvic-extension/utility/Utilities.hpp"
#include "openvic-simulation/types/TextFormat.hpp"

using namespace OpenVic;
using namespace godot;
Expand Down Expand Up @@ -241,12 +242,13 @@ Error GUILabel::set_gui_text(GUI::Text const* new_gui_text, GFX::Font::colour_co

set_text(Utilities::std_to_godot_string(gui_text->get_text()));

using enum GUI::AlignedElement::format_t;
static const ordered_map<GUI::AlignedElement::format_t, HorizontalAlignment> format_map {
using enum text_format_t;
static const ordered_map<text_format_t, HorizontalAlignment> format_map {
{ left, HORIZONTAL_ALIGNMENT_LEFT },
{ centre, HORIZONTAL_ALIGNMENT_CENTER },
{ right, HORIZONTAL_ALIGNMENT_RIGHT }
};

const decltype(format_map)::const_iterator it = format_map.find(gui_text->get_format());
set_horizontal_alignment(it != format_map.end() ? it->second : HORIZONTAL_ALIGNMENT_LEFT);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "openvic-extension/utility/ClassBindings.hpp"
#include "openvic-extension/utility/UITools.hpp"
#include "openvic-extension/utility/Utilities.hpp"
#include "openvic-simulation/types/TextFormat.hpp"

using namespace OpenVic;
using namespace godot;
Expand All @@ -30,7 +31,7 @@ Error GUIOverlappingElementsBox::_update_child_positions() {

float starting_x = 0.0f;
Error err = OK;
using enum GUI::AlignedElement::format_t;
using enum text_format_t;
switch (gui_overlapping_elements_box->get_format()) {
case left:
break;
Expand Down
10 changes: 10 additions & 0 deletions extension/src/openvic-extension/register_types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,19 @@
#include "openvic-extension/singletons/Checksum.hpp"
#include "openvic-extension/singletons/GameSingleton.hpp"
#include "openvic-extension/singletons/LoadLocalisation.hpp"
#include "openvic-extension/singletons/MapItemSingleton.hpp"
#include "openvic-extension/singletons/MenuSingleton.hpp"
#include "openvic-extension/singletons/ModelSingleton.hpp"
#include "openvic-extension/singletons/SoundSingleton.hpp"


using namespace godot;
using namespace OpenVic;

static Checksum* _checksum_singleton = nullptr;
static LoadLocalisation* _load_localisation = nullptr;
static GameSingleton* _game_singleton = nullptr;
static MapItemSingleton* _map_item_singleton = nullptr;
static MenuSingleton* _menu_singleton = nullptr;
static ModelSingleton* _model_singleton = nullptr;
static AssetManager* _asset_manager_singleton = nullptr;
Expand All @@ -56,6 +59,10 @@ void initialize_openvic_types(ModuleInitializationLevel p_level) {
_game_singleton = memnew(GameSingleton);
Engine::get_singleton()->register_singleton("GameSingleton", GameSingleton::get_singleton());

ClassDB::register_class<MapItemSingleton>();
_map_item_singleton = memnew(MapItemSingleton);
Engine::get_singleton()->register_singleton("MapItemSingleton", MapItemSingleton::get_singleton());

ClassDB::register_class<MenuSingleton>();
_menu_singleton = memnew(MenuSingleton);
Engine::get_singleton()->register_singleton("MenuSingleton", MenuSingleton::get_singleton());
Expand Down Expand Up @@ -117,6 +124,9 @@ void uninitialize_openvic_types(ModuleInitializationLevel p_level) {
Engine::get_singleton()->unregister_singleton("GameSingleton");
memdelete(_game_singleton);

Engine::get_singleton()->unregister_singleton("MapItemSingleton");
memdelete(_map_item_singleton);

Engine::get_singleton()->unregister_singleton("MenuSingleton");
memdelete(_menu_singleton);

Expand Down
229 changes: 229 additions & 0 deletions extension/src/openvic-extension/singletons/MapItemSingleton.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@


//billboards, projections, and progress bar

#include "MapItemSingleton.hpp"
#include <string_view>

#include <godot_cpp/variant/utility_functions.hpp>

#include <openvic-simulation/map/ProvinceInstance.hpp>

#include "openvic-extension/singletons/GameSingleton.hpp"
#include "openvic-extension/utility/ClassBindings.hpp"
#include "openvic-extension/utility/Utilities.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/DefinitionManager.hpp"
#include "openvic-simulation/country/CountryDefinition.hpp"
#include "openvic-simulation/country/CountryInstance.hpp"
#include "openvic-simulation/interface/GFXObject.hpp"
#include "openvic-simulation/map/ProvinceDefinition.hpp"
#include "openvic-simulation/types/Vector.hpp"

using namespace godot;
using namespace OpenVic;

void MapItemSingleton::_bind_methods() {
OV_BIND_METHOD(MapItemSingleton::get_billboards);
OV_BIND_METHOD(MapItemSingleton::get_province_positions);
OV_BIND_METHOD(MapItemSingleton::get_province_count);
OV_BIND_METHOD(MapItemSingleton::get_capital_count);
OV_BIND_METHOD(MapItemSingleton::get_capital_positions);
OV_BIND_METHOD(MapItemSingleton::get_crime_icons);
OV_BIND_METHOD(MapItemSingleton::get_rgo_icons);
}

MapItemSingleton* MapItemSingleton::get_singleton() {
return singleton;
}

MapItemSingleton::MapItemSingleton() {
ERR_FAIL_COND(singleton != nullptr);
singleton = this;
}

MapItemSingleton::~MapItemSingleton() {
ERR_FAIL_COND(singleton != this);
singleton = nullptr;
}

// Get the billboard object from the loaded objects

GFX::Billboard const* MapItemSingleton::get_billboard(std::string_view name, bool error_on_fail) const {
GameSingleton const* game_singleton = GameSingleton::get_singleton();
ERR_FAIL_NULL_V(game_singleton, nullptr);
DefinitionManager const* definition_manager = &game_singleton->get_definition_manager();
ERR_FAIL_NULL_V(definition_manager, nullptr);

GFX::Billboard const* billboard =
definition_manager->get_ui_manager().get_cast_object_by_identifier<GFX::Billboard>(name);

if (error_on_fail) {
//ERR_FAIL_NULL_V_MSG(billboard, nullptr, vformat("Failed to find billboard \"%s\"", Utilities::std_to_godot_string(name)));
ERR_FAIL_NULL_V_MSG(billboard, nullptr, "Failed to find billboard inner");
}

return billboard;
}

// repackage the billboard object into a godot dictionnary for the Billboard manager to work with
bool MapItemSingleton::add_billboard_dict(std::string_view name, TypedArray<Dictionary>& billboard_dict_array) {

static const StringName name_key = "name";
static const StringName texture_key = "texture";
static const StringName scale_key = "scale";
static const StringName noOfFrames_key = "noFrames";
//TODO: might need font, font_size, and offset keys in the future


GFX::Billboard const* billboard = get_billboard(name,false);

ERR_FAIL_NULL_V_MSG(
billboard, false, "Failed to find billboard"
);

Dictionary dict;

dict[name_key] = Utilities::std_to_godot_string(billboard->get_name());
dict[texture_key] = Utilities::std_to_godot_string(billboard->get_texture_file());
dict[scale_key] = billboard->get_scale().to_float();
dict[noOfFrames_key] = billboard->get_no_of_frames();

billboard_dict_array.push_back(dict);

return true;
}


//get an array of all the billboard dictionnaries
TypedArray<Dictionary> MapItemSingleton::get_billboards(){
GameSingleton const* game_singleton = GameSingleton::get_singleton();
ERR_FAIL_NULL_V(game_singleton, {});

DefinitionManager const* definition_manager = &game_singleton->get_definition_manager();
ERR_FAIL_NULL_V(definition_manager, TypedArray<Dictionary>());

TypedArray<Dictionary> ret;

for (std::unique_ptr<GFX::Object> const& obj : definition_manager->get_ui_manager().get_objects()) {
if (obj->is_type<GFX::Billboard>()) {
add_billboard_dict(obj->get_name(), ret);
}
}

return ret;
}

//dont use this, it includes water provinces
int MapItemSingleton::get_province_count(){
GameSingleton const* game_singleton = GameSingleton::get_singleton();
ERR_FAIL_NULL_V(game_singleton, 0);

DefinitionManager const* definition_manager = &game_singleton->get_definition_manager();
ERR_FAIL_NULL_V(definition_manager, 0);

return definition_manager->get_map_definition().get_province_definition_count();
}

PackedVector2Array MapItemSingleton::get_province_positions(){
GameSingleton const* game_singleton = GameSingleton::get_singleton();
ERR_FAIL_NULL_V(game_singleton, PackedVector2Array());

DefinitionManager const* definition_manager = &game_singleton->get_definition_manager();
ERR_FAIL_NULL_V(definition_manager, PackedVector2Array());

PackedVector2Array billboard_pos = PackedVector2Array();

int prov_count = definition_manager->get_map_definition().get_province_definition_count();

for(ProvinceDefinition const& prov : definition_manager->get_map_definition().get_province_definitions()){
if(prov.is_water()) continue; //billboards dont appear over water, skip

fvec2_t city_pos = prov.get_city_position();
Vector2 pos = Utilities::to_godot_fvec2(city_pos) / game_singleton->get_map_dims();
billboard_pos.push_back(pos);

}

return billboard_pos;
}

//includes non-existent countries, used for setting the billboard buffer size
int MapItemSingleton::get_capital_count(){
GameSingleton const* game_singleton = GameSingleton::get_singleton();
ERR_FAIL_NULL_V(game_singleton, 0);

InstanceManager const* instance_manager = game_singleton->get_instance_manager();
ERR_FAIL_NULL_V(instance_manager, 0);

return instance_manager->get_country_instance_manager().get_country_instance_count();
}

PackedVector2Array MapItemSingleton::get_capital_positions(){
GameSingleton const* game_singleton = GameSingleton::get_singleton();
ERR_FAIL_NULL_V(game_singleton, PackedVector2Array());

InstanceManager const* instance_manager = game_singleton->get_instance_manager();
ERR_FAIL_NULL_V(instance_manager, PackedVector2Array());

PackedVector2Array billboard_pos = PackedVector2Array();

for(CountryInstance const& country : instance_manager->get_country_instance_manager().get_country_instances()){
if(!country.exists()) continue; //skip non-existant countries

fvec2_t city_pos = country.get_capital()->get_province_definition().get_city_position();
Vector2 pos = Utilities::to_godot_fvec2(city_pos) / game_singleton->get_map_dims();
billboard_pos.push_back(pos);

}

return billboard_pos;
}

PackedInt32Array MapItemSingleton::get_crime_icons(){
GameSingleton const* game_singleton = GameSingleton::get_singleton();
ERR_FAIL_NULL_V(game_singleton, PackedInt32Array());

InstanceManager const* instance_manager = game_singleton->get_instance_manager();
ERR_FAIL_NULL_V(instance_manager, PackedInt32Array());

PackedInt32Array icons = PackedInt32Array();

for(ProvinceInstance const& prov_inst : instance_manager->get_map_instance().get_province_instances()){
ProvinceDefinition const* prov = &prov_inst.get_province_definition();
if(prov->is_water()) continue; //billboards dont appear over water, skip

icons.push_back(prov_inst.get_crime()->get_icon());
}

return icons;

}

PackedInt32Array MapItemSingleton::get_rgo_icons(){
GameSingleton const* game_singleton = GameSingleton::get_singleton();
ERR_FAIL_NULL_V(game_singleton, PackedInt32Array());

InstanceManager const* instance_manager = game_singleton->get_instance_manager();
ERR_FAIL_NULL_V(instance_manager, PackedInt32Array());

PackedInt32Array icons = PackedInt32Array();

for(ProvinceInstance const& prov_inst : instance_manager->get_map_instance().get_province_instances()){
ProvinceDefinition const* prov = &prov_inst.get_province_definition();
if(prov->is_water()) continue; //billboards dont appear over water, skip

icons.push_back(prov_inst.get_rgo_good()->get_index()+1);
}

return icons;

}


/*
TODO: National focus isn't implemented yet. It could be done at the country instance, or the province instance
*/
38 changes: 38 additions & 0 deletions extension/src/openvic-extension/singletons/MapItemSingleton.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#pragma once

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

//billboards, projections, and progress bar

namespace OpenVic {
class MapItemSingleton : public godot::Object {
GDCLASS(MapItemSingleton, godot::Object)

static inline MapItemSingleton* singleton = nullptr;

protected:
static void _bind_methods();

public:
static MapItemSingleton* get_singleton();

MapItemSingleton();
~MapItemSingleton();

private:
GFX::Billboard const* get_billboard(std::string_view name, bool error_on_fail = true) const;
bool add_billboard_dict(std::string_view name, godot::TypedArray<godot::Dictionary>& billboard_dict_array);
godot::TypedArray<godot::Dictionary> get_billboards();
int get_province_count();
godot::PackedVector2Array get_province_positions();
int get_capital_count();
godot::PackedVector2Array get_capital_positions();

godot::PackedInt32Array get_crime_icons();
godot::PackedInt32Array get_rgo_icons();

};

}
18 changes: 18 additions & 0 deletions game/src/Game/GameSession/BillboardCamera.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
extends Camera3D

@export var mapview:Node3D
var map_cam:Camera3D

#This subviewport setup exists so billboards will draw
#ontop of other scene objects (units)

# Called when the node enters the scene tree for the first time.
func _ready():
map_cam = mapview.get_child(0) as Camera3D
fov = map_cam.fov
near = map_cam.near
far = map_cam.far
keep_aspect = map_cam.keep_aspect

func _process(delta):
transform = map_cam.transform
Loading

0 comments on commit 68ba1b2

Please sign in to comment.