aboutsummaryrefslogtreecommitdiff
path: root/game/src
diff options
context:
space:
mode:
author Hop311 <Hop3114@gmail.com>2023-11-17 21:17:55 +0100
committer GitHub <noreply@github.com>2023-11-17 21:17:55 +0100
commit9165f5980c5cfe75b3bad4303a5822340f6adcfc (patch)
tree79a69cb7601bf1367e4ee4f10ebf61b698319bf3 /game/src
parent72d893d55d26ae9dc6739a853d1773b3cb286123 (diff)
parentaefc61a1aff091e31436c60d004531b5905cecba (diff)
Merge pull request #166 from OpenVicProject/gui
GUI elements -> Godot UI nodes generator
Diffstat (limited to 'game/src')
-rw-r--r--game/src/Game/GameSession/GameSession.gd6
-rw-r--r--game/src/Game/GameSession/GameSession.tscn17
-rw-r--r--game/src/Game/GameSession/MapControlPanel/Minimap.gd2
-rw-r--r--game/src/Game/GameSession/MapView.gd5
-rw-r--r--game/src/Game/GameSession/ProvinceIndexSampler.gdshaderinc6
-rw-r--r--game/src/Game/GameSession/ProvinceOverviewPanel.gd215
-rw-r--r--game/src/Game/GameSession/ProvinceOverviewPanel/ProvinceOverviewPanel.gd142
-rw-r--r--game/src/Game/GameSession/ProvinceOverviewPanel/ProvinceOverviewPanel.tscn124
-rw-r--r--game/src/Game/GameSession/TerrainMap.gdshader87
-rw-r--r--game/src/Game/GlobalClass/ShaderManager.gd36
10 files changed, 345 insertions, 295 deletions
diff --git a/game/src/Game/GameSession/GameSession.gd b/game/src/Game/GameSession/GameSession.gd
index 2a27e3d..afff820 100644
--- a/game/src/Game/GameSession/GameSession.gd
+++ b/game/src/Game/GameSession/GameSession.gd
@@ -7,6 +7,12 @@ func _ready():
if GameSingleton.setup_game() != OK:
push_error("Failed to setup game")
+ # Temporarily here for cosmetic reasons, will be moved to its
+ # own child node later, similar to ProvinceOverviewPanel
+ add_child(GameSingleton.generate_gui("topbar.gui", "topbar"))
+ $topbar/topbar_outlinerbutton_bg.visible = false
+ $topbar/topbar_outlinerbutton.visible = false
+
func _process(_delta : float):
GameSingleton.try_tick()
diff --git a/game/src/Game/GameSession/GameSession.tscn b/game/src/Game/GameSession/GameSession.tscn
index c9f4095..755139e 100644
--- a/game/src/Game/GameSession/GameSession.tscn
+++ b/game/src/Game/GameSession/GameSession.tscn
@@ -5,7 +5,7 @@
[ext_resource type="PackedScene" uid="uid://g524p8lr574w" path="res://src/Game/GameSession/MapControlPanel/MapControlPanel.tscn" id="3_afh6d"]
[ext_resource type="PackedScene" uid="uid://dvdynl6eir40o" path="res://src/Game/GameSession/GameSessionMenu.tscn" id="3_bvmqh"]
[ext_resource type="PackedScene" uid="uid://dkehmdnuxih2r" path="res://src/Game/GameSession/MapView.tscn" id="4_xkg5j"]
-[ext_resource type="PackedScene" uid="uid://byq323jbel48u" path="res://src/Game/GameSession/ProvinceOverviewPanel/ProvinceOverviewPanel.tscn" id="5_osjnn"]
+[ext_resource type="Script" path="res://src/Game/GameSession/ProvinceOverviewPanel.gd" id="5_lfv8l"]
[ext_resource type="PackedScene" uid="uid://cnbfxjy1m6wja" path="res://src/Game/Menu/OptionMenu/OptionsMenu.tscn" id="6_p5mnx"]
[ext_resource type="PackedScene" uid="uid://dd8k3p7r3huwc" path="res://src/Game/GameSession/GameSpeedPanel.tscn" id="7_myy4q"]
[ext_resource type="PackedScene" uid="uid://d3g6wbvwflmyk" path="res://src/Game/Menu/SaveLoadMenu/SaveLoadMenu.tscn" id="8_4g7ko"]
@@ -24,6 +24,16 @@ _game_session_menu = NodePath("GameSessionMenu")
[node name="MapView" parent="." instance=ExtResource("4_xkg5j")]
+[node name="ProvinceOverviewPanel" type="Control" parent="."]
+layout_mode = 1
+anchors_preset = 15
+anchor_right = 1.0
+anchor_bottom = 1.0
+grow_horizontal = 2
+grow_vertical = 2
+mouse_filter = 1
+script = ExtResource("5_lfv8l")
+
[node name="MapControlPanel" parent="." instance=ExtResource("3_afh6d")]
layout_mode = 1
anchors_preset = 3
@@ -34,9 +44,6 @@ anchor_bottom = 1.0
grow_horizontal = 0
grow_vertical = 0
-[node name="ProvinceOverviewPanel" parent="." instance=ExtResource("5_osjnn")]
-layout_mode = 1
-
[node name="GameSpeedPanel" parent="." instance=ExtResource("7_myy4q")]
layout_mode = 0
offset_right = 302.0
@@ -86,8 +93,6 @@ grow_horizontal = 0
[connection signal="mouse_exited" from="MapControlPanel" to="MapView" method="_on_mouse_entered_viewport"]
[connection signal="zoom_in_button_pressed" from="MapControlPanel" to="MapView" method="zoom_in"]
[connection signal="zoom_out_button_pressed" from="MapControlPanel" to="MapView" method="zoom_out"]
-[connection signal="mouse_entered" from="ProvinceOverviewPanel" to="MapView" method="_on_mouse_exited_viewport"]
-[connection signal="mouse_exited" from="ProvinceOverviewPanel" to="MapView" method="_on_mouse_entered_viewport"]
[connection signal="load_button_pressed" from="GameSessionMenu" to="SaveLoadMenu" method="show_for_load"]
[connection signal="options_button_pressed" from="GameSessionMenu" to="OptionsMenu" method="show"]
[connection signal="save_button_pressed" from="GameSessionMenu" to="SaveLoadMenu" method="show_for_save"]
diff --git a/game/src/Game/GameSession/MapControlPanel/Minimap.gd b/game/src/Game/GameSession/MapControlPanel/Minimap.gd
index be65db5..5564821 100644
--- a/game/src/Game/GameSession/MapControlPanel/Minimap.gd
+++ b/game/src/Game/GameSession/MapControlPanel/Minimap.gd
@@ -10,7 +10,7 @@ var _minimap_shader : ShaderMaterial
var _viewport_points : PackedVector2Array
func _ready():
- _minimap_texture.custom_minimum_size = Vector2(GameSingleton.get_aspect_ratio(), 1.0) * 150
+ _minimap_texture.custom_minimum_size = Vector2(GameSingleton.get_map_aspect_ratio(), 1.0) * 150
var minimap_material := _minimap_texture.get_material()
if GameLoader.ShaderManager.set_up_shader(minimap_material, false) != OK:
push_error("Failed to set up minimap shader")
diff --git a/game/src/Game/GameSession/MapView.gd b/game/src/Game/GameSession/MapView.gd
index 345ab9e..7093c69 100644
--- a/game/src/Game/GameSession/MapView.gd
+++ b/game/src/Game/GameSession/MapView.gd
@@ -74,7 +74,10 @@ func _ready():
# Set map mesh size and get bounds
const pixels_per_terrain_tile : float = 32.0
_map_shader_material.set_shader_parameter(GameLoader.ShaderManager.param_terrain_tile_factor,
- float(GameSingleton.get_height()) / pixels_per_terrain_tile)
+ float(GameSingleton.get_map_height()) / pixels_per_terrain_tile)
+ const pixels_per_stripe_tile : float = 16.0
+ _map_shader_material.set_shader_parameter(GameLoader.ShaderManager.param_stripe_tile_factor,
+ float(GameSingleton.get_map_height()) / pixels_per_stripe_tile)
var map_mesh_aabb := _map_mesh.get_core_aabb() * _map_mesh_instance.transform
_map_mesh_corner = Vector2(
min(map_mesh_aabb.position.x, map_mesh_aabb.end.x),
diff --git a/game/src/Game/GameSession/ProvinceIndexSampler.gdshaderinc b/game/src/Game/GameSession/ProvinceIndexSampler.gdshaderinc
index 65f73d8..1adcd95 100644
--- a/game/src/Game/GameSession/ProvinceIndexSampler.gdshaderinc
+++ b/game/src/Game/GameSession/ProvinceIndexSampler.gdshaderinc
@@ -4,15 +4,21 @@ uniform sampler2DArray province_shape_tex : repeat_enable, filter_nearest;
// Province shape subdivisions
uniform vec2 province_shape_subdivisions;
+// Convert a vector of 3 normalised floats to a vector of 3 unsigned bytes
uvec3 vec3_to_uvec3(vec3 v) {
return uvec3(v * 255.0);
}
+
+// Create a uint triplet describing the province and terrain data at a map-space UV coordinate:
+// (u, v) -> (province index bottom byte, province index top byte, terrain index byte)
uvec3 read_uvec3(vec2 uv) {
uv *= province_shape_subdivisions;
vec2 subdivision_coords = mod(floor(uv), province_shape_subdivisions);
float idx = subdivision_coords.x + subdivision_coords.y * province_shape_subdivisions.x;
return vec3_to_uvec3(texture(province_shape_tex, vec3(uv, idx)).rgb);
}
+
+// Combine a (lower byte, upper byte) uint pair into a single 2-byte uint
uint uvec2_to_uint(uvec2 v) {
return (v.y << 8u) | v.x;
}
diff --git a/game/src/Game/GameSession/ProvinceOverviewPanel.gd b/game/src/Game/GameSession/ProvinceOverviewPanel.gd
new file mode 100644
index 0000000..1292eb4
--- /dev/null
+++ b/game/src/Game/GameSession/ProvinceOverviewPanel.gd
@@ -0,0 +1,215 @@
+extends Control
+
+var _province_name_label : Label
+var _region_name_label : Label
+var _life_rating_bar : TextureProgressBar
+var _total_population_label : Label
+var _rgo_icon_texture : AtlasTexture
+
+const _missing_suffix : String = "_MISSING"
+
+const _province_info_province_key : StringName = &"province"
+const _province_info_region_key : StringName = &"region"
+const _province_info_life_rating_key : StringName = &"life_rating"
+const _province_info_terrain_type_key : StringName = &"terrain_type"
+const _province_info_total_population_key : StringName = &"total_population"
+const _province_info_pop_types_key : StringName = &"pop_types"
+const _province_info_pop_ideologies_key : StringName = &"pop_ideologies"
+const _province_info_pop_cultures_key : StringName = &"pop_cultures"
+const _province_info_rgo_key : StringName = &"rgo"
+const _province_info_buildings_key : StringName = &"buildings"
+
+const _building_info_building_key : StringName = &"building"
+const _building_info_level_key : StringName = &"level"
+const _building_info_expansion_state_key : StringName = &"expansion_state"
+const _building_info_start_date_key : StringName = &"start_date"
+const _building_info_end_date_key : StringName = &"end_date"
+const _building_info_expansion_progress_key : StringName = &"expansion_progress"
+
+const _piechart_info_size_key : StringName = &"size"
+const _piechart_info_colour_key : StringName = &"colour"
+
+var _selected_index : int:
+ get: return _selected_index
+ set(v):
+ _selected_index = v
+ _update_info()
+var _province_info : Dictionary
+
+func _check_class(object : Object, klass : String, name : String) -> bool:
+ if object.get_class() == klass:
+ return true
+ else:
+ push_error("Invalid ", name, " class: ", object.get_class(), " (expected ", klass, ")")
+ return false
+
+func _try_get_node(path : NodePath, klass : String) -> Node:
+ var node : Node = get_node(path)
+ if node != null:
+ if _check_class(node, klass, path):
+ return node
+ else:
+ push_error("Failed to get node: ", path, " (returned null)")
+ return null
+
+func _ready():
+ GameSingleton.province_selected.connect(_on_province_selected)
+ GameSingleton.state_updated.connect(_update_info)
+
+ add_child(GameSingleton.generate_gui("province_interface.gui", "province_view"))
+
+ var close_button : Button = _try_get_node(^"./province_view/close_button", "Button")
+ if close_button != null:
+ close_button.pressed.connect(_on_close_button_pressed)
+
+ _region_name_label = _try_get_node(^"./province_view/province_view_header/state_name", "Label")
+
+ _province_name_label = _try_get_node(^"./province_view/province_view_header/province_name", "Label")
+
+ _life_rating_bar = _try_get_node(^"./province_view/province_view_header/liferating", "TextureProgressBar")
+
+ var goods_icon : TextureRect = _try_get_node(^"./province_view/province_statistics/goods_type", "TextureRect")
+ if goods_icon != null:
+ var texture := goods_icon.texture
+ if _check_class(texture, "GFXIconTexture", "good_texture"):
+ _rgo_icon_texture = texture
+
+
+ var rgo_population_label : Label = _try_get_node(^"./province_view/province_statistics/rgo_population", "Label")
+ if rgo_population_label != null:
+ rgo_population_label.text = "0"
+
+ #^"./province_view/province_statistics/crime_icon"
+
+ _total_population_label = _try_get_node(^"./province_view/province_statistics/total_population", "Label")
+
+ #^"./province_view/province_statistics/growth"
+ #^"./province_view/province_statistics/workforce_chart"
+ #^"./province_view/province_statistics/ideology_chart"
+ #^"./province_view/province_statistics/culture_chart"
+
+ $province_view/province_view_header/occupation_progress.visible = false
+ $province_view/province_view_header/occupation_icon.visible = false
+ $province_view/province_view_header/occupation_flag.visible = false
+ $province_view/province_colony.visible = false
+ $province_view/province_other.visible = false
+ $province_view/province_buildings/army_size.visible = false
+ $province_view/province_buildings/army_text.visible = false
+ $province_view/province_buildings/navy_text.visible = false
+ $province_view/national_focus_window.visible = false
+
+ _update_info()
+
+func _notification(what : int):
+ match what:
+ NOTIFICATION_TRANSLATION_CHANGED:
+ _update_info()
+"""
+enum { CANNOT_EXPAND, CAN_EXPAND, PREPARING, EXPANDING }
+
+func _expand_building(building_identifier : String) -> void:
+ if GameSingleton.expand_building(_selected_index, building_identifier) != OK:
+ push_error("Failed to expand ", building_identifier, " in province #", _selected_index);
+
+# Each building row contains:
+# level - Level Label
+# name - Name Label
+# button - Expansion Button
+# progress_bar - Expansion ProgressBar
+var _building_rows : Array[Dictionary]
+
+
+# REQUIREMENTS:
+# * UI-183, UI-185, UI-186, UI-765, UI-187, UI-188, UI-189
+# * UI-191, UI-193, UI-194, UI-766, UI-195, UI-196, UI-197
+# * UI-199, UI-201, UI-202, UI-767, UI-203, UI-204, UI-205
+func _add_building_row() -> void:
+ var row : Dictionary = {}
+
+ row.level = Label.new()
+ row.level.text = "X"
+ _buildings_container.add_child(row.level)
+
+ row.name = Label.new()
+ row.name.text = _building_info_building_key + _missing_suffix
+ _buildings_container.add_child(row.name)
+
+ row.button = Button.new()
+ row.button.text = "EXPAND_PROVINCE_BUILDING"
+ row.button.size_flags_horizontal = Control.SIZE_EXPAND_FILL
+ row.button.mouse_filter = Control.MOUSE_FILTER_PASS
+ row.button.focus_mode = FOCUS_NONE
+ row.button.pressed.connect(func(): _expand_building(row.name.text))
+ _buildings_container.add_child(row.button)
+
+ row.progress_bar = ProgressBar.new()
+ row.progress_bar.max_value = 1
+ row.progress_bar.size_flags_horizontal = Control.SIZE_EXPAND_FILL
+ row.progress_bar.mouse_filter = Control.MOUSE_FILTER_PASS
+ _buildings_container.add_child(row.progress_bar)
+
+ _building_rows.append(row)
+ _set_building_row(_building_rows.size() - 1, {})
+
+func _set_building_row(index : int, building : Dictionary) -> void:
+ if index < 0 or index > _building_rows.size():
+ push_error("Invalid building row index: ", index, " (max ", _building_rows.size(), ")")
+ return
+ if index == _building_rows.size(): _add_building_row()
+ var row := _building_rows[index]
+ if building.is_empty():
+ row.level.visible = false
+ row.name.visible = false
+ row.progress_bar.visible = false
+ row.button.visible = false
+ return
+ row.level.text = str(building.get(_building_info_level_key, 0))
+ row.level.visible = true
+ row.name.text = building.get(_building_info_building_key,
+ _building_info_building_key + _missing_suffix)
+ row.name.visible = true
+
+ var expansion_state : int = building.get(_building_info_expansion_state_key,
+ CANNOT_EXPAND)
+ var show_progress_bar := expansion_state == PREPARING or expansion_state == EXPANDING
+ row.progress_bar.value = building.get(_building_info_expansion_progress_key, 0)
+ row.progress_bar.visible = show_progress_bar
+ row.button.disabled = expansion_state != CAN_EXPAND
+ row.button.visible = not show_progress_bar
+"""
+func _update_info() -> void:
+ _province_info = GameSingleton.get_province_info_from_index(_selected_index)
+ if _province_info:
+ if _province_name_label:
+ _province_name_label.text = "PROV" + _province_info.get(_province_info_province_key,
+ _province_info_province_key + _missing_suffix)
+ if _region_name_label:
+ _region_name_label.text = _province_info.get(_province_info_region_key,
+ _province_info_region_key + _missing_suffix)
+ if _life_rating_bar:
+ _life_rating_bar.value = _province_info.get(_province_info_life_rating_key, 0) * 0
+
+ if _total_population_label:
+ _total_population_label.text = Localisation.tr_number(_province_info.get(_province_info_total_population_key, 0))
+
+ #_pop_type_chart.set_to_distribution(_province_info.get(_province_info_pop_types_key, {}))
+ #_pop_ideology_chart.set_to_distribution(_province_info.get(_province_info_pop_ideologies_key, {}))
+ #_pop_culture_chart.set_to_distribution(_province_info.get(_province_info_pop_cultures_key, {}))
+
+ if _rgo_icon_texture:
+ _rgo_icon_texture.set_icon_index((_selected_index % 40) + 1)
+
+ #var buildings : Array = _province_info.get(_province_info_buildings_key, [])
+ #for i in max(buildings.size(), _building_rows.size()):
+ # _set_building_row(i, buildings[i] if i < buildings.size() else {})
+
+ show()
+ else:
+ hide()
+ mouse_exited.emit()
+
+func _on_province_selected(index : int) -> void:
+ _selected_index = index
+
+func _on_close_button_pressed() -> void:
+ GameSingleton.set_selected_province(0)
diff --git a/game/src/Game/GameSession/ProvinceOverviewPanel/ProvinceOverviewPanel.gd b/game/src/Game/GameSession/ProvinceOverviewPanel/ProvinceOverviewPanel.gd
deleted file mode 100644
index ae42450..0000000
--- a/game/src/Game/GameSession/ProvinceOverviewPanel/ProvinceOverviewPanel.gd
+++ /dev/null
@@ -1,142 +0,0 @@
-extends PanelContainer
-
-@export var _province_name_label : Label
-@export var _region_name_label : Label
-@export var _life_rating_bar : ProgressBar
-@export var _terrain_type_name_label : Label
-@export var _total_population_label : Label
-@export var _rgo_icon_texture_rect : TextureRect
-@export var _rgo_name_label : Label
-@export var _buildings_container : Container
-@export var _pop_type_chart : PieChart
-@export var _pop_ideology_chart : PieChart
-@export var _pop_culture_chart : PieChart
-
-const _missing_suffix : String = "_MISSING"
-
-var _selected_index : int:
- get: return _selected_index
- set(v):
- _selected_index = v
- _update_info()
-var _province_info : Dictionary
-
-func _ready():
- GameSingleton.province_selected.connect(_on_province_selected)
- GameSingleton.state_updated.connect(_update_info)
- _update_info()
-
-func _notification(what : int):
- match what:
- NOTIFICATION_TRANSLATION_CHANGED:
- _update_info()
-
-enum { CANNOT_EXPAND, CAN_EXPAND, PREPARING, EXPANDING }
-
-func _expand_building(building_identifier : String) -> void:
- if GameSingleton.expand_building(_selected_index, building_identifier) != OK:
- push_error("Failed to expand ", building_identifier, " in province #", _selected_index);
-
-# Each building row contains:
-# level - Level Label
-# name - Name Label
-# button - Expansion Button
-# progress_bar - Expansion ProgressBar
-var _building_rows : Array[Dictionary]
-
-# REQUIREMENTS:
-# * UI-183, UI-185, UI-186, UI-765, UI-187, UI-188, UI-189
-# * UI-191, UI-193, UI-194, UI-766, UI-195, UI-196, UI-197
-# * UI-199, UI-201, UI-202, UI-767, UI-203, UI-204, UI-205
-func _add_building_row() -> void:
- var row : Dictionary = {}
-
- row.level = Label.new()
- row.level.text = "X"
- _buildings_container.add_child(row.level)
-
- row.name = Label.new()
- row.name.text = GameSingleton.get_building_info_building_key() + _missing_suffix
- _buildings_container.add_child(row.name)
-
- row.button = Button.new()
- row.button.text = "EXPAND_PROVINCE_BUILDING"
- row.button.size_flags_horizontal = Control.SIZE_EXPAND_FILL
- row.button.mouse_filter = Control.MOUSE_FILTER_PASS
- row.button.focus_mode = FOCUS_NONE
- row.button.pressed.connect(func(): _expand_building(row.name.text))
- _buildings_container.add_child(row.button)
-
- row.progress_bar = ProgressBar.new()
- row.progress_bar.max_value = 1
- row.progress_bar.size_flags_horizontal = Control.SIZE_EXPAND_FILL
- row.progress_bar.mouse_filter = Control.MOUSE_FILTER_PASS
- _buildings_container.add_child(row.progress_bar)
-
- _building_rows.append(row)
- _set_building_row(_building_rows.size() - 1, {})
-
-func _set_building_row(index : int, building : Dictionary) -> void:
- if index < 0 or index > _building_rows.size():
- push_error("Invalid building row index: ", index, " (max ", _building_rows.size(), ")")
- return
- if index == _building_rows.size(): _add_building_row()
- var row := _building_rows[index]
- if building.is_empty():
- row.level.visible = false
- row.name.visible = false
- row.progress_bar.visible = false
- row.button.visible = false
- return
- row.level.text = str(building.get(GameSingleton.get_building_info_level_key(), 0))
- row.level.visible = true
- row.name.text = building.get(GameSingleton.get_building_info_building_key(),
- GameSingleton.get_building_info_building_key() + _missing_suffix)
- row.name.visible = true
-
- var expansion_state : int = building.get(GameSingleton.get_building_info_expansion_state_key(),
- CANNOT_EXPAND)
- var show_progress_bar := expansion_state == PREPARING or expansion_state == EXPANDING
- row.progress_bar.value = building.get(GameSingleton.get_building_info_expansion_progress_key(), 0)
- row.progress_bar.visible = show_progress_bar
- row.button.disabled = expansion_state != CAN_EXPAND
- row.button.visible = not show_progress_bar
-
-func _update_info() -> void:
- _province_info = GameSingleton.get_province_info_from_index(_selected_index)
- if _province_info:
- _province_name_label.text = "PROV" + _province_info.get(GameSingleton.get_province_info_province_key(),
- GameSingleton.get_province_info_province_key() + _missing_suffix)
- _region_name_label.text = _province_info.get(GameSingleton.get_province_info_region_key(),
- GameSingleton.get_province_info_region_key() + _missing_suffix)
- _life_rating_bar.value = _province_info.get(GameSingleton.get_province_info_life_rating_key(), 0)
- _life_rating_bar.tooltip_text = tr("LIFE_RATING_TOOLTIP").format({
- "life_rating": Localisation.tr_number(_life_rating_bar.value)
- })
- _terrain_type_name_label.text = _province_info.get(GameSingleton.get_province_info_terrain_type_key(),
- GameSingleton.get_province_info_terrain_type_key() + _missing_suffix)
-
- _total_population_label.text = Localisation.tr_number(_province_info.get(GameSingleton.get_province_info_total_population_key(), 0))
-
- _pop_type_chart.set_to_distribution(_province_info.get(GameSingleton.get_province_info_pop_types_key(), {}))
- _pop_ideology_chart.set_to_distribution(_province_info.get(GameSingleton.get_province_info_pop_ideologies_key(), {}))
- _pop_culture_chart.set_to_distribution(_province_info.get(GameSingleton.get_province_info_pop_cultures_key(), {}))
-
- _rgo_name_label.text = _province_info.get(GameSingleton.get_province_info_rgo_key(),
- GameSingleton.get_province_info_rgo_key() + _missing_suffix)
- _rgo_icon_texture_rect.texture = null
-
- var buildings : Array = _province_info.get(GameSingleton.get_province_info_buildings_key(), [])
- for i in max(buildings.size(), _building_rows.size()):
- _set_building_row(i, buildings[i] if i < buildings.size() else {})
-
- show()
- else:
- hide()
- mouse_exited.emit()
-
-func _on_province_selected(index : int) -> void:
- _selected_index = index
-
-func _on_close_button_pressed() -> void:
- GameSingleton.set_selected_province(0)
diff --git a/game/src/Game/GameSession/ProvinceOverviewPanel/ProvinceOverviewPanel.tscn b/game/src/Game/GameSession/ProvinceOverviewPanel/ProvinceOverviewPanel.tscn
deleted file mode 100644
index bbd0b95..0000000
--- a/game/src/Game/GameSession/ProvinceOverviewPanel/ProvinceOverviewPanel.tscn
+++ /dev/null
@@ -1,124 +0,0 @@
-[gd_scene load_steps=3 format=3 uid="uid://byq323jbel48u"]
-
-[ext_resource type="Script" path="res://src/Game/GameSession/ProvinceOverviewPanel/ProvinceOverviewPanel.gd" id="1_3n8k5"]
-[ext_resource type="PackedScene" uid="uid://cr7p1k2xm7mum" path="res://src/Game/Theme/PieChart/PieChart.tscn" id="2_3oytt"]
-
-[node name="ProvinceOverviewPanel" type="PanelContainer" node_paths=PackedStringArray("_province_name_label", "_region_name_label", "_life_rating_bar", "_terrain_type_name_label", "_total_population_label", "_rgo_icon_texture_rect", "_rgo_name_label", "_buildings_container", "_pop_type_chart", "_pop_ideology_chart", "_pop_culture_chart")]
-editor_description = "UI-56"
-anchors_preset = 2
-anchor_top = 1.0
-anchor_bottom = 1.0
-offset_top = -300.0
-offset_right = 200.0
-grow_vertical = 0
-mouse_filter = 1
-script = ExtResource("1_3n8k5")
-_province_name_label = NodePath("PanelList/TopBarList/NameList/ProvinceName")
-_region_name_label = NodePath("PanelList/TopBarList/NameList/RegionName")
-_life_rating_bar = NodePath("PanelList/TopBarList/NameList/LifeRatingBar")
-_terrain_type_name_label = NodePath("PanelList/TopBarList/NameList/TerrainTypeName")
-_total_population_label = NodePath("PanelList/InteractList/TotalPopulation")
-_rgo_icon_texture_rect = NodePath("PanelList/InteractList/RGOInfo/RGOIcon")
-_rgo_name_label = NodePath("PanelList/InteractList/RGOInfo/RGOName")
-_buildings_container = NodePath("PanelList/InteractList/BuildingsContainer")
-_pop_type_chart = NodePath("PanelList/InteractList/PopStats/PopTypeChart")
-_pop_ideology_chart = NodePath("PanelList/InteractList/PopStats/PopIdeologyChart")
-_pop_culture_chart = NodePath("PanelList/InteractList/PopStats/PopCultureChart")
-
-[node name="PanelList" type="VBoxContainer" parent="."]
-layout_mode = 2
-
-[node name="TopBarList" type="HBoxContainer" parent="PanelList"]
-layout_mode = 2
-
-[node name="NameList" type="VBoxContainer" parent="PanelList/TopBarList"]
-layout_mode = 2
-size_flags_horizontal = 3
-size_flags_vertical = 0
-
-[node name="ProvinceName" type="Label" parent="PanelList/TopBarList/NameList"]
-editor_description = "UI-57"
-layout_mode = 2
-text = "province_MISSING"
-vertical_alignment = 1
-
-[node name="RegionName" type="Label" parent="PanelList/TopBarList/NameList"]
-editor_description = "UI-58"
-layout_mode = 2
-text = "region_MISSING"
-vertical_alignment = 1
-
-[node name="LifeRatingBar" type="ProgressBar" parent="PanelList/TopBarList/NameList"]
-editor_description = "UI-62"
-layout_mode = 2
-mouse_filter = 1
-
-[node name="TerrainTypeName" type="Label" parent="PanelList/TopBarList/NameList"]
-layout_mode = 2
-text = "terrain_type_MISSING"
-vertical_alignment = 1
-
-[node name="CloseButton" type="Button" parent="PanelList/TopBarList"]
-custom_minimum_size = Vector2(30, 30)
-layout_mode = 2
-size_flags_vertical = 0
-focus_mode = 0
-mouse_filter = 1
-text = "X"
-
-[node name="InteractList" type="VBoxContainer" parent="PanelList"]
-layout_mode = 2
-size_flags_vertical = 3
-
-[node name="HSeparator" type="HSeparator" parent="PanelList/InteractList"]
-layout_mode = 2
-mouse_filter = 1
-
-[node name="TotalPopulation" type="Label" parent="PanelList/InteractList"]
-editor_description = "UI-121"
-layout_mode = 2
-tooltip_text = "PROVINCE_POPULATION_TOOLTIP"
-mouse_filter = 1
-text = "total_population_MISSING"
-
-[node name="RGOInfo" type="HBoxContainer" parent="PanelList/InteractList"]
-editor_description = "UI-112"
-layout_mode = 2
-
-[node name="RGOIcon" type="TextureRect" parent="PanelList/InteractList/RGOInfo"]
-editor_description = "UI-100"
-layout_mode = 2
-
-[node name="RGOName" type="Label" parent="PanelList/InteractList/RGOInfo"]
-layout_mode = 2
-text = "rgo_MISSING"
-vertical_alignment = 1
-
-[node name="HSeparator2" type="HSeparator" parent="PanelList/InteractList"]
-layout_mode = 2
-mouse_filter = 1
-
-[node name="PopStats" type="HBoxContainer" parent="PanelList/InteractList"]
-editor_description = "UI-124"
-layout_mode = 2
-
-[node name="PopTypeChart" parent="PanelList/InteractList/PopStats" instance=ExtResource("2_3oytt")]
-editor_description = "UI-125"
-layout_mode = 2
-
-[node name="PopIdeologyChart" parent="PanelList/InteractList/PopStats" instance=ExtResource("2_3oytt")]
-layout_mode = 2
-
-[node name="PopCultureChart" parent="PanelList/InteractList/PopStats" instance=ExtResource("2_3oytt")]
-editor_description = "UI-127"
-layout_mode = 2
-
-[node name="HSeparator3" type="HSeparator" parent="PanelList/InteractList"]
-layout_mode = 2
-mouse_filter = 1
-
-[node name="BuildingsContainer" type="GridContainer" parent="PanelList/InteractList"]
-layout_mode = 2
-columns = 3
-
-[connection signal="pressed" from="PanelList/TopBarList/CloseButton" to="." method="_on_close_button_pressed"]
diff --git a/game/src/Game/GameSession/TerrainMap.gdshader b/game/src/Game/GameSession/TerrainMap.gdshader
index 852ccc3..35a108b 100644
--- a/game/src/Game/GameSession/TerrainMap.gdshader
+++ b/game/src/Game/GameSession/TerrainMap.gdshader
@@ -14,34 +14,89 @@ uniform uint selected_index;
uniform sampler2DArray terrain_tex: source_color, repeat_enable, filter_linear;
// The number of times the terrain textures should tile vertically
uniform float terrain_tile_factor;
+// Map stripe mask texture
+uniform sampler2D stripe_tex: source_color, repeat_enable, filter_linear;
+// The number of times the stripe texture should tile vertically
+uniform float stripe_tile_factor;
+// Land map tint
+uniform sampler2D colormap_land_tex: source_color, repeat_enable, filter_linear;
+// Water map tint
+uniform sampler2D colormap_water_tex: source_color, repeat_enable, filter_linear;
const vec3 highlight_colour = vec3(1.0);
-vec3 get_terrain_colour(vec2 uv, vec2 corner, vec2 half_pixel_size, vec2 terrain_uv) {
+vec3 get_terrain_colour(
+ vec2 uv, vec2 corner, vec2 half_pixel_size, // Components for calculating province sampling UV
+ float stripe_mask, // Stripe mask value - between 0 (base) and 1 (stripe)
+ vec2 terrain_uv, // UV coordinates scaled for terrain texture tiling
+ vec3 land_tint_colour, vec3 water_tint_colour // Colours for tinting terrain
+) {
+
uvec3 province_data = read_uvec3(fma(corner, half_pixel_size, uv));
- vec4 province_colour = texelFetch(province_colour_tex, ivec2(province_data.rg), 0);
- vec3 terrain_colour = texture(terrain_tex, vec3(terrain_uv, float(province_data.b))).rgb;
- vec3 mixed_colour = mix(terrain_colour, province_colour.rgb, province_colour.a);
- uint index = uvec2_to_uint(province_data.rg);
- float mix_val = 0.1 * (float(index == hover_index) + float(index == selected_index));
- return mix(mixed_colour, highlight_colour, mix_val);
+ uint province_index = uvec2_to_uint(province_data.rg);
+ uint terrain_index = province_data.b;
+
+ province_data.r *= 2u; // Double "x coordinate" as colours come in (base, stripe) pairs
+ vec4 province_base_colour = texelFetch(province_colour_tex, ivec2(province_data.rg), 0);
+ province_data.r += 1u; // Add 1 to "x coordinate" to move from base to strip colour
+ vec4 province_stripe_colour = texelFetch(province_colour_tex, ivec2(province_data.rg), 0);
+ vec4 province_colour = mix(province_base_colour, province_stripe_colour, stripe_mask);
+
+ vec3 terrain_colour = texture(terrain_tex, vec3(terrain_uv, float(terrain_index))).rgb;
+ vec3 tint_colour = mix(land_tint_colour, water_tint_colour, float(terrain_index == 0u));
+ vec3 tinted_terrain_colour = mix(terrain_colour, tint_colour, 0.3);
+ vec3 mixed_colour = mix(tinted_terrain_colour, province_colour.rgb, province_colour.a);
+
+ float highlight_mix_val = 0.1 * (float(province_index == hover_index) + float(province_index == selected_index));
+ return mix(mixed_colour, highlight_colour, highlight_mix_val);
+}
+
+// Rescale UV coordinates to remove squashing caused by normalisation
+vec2 denormalise(vec2 uv, vec2 dims) {
+ return vec2(uv.x * dims.x / dims.y, uv.y);
}
vec3 mix_terrain_colour(vec2 uv) {
vec2 map_size = vec2(textureSize(province_shape_tex, 0).xy) * province_shape_subdivisions;
- vec2 pixel_offset = fract(fma(uv, map_size, vec2(0.5)));
+ vec2 uv_centred = fma(uv, map_size, vec2(0.5));
+ vec2 pixel_offset = fract(uv_centred);
vec2 half_pixel_size = 0.49 / map_size;
- vec2 terrain_uv = uv;
- terrain_uv.x *= map_size.x / map_size.y;
- terrain_uv *= terrain_tile_factor;
+ // UV coords adjusted to remove squashing caused by normalisation relative to map dimensions
+ vec2 unscaled_uv = denormalise(uv, map_size);
+
+ vec2 stripe_uv = unscaled_uv * stripe_tile_factor;
+ // Stripe mask value - between 0 (base) and 1 (stripe)
+ float stripe_mask = texture(stripe_tex, stripe_uv).b;
+
+ vec2 terrain_uv = unscaled_uv * terrain_tile_factor;
+ vec2 colormap_uv = vec2(uv.x, 1.0 - uv.y);
+ vec3 colormap_land_colour = texture(colormap_land_tex, colormap_uv).rgb;
+ vec3 colormap_water_colour = texture(colormap_water_tex, colormap_uv).rgb;
return mix(
- mix(get_terrain_colour(uv, vec2(-1, -1), half_pixel_size, terrain_uv),
- get_terrain_colour(uv, vec2(+1, -1), half_pixel_size, terrain_uv), pixel_offset.x),
- mix(get_terrain_colour(uv, vec2(-1, +1), half_pixel_size, terrain_uv),
- get_terrain_colour(uv, vec2(+1, +1), half_pixel_size, terrain_uv), pixel_offset.x),
- pixel_offset.y);
+ mix(
+ get_terrain_colour(
+ uv, vec2(-1, -1), half_pixel_size, stripe_mask,
+ terrain_uv, colormap_land_colour, colormap_water_colour
+ ),
+ get_terrain_colour(
+ uv, vec2(+1, -1), half_pixel_size, stripe_mask,
+ terrain_uv, colormap_land_colour, colormap_water_colour
+ ), pixel_offset.x
+ ),
+ mix(
+ get_terrain_colour(
+ uv, vec2(-1, +1), half_pixel_size, stripe_mask,
+ terrain_uv, colormap_land_colour, colormap_water_colour
+ ),
+ get_terrain_colour(
+ uv, vec2(+1, +1), half_pixel_size, stripe_mask,
+ terrain_uv, colormap_land_colour, colormap_water_colour
+ ), pixel_offset.x
+ ),
+ pixel_offset.y
+ );
}
void fragment() {
diff --git a/game/src/Game/GlobalClass/ShaderManager.gd b/game/src/Game/GlobalClass/ShaderManager.gd
index fd91e31..ace3c3a 100644
--- a/game/src/Game/GlobalClass/ShaderManager.gd
+++ b/game/src/Game/GlobalClass/ShaderManager.gd
@@ -8,6 +8,18 @@ const param_hover_index : StringName = &"hover_index"
const param_selected_index : StringName = &"selected_index"
const param_terrain_tex : StringName = &"terrain_tex"
const param_terrain_tile_factor : StringName = &"terrain_tile_factor"
+const param_stripe_tex : StringName = &"stripe_tex"
+const param_stripe_tile_factor : StringName = &"stripe_tile_factor"
+const param_colormap_land_tex : StringName = &"colormap_land_tex"
+const param_colormap_water_tex : StringName = &"colormap_water_tex"
+
+func _set_shader_texture(shader_material : ShaderMaterial, texture_path : StringName, texture_param : StringName) -> Error:
+ var texture := AssetManager.get_texture(texture_path)
+ if texture == null:
+ push_error("Failed to get texture: ", texture_path)
+ return FAILED
+ shader_material.set_shader_parameter(texture_param, texture)
+ return OK
func set_up_shader(material : Material, add_cosmetic_textures : bool) -> Error:
# Shader Material
@@ -19,31 +31,45 @@ func set_up_shader(material : Material, add_cosmetic_textures : bool) -> Error:
return FAILED
var shader_material : ShaderMaterial = material
+ var ret : Error = OK
+
# Province shape texture
var province_shape_texture := GameSingleton.get_province_shape_texture()
if province_shape_texture == null:
push_error("Failed to get province shape texture!")
- return FAILED
+ ret = FAILED
shader_material.set_shader_parameter(param_province_shape_tex, province_shape_texture)
var subdivisions := GameSingleton.get_province_shape_image_subdivisions()
if subdivisions.x < 1 or subdivisions.y < 1:
push_error("Invalid province shape image subdivision: ", subdivisions.x, "x", subdivisions.y)
- return FAILED
+ ret = FAILED
shader_material.set_shader_parameter(param_province_shape_subdivisions, Vector2(subdivisions))
if add_cosmetic_textures:
+
# Province colour texture
var map_province_colour_texture := GameSingleton.get_province_colour_texture()
if map_province_colour_texture == null:
push_error("Failed to get province colour image!")
- return FAILED
+ ret = FAILED
shader_material.set_shader_parameter(param_province_colour_tex, map_province_colour_texture)
# Terrain texture
var terrain_texture := GameSingleton.get_terrain_texture()
if terrain_texture == null:
push_error("Failed to get terrain texture!")
- return FAILED
+ ret = FAILED
shader_material.set_shader_parameter(param_terrain_tex, terrain_texture)
- return OK
+ # Stripe texture
+ if _set_shader_texture(shader_material, &"map/terrain/stripes.dds", param_stripe_tex) != OK:
+ ret = FAILED
+
+ # Land colormap
+ if _set_shader_texture(shader_material, &"map/terrain/colormap.dds", param_colormap_land_tex) != OK:
+ ret = FAILED
+ # Water colormap
+ if _set_shader_texture(shader_material, &"map/terrain/colormap_water.dds", param_colormap_water_tex) != OK:
+ ret = FAILED
+
+ return ret