Skip to content

Commit

Permalink
add map projections
Browse files Browse the repository at this point in the history
  • Loading branch information
Nemrav committed Dec 17, 2024
1 parent 8e911c8 commit af0ba44
Show file tree
Hide file tree
Showing 6 changed files with 356 additions and 6 deletions.
78 changes: 76 additions & 2 deletions extension/src/openvic-extension/singletons/MapItemSingleton.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#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/utility_functions.hpp"
//#include "godot_cpp/variant/utility_functions.hpp"
#include "godot_cpp/variant/vector2.hpp"
#include "openvic-extension/singletons/GameSingleton.hpp"
#include "openvic-extension/utility/ClassBindings.hpp"
Expand All @@ -16,7 +16,7 @@
#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 "openvic-simulation/types/Vector.hpp"

using namespace godot;
using namespace OpenVic;
Expand All @@ -29,6 +29,8 @@ void MapItemSingleton::_bind_methods() {
OV_BIND_METHOD(MapItemSingleton::get_crime_icons);
OV_BIND_METHOD(MapItemSingleton::get_rgo_icons);
OV_BIND_METHOD(MapItemSingleton::get_national_focus_icons);
OV_BIND_METHOD(MapItemSingleton::get_projections);
OV_BIND_METHOD(MapItemSingleton::get_unit_position_by_province_index,{"index"});
}

MapItemSingleton* MapItemSingleton::get_singleton() {
Expand Down Expand Up @@ -102,6 +104,67 @@ TypedArray<Dictionary> MapItemSingleton::get_billboards() const {
return ret;
}


GFX::Projection const* MapItemSingleton::get_projection(std::string_view name, bool error_on_fail) const {
GameSingleton const* game_singleton = GameSingleton::get_singleton();
ERR_FAIL_NULL_V(game_singleton, nullptr);

GFX::Projection const* projection =
game_singleton->get_definition_manager().get_ui_manager().get_cast_object_by_identifier<GFX::Projection>(name);

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

return projection;
}

bool MapItemSingleton::add_projection_dict(std::string_view name, TypedArray<Dictionary>& projection_dict_array) const {

static const StringName name_key = "name";
static const StringName texture_key = "texture";
static const StringName size_key = "size";
static const StringName spin_key = "spin";
static const StringName expanding_key = "expanding";
static const StringName duration_key = "duration";
static const StringName additative_key = "additative";

GFX::Projection const* projection = get_projection(name, false);

ERR_FAIL_NULL_V_MSG(projection, false, vformat("Failed to find projection \"%s\"", Utilities::std_to_godot_string(name)));

Dictionary dict;

dict[name_key] = Utilities::std_to_godot_string(projection->get_name());
dict[texture_key] = Utilities::std_to_godot_string(projection->get_texture_file());
dict[size_key] = projection->get_size().to_float();
dict[spin_key] = projection->get_spin().to_float();
dict[expanding_key] = projection->get_expanding().to_float();
dict[duration_key] = projection->get_duration().to_float();
dict[additative_key] = projection->get_additative();

projection_dict_array.push_back(dict);

return true;
}

TypedArray<Dictionary> MapItemSingleton::get_projections() const {
GameSingleton const* game_singleton = GameSingleton::get_singleton();
ERR_FAIL_NULL_V(game_singleton, {});

TypedArray<Dictionary> ret;

for (std::unique_ptr<GFX::Object> const& obj : game_singleton->get_definition_manager().get_ui_manager().get_objects()) {
if (obj->is_type<GFX::Projection>()) {
add_projection_dict(obj->get_name(), ret);
}
}

return ret;
}

// We assume GameSingleton isn't null when this is being called
static Vector2 get_billboard_pos(ProvinceDefinition const& province) {
return Utilities::to_godot_fvec2(province.get_city_position()) / GameSingleton::get_singleton()->get_map_dims();
Expand Down Expand Up @@ -260,3 +323,14 @@ PackedByteArray MapItemSingleton::get_national_focus_icons() const {

return icons;
}


Vector2 MapItemSingleton::get_unit_position_by_province_index(int32_t province_index) const {
GameSingleton const* game_singleton = GameSingleton::get_singleton();
ERR_FAIL_NULL_V(game_singleton, {});

return Utilities::to_godot_fvec2(
game_singleton->get_definition_manager().get_map_definition()
.get_province_definition_by_index(province_index)->get_unit_position()
) / GameSingleton::get_singleton()->get_map_dims();
}
10 changes: 8 additions & 2 deletions extension/src/openvic-extension/singletons/MapItemSingleton.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@
#include <openvic-simulation/interface/GFXObject.hpp>
#include <openvic-simulation/types/OrderedContainers.hpp>

//billboards, projections, and progress bar
//for now though, only billboards
//billboards, projections, and progress bar (no progress bar yet)

namespace OpenVic {
class MapItemSingleton : public godot::Object {
Expand All @@ -27,12 +26,19 @@ namespace OpenVic {
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) const;
godot::TypedArray<godot::Dictionary> get_billboards() const;

GFX::Projection const* get_projection(std::string_view name, bool error_on_fail = true) const;
bool add_projection_dict(std::string_view name, godot::TypedArray<godot::Dictionary>& projection_dict_array) const;
godot::TypedArray<godot::Dictionary> get_projections() const;

godot::PackedVector2Array get_province_positions() const;
int32_t get_max_capital_count() const;
godot::PackedVector2Array get_capital_positions() const;

godot::PackedByteArray get_crime_icons() const;
godot::PackedByteArray get_rgo_icons() const;
godot::PackedByteArray get_national_focus_icons() const;

godot::Vector2 get_unit_position_by_province_index(int32_t province_index) const;
};
}
7 changes: 6 additions & 1 deletion game/src/Game/GameSession/MapView.gd
Original file line number Diff line number Diff line change
Expand Up @@ -225,9 +225,14 @@ func _unhandled_input(event : InputEvent) -> void:
elif event.is_action_pressed(_action_right_click):
if _mouse_over_viewport:
if _map_mesh.is_valid_uv_coord(_mouse_pos_map):
var province_index : int = GameSingleton.get_province_index_from_uv_coords(_mouse_pos_map)
var unit_position : Vector2 = MapItemSingleton.get_unit_position_by_province_index(province_index)
#print(unit_position)
#print(_map_to_world_coords(unit_position))
$ProjectionManager.add_move_marker(_map_to_world_coords(unit_position), randi_range(0,1))
# TODO - open diplomacy screen on province owner or viewed country if province has no owner
#Events.NationManagementScreens.open_nation_management_screen(NationManagement.Screen.DIPLOMACY)
GameSingleton.set_viewed_country_by_province_index(GameSingleton.get_province_index_from_uv_coords(_mouse_pos_map))
GameSingleton.set_viewed_country_by_province_index(province_index)
else:
print("Right-clicked outside the map!")
elif event.is_action_pressed(_action_drag):
Expand Down
29 changes: 28 additions & 1 deletion game/src/Game/GameSession/MapView.tscn
Original file line number Diff line number Diff line change
@@ -1,8 +1,30 @@
[gd_scene load_steps=8 format=3 uid="uid://dkehmdnuxih2r"]
[gd_scene load_steps=13 format=3 uid="uid://dkehmdnuxih2r"]

[ext_resource type="Script" path="res://src/Game/GameSession/MapView.gd" id="1_exccw"]
[ext_resource type="Shader" path="res://src/Game/GameSession/TerrainMap.gdshader" id="1_upocn"]
[ext_resource type="Script" path="res://src/Game/GameSession/MapText.gd" id="2_13bgq"]
[ext_resource type="Shader" path="res://src/Game/GameSession/Projection.gdshader" id="4_2f4io"]
[ext_resource type="Script" path="res://src/Game/GameSession/ProjectionManager.gd" id="5_h3t3v"]

[sub_resource type="ShaderMaterial" id="ShaderMaterial_0txs7"]
render_priority = 0
shader = ExtResource("4_2f4io")
shader_parameter/sizes = PackedFloat32Array()
shader_parameter/spin = null
shader_parameter/expanding = null
shader_parameter/duration = null
shader_parameter/additative = null
shader_parameter/time = 0.0
shader_parameter/projections = null

[sub_resource type="QuadMesh" id="QuadMesh_rxujm"]
material = SubResource("ShaderMaterial_0txs7")
orientation = 1

[sub_resource type="MultiMesh" id="MultiMesh_ncb3x"]
transform_format = 1
use_custom_data = true
mesh = SubResource("QuadMesh_rxujm")

[sub_resource type="ShaderMaterial" id="ShaderMaterial_tayeg"]
render_priority = 0
Expand Down Expand Up @@ -36,6 +58,10 @@ _map_text = NodePath("MapText")
transform = Transform3D(1, 0, 0, 0, 0.707107, 0.707107, 0, -0.707107, 0.707107, 0.25, 1.5, -2.75)
near = 0.01

[node name="ProjectionManager" type="MultiMeshInstance3D" parent="."]
multimesh = SubResource("MultiMesh_ncb3x")
script = ExtResource("5_h3t3v")

[node name="MapText" type="Node3D" parent="." node_paths=PackedStringArray("_map_view")]
script = ExtResource("2_13bgq")
_map_view = NodePath("..")
Expand All @@ -56,4 +82,5 @@ light_energy = 1.5
light_bake_mode = 0
sky_mode = 1

[connection signal="detailed_view_changed" from="." to="ProjectionManager" method="set_visible"]
[connection signal="detailed_view_changed" from="." to="MapText" method="set_visible"]
50 changes: 50 additions & 0 deletions game/src/Game/GameSession/Projection.gdshader
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
shader_type spatial;
render_mode unshaded;

uniform sampler2D projections[3] : source_color;
uniform float sizes[3];
uniform float spin[3];
uniform float expanding[3];
uniform float duration[3];
uniform bool additative[3]; //if true, black becomes a transparency colour
uniform float time = 0.0;

void vertex() {
COLOR = INSTANCE_CUSTOM;
uint type = uint(COLOR.x + 0.5);
float start_time = COLOR.y;

float rot = time*spin[type];
mat3 rotation_matrix = mat3(
vec3(cos(-rot), 0.0, sin(-rot)),
vec3(0.0, 1.0, 0.0),
vec3(-sin(-rot), 0.0, cos(-rot))
);
VERTEX.xyz *= rotation_matrix *
clamp(
expanding[type] * mod(time-start_time,3600.0),
0.0,
sizes[type]
);
}

void fragment() {
// Called for every pixel the material is visible on.
uint type = uint(COLOR.x + 0.5);
vec4 sample = texture(projections[type],UV);
ALBEDO.rgb = sample.rgb;

float start_time = COLOR.y;
//if time exceeded: 0.0, else 1.0
//This produces a nicer effect than vic2, shame we can't use it
//float is_finished = clamp(duration[type] - mod(time-start_time,3600.0),0.0,1.0);
float is_finished = ceil(clamp(duration[type] - mod(time-start_time,3600.0),0.0,1.0));
if(duration[type] == 0.0){
is_finished = 1.0;
}
//if additative, then black = transparent, otherwise use alpha
float add_tr = float(additative[type]);
float not_add_tr = float(!additative[type]);
//is_finished*
ALPHA = is_finished*(not_add_tr*sample.a + add_tr*(sample.r+sample.g+sample.b));
}
Loading

0 comments on commit af0ba44

Please sign in to comment.