From bc0b3c61ae0b742da304cada451fba1df72bb0ad Mon Sep 17 00:00:00 2001 From: hop311 Date: Wed, 8 Nov 2023 22:24:21 +0000 Subject: GUI elements -> Godot UI nodes generator --- game/src/Game/GameSession/GameSession.gd | 6 + game/src/Game/GameSession/GameSession.tscn | 17 +- game/src/Game/GameSession/ProvinceOverviewPanel.gd | 215 +++++++++++++++++++++ .../ProvinceOverviewPanel/ProvinceOverviewPanel.gd | 142 -------------- .../ProvinceOverviewPanel.tscn | 124 ------------ 5 files changed, 232 insertions(+), 272 deletions(-) create mode 100644 game/src/Game/GameSession/ProvinceOverviewPanel.gd delete mode 100644 game/src/Game/GameSession/ProvinceOverviewPanel/ProvinceOverviewPanel.gd delete mode 100644 game/src/Game/GameSession/ProvinceOverviewPanel/ProvinceOverviewPanel.tscn (limited to 'game/src/Game') 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/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"] -- cgit v1.2.3-56-ga3b1 From 3490e740a7235dce236fc2ce973e5cbf64d6e727 Mon Sep 17 00:00:00 2001 From: hop311 Date: Wed, 15 Nov 2023 23:54:57 +0000 Subject: Striped mapmodes --- extension/deps/openvic-simulation | 2 +- extension/src/openvic-extension/UIAdapter.cpp | 8 ++-- .../openvic-extension/singletons/GameSingleton.cpp | 49 ++++++++++++---------- .../openvic-extension/singletons/GameSingleton.hpp | 8 ++-- .../src/openvic-extension/utility/Utilities.hpp | 4 ++ game/localisation/en_GB/mapmodes.csv | 1 + .../Game/GameSession/MapControlPanel/Minimap.gd | 2 +- game/src/Game/GameSession/MapView.gd | 5 ++- .../GameSession/ProvinceIndexSampler.gdshaderinc | 6 +++ game/src/Game/GameSession/TerrainMap.gdshader | 39 +++++++++++------ game/src/Game/GlobalClass/ShaderManager.gd | 9 ++++ 11 files changed, 87 insertions(+), 46 deletions(-) (limited to 'game/src/Game') diff --git a/extension/deps/openvic-simulation b/extension/deps/openvic-simulation index f572664..2607fd6 160000 --- a/extension/deps/openvic-simulation +++ b/extension/deps/openvic-simulation @@ -1 +1 @@ -Subproject commit f572664cbe1aa5ec2cb6907de3083f058c20af7e +Subproject commit 2607fd63b849788e92174161a9cea72141c88f7a diff --git a/extension/src/openvic-extension/UIAdapter.cpp b/extension/src/openvic-extension/UIAdapter.cpp index 5b889d6..d688754 100644 --- a/extension/src/openvic-extension/UIAdapter.cpp +++ b/extension/src/openvic-extension/UIAdapter.cpp @@ -65,7 +65,7 @@ static T* new_control(GUI::Element const& element) { UtilityFunctions::push_error("Invalid orientation for GUI element ", std_view_to_godot_string(element.get_name())); } - node->set_position(Utilities::to_godot_ivec2(element.get_position())); + node->set_position(Utilities::to_godot_fvec2(element.get_position())); node->set_focus_mode(Control::FOCUS_NONE); return node; @@ -343,7 +343,7 @@ bool GodotGUIBuilder::generate_overlapping_elements( return false; } - godot_rect->set_size(Utilities::to_godot_ivec2(overlapping_elements.get_size())); + godot_rect->set_size(Utilities::to_godot_fvec2(overlapping_elements.get_size())); godot_rect->set_color({ 0.0f, 0.5f, 1.0f, 0.2f }); result = godot_rect; @@ -362,7 +362,7 @@ bool GodotGUIBuilder::generate_listbox(GUI::Element const& element, AssetManager return false; } - godot_rect->set_size(Utilities::to_godot_ivec2(listbox.get_size())); + godot_rect->set_size(Utilities::to_godot_fvec2(listbox.get_size())); godot_rect->set_color({ 1.0f, 0.5f, 0.0f, 0.2f }); result = godot_rect; @@ -382,7 +382,7 @@ bool GodotGUIBuilder::generate_window(GUI::Element const& element, AssetManager& return false; } - godot_panel->set_size(Utilities::to_godot_ivec2(window.get_size())); + godot_panel->set_size(Utilities::to_godot_fvec2(window.get_size())); godot_panel->set_self_modulate({ 1.0f, 1.0f, 1.0f, 0.0f }); bool ret = true; diff --git a/extension/src/openvic-extension/singletons/GameSingleton.cpp b/extension/src/openvic-extension/singletons/GameSingleton.cpp index bb1732e..d101a86 100644 --- a/extension/src/openvic-extension/singletons/GameSingleton.cpp +++ b/extension/src/openvic-extension/singletons/GameSingleton.cpp @@ -23,15 +23,14 @@ void GameSingleton::_bind_methods() { OV_BIND_METHOD(GameSingleton::load_defines_compatibility_mode, { "file_paths" }); OV_BIND_SMETHOD(search_for_game_path, { "hint_path" }, DEFVAL(String {})); - OV_BIND_METHOD(GameSingleton::lookup_file, { "path" }); OV_BIND_METHOD(GameSingleton::setup_game); OV_BIND_METHOD(GameSingleton::get_province_index_from_uv_coords, { "coords" }); OV_BIND_METHOD(GameSingleton::get_province_info_from_index, { "index" }); - OV_BIND_METHOD(GameSingleton::get_width); - OV_BIND_METHOD(GameSingleton::get_height); - OV_BIND_METHOD(GameSingleton::get_aspect_ratio); + OV_BIND_METHOD(GameSingleton::get_map_width); + OV_BIND_METHOD(GameSingleton::get_map_height); + OV_BIND_METHOD(GameSingleton::get_map_aspect_ratio); OV_BIND_METHOD(GameSingleton::get_terrain_texture); OV_BIND_METHOD(GameSingleton::get_province_shape_image_subdivisions); OV_BIND_METHOD(GameSingleton::get_province_shape_texture); @@ -149,19 +148,25 @@ Dataloader const& GameSingleton::get_dataloader() const { } Error GameSingleton::setup_game() { - bool ret = game_manager.setup(); + BookmarkManager const& bookmark_manager = game_manager.get_history_manager().get_bookmark_manager(); + if (bookmark_manager.bookmarks_empty()) { + UtilityFunctions::push_error("No bookmark to load!"); + return FAILED; + } + bool ret = game_manager.load_bookmark(&bookmark_manager.get_bookmarks().front()); + // TODO - load pop history with the new history system ret &= dataloader.load_pop_history(game_manager, "history/pops/" + game_manager.get_today().to_string()); return ERR(ret); } int32_t GameSingleton::get_province_index_from_uv_coords(Vector2 const& coords) const { - const size_t x_mod_w = UtilityFunctions::fposmod(coords.x, 1.0f) * get_width(); - const size_t y_mod_h = UtilityFunctions::fposmod(coords.y, 1.0f) * get_height(); + const size_t x_mod_w = UtilityFunctions::fposmod(coords.x, 1.0f) * get_map_width(); + const size_t y_mod_h = UtilityFunctions::fposmod(coords.y, 1.0f) * get_map_height(); return game_manager.get_map().get_province_index_at(x_mod_w, y_mod_h); } template T> -static Dictionary _distribution_to_dictionary(decimal_map_t const& dist) { +static Dictionary _distribution_to_dictionary(fixed_point_map_t const& dist) { static const StringName piechart_info_size_key = "size"; static const StringName piechart_info_colour_key = "colour"; Dictionary dict; @@ -216,15 +221,15 @@ Dictionary GameSingleton::get_province_info_from_index(int32_t index) const { } ret[province_info_total_population_key] = province->get_total_population(); - decimal_map_t const& pop_types = province->get_pop_type_distribution(); + fixed_point_map_t const& pop_types = province->get_pop_type_distribution(); if (!pop_types.empty()) { ret[province_info_pop_types_key] = _distribution_to_dictionary(pop_types); } - decimal_map_t const& ideologies = province->get_ideology_distribution(); + fixed_point_map_t const& ideologies = province->get_ideology_distribution(); if (!ideologies.empty()) { ret[province_info_pop_ideologies_key] = _distribution_to_dictionary(ideologies); } - decimal_map_t const& cultures = province->get_culture_distribution(); + fixed_point_map_t const& cultures = province->get_culture_distribution(); if (!cultures.empty()) { ret[province_info_pop_cultures_key] = _distribution_to_dictionary(cultures); } @@ -245,7 +250,7 @@ Dictionary GameSingleton::get_province_info_from_index(int32_t index) const { Dictionary building_dict; building_dict[building_info_building_key] = std_view_to_godot_string(building.get_identifier()); - building_dict[building_info_level_key] = static_cast(building.get_current_level()); + building_dict[building_info_level_key] = static_cast(building.get_level()); building_dict[building_info_expansion_state_key] = static_cast(building.get_expansion_state()); building_dict[building_info_start_date_key] = std_to_godot_string(building.get_start_date().to_string()); building_dict[building_info_end_date_key] = std_to_godot_string(building.get_end_date().to_string()); @@ -258,16 +263,16 @@ Dictionary GameSingleton::get_province_info_from_index(int32_t index) const { return ret; } -int32_t GameSingleton::get_width() const { +int32_t GameSingleton::get_map_width() const { return game_manager.get_map().get_width(); } -int32_t GameSingleton::get_height() const { +int32_t GameSingleton::get_map_height() const { return game_manager.get_map().get_height(); } -float GameSingleton::get_aspect_ratio() const { - return static_cast(get_width()) / static_cast(get_height()); +float GameSingleton::get_map_aspect_ratio() const { + return static_cast(get_map_width()) / static_cast(get_map_height()); } Ref GameSingleton::get_terrain_texture() const { @@ -289,7 +294,7 @@ Ref GameSingleton::get_province_colour_texture() const { Error GameSingleton::_update_colour_image() { static PackedByteArray colour_data_array; static constexpr int64_t colour_data_array_size = - (static_cast(Province::MAX_INDEX) + 1) * Map::MAPMODE_COLOUR_SIZE; + (static_cast(Province::MAX_INDEX) + 1) * sizeof(Mapmode::base_stripe_t); colour_data_array.resize(colour_data_array_size); Error err = OK; @@ -297,12 +302,16 @@ Error GameSingleton::_update_colour_image() { err = FAILED; } + /* We reshape the list of colours into a square, as each texture dimensions cannot exceed 16384. */ static constexpr int32_t PROVINCE_INDEX_SQRT = 1 << (sizeof(Province::index_t) * 4); if (province_colour_image.is_null()) { province_colour_image.instantiate(); ERR_FAIL_NULL_V_EDMSG(province_colour_image, FAILED, "Failed to create province colour image"); } - province_colour_image->set_data(PROVINCE_INDEX_SQRT, PROVINCE_INDEX_SQRT, false, Image::FORMAT_RGBA8, colour_data_array); + /* Width is doubled as each province has a (base, stripe) colour pair. */ + province_colour_image->set_data( + PROVINCE_INDEX_SQRT * 2, PROVINCE_INDEX_SQRT, false, Image::FORMAT_RGBA8, colour_data_array + ); if (province_colour_texture.is_null()) { province_colour_texture = ImageTexture::create_from_image(province_colour_image); ERR_FAIL_NULL_V_EDMSG(province_colour_texture, FAILED, "Failed to create province colour texture"); @@ -543,7 +552,3 @@ Error GameSingleton::load_defines_compatibility_mode(PackedStringArray const& fi String GameSingleton::search_for_game_path(String hint_path) { return std_to_godot_string(Dataloader::search_for_game_path(godot_to_std_string(hint_path)).string()); } - -String GameSingleton::lookup_file(String const& path) const { - return std_to_godot_string(dataloader.lookup_file(godot_to_std_string(path)).string()); -} diff --git a/extension/src/openvic-extension/singletons/GameSingleton.hpp b/extension/src/openvic-extension/singletons/GameSingleton.hpp index 403fbb6..1346a5f 100644 --- a/extension/src/openvic-extension/singletons/GameSingleton.hpp +++ b/extension/src/openvic-extension/singletons/GameSingleton.hpp @@ -69,8 +69,6 @@ namespace OpenVic { static godot::String search_for_game_path(godot::String hint_path = {}); - godot::String lookup_file(godot::String const& path) const; - /* Post-load/restart game setup - reset the game to post-load state * and (re)generate starting data, e.g. buildings. */ @@ -83,9 +81,9 @@ namespace OpenVic { */ godot::Dictionary get_province_info_from_index(int32_t index) const; - int32_t get_width() const; - int32_t get_height() const; - float get_aspect_ratio() const; + int32_t get_map_width() const; + int32_t get_map_height() const; + float get_map_aspect_ratio() const; /* The cosmetic terrain textures stored in a Texture2DArray. */ diff --git a/extension/src/openvic-extension/utility/Utilities.hpp b/extension/src/openvic-extension/utility/Utilities.hpp index fc106db..752f495 100644 --- a/extension/src/openvic-extension/utility/Utilities.hpp +++ b/extension/src/openvic-extension/utility/Utilities.hpp @@ -42,6 +42,10 @@ namespace OpenVic::Utilities { return { vec.x, vec.y }; } + inline godot::Vector2 to_godot_fvec2(fvec2_t vec) { + return { vec.x, vec.y }; + } + godot::Ref load_godot_image(godot::String const& path); godot::Ref load_godot_font(godot::String const& fnt_path, godot::Ref const& image); diff --git a/game/localisation/en_GB/mapmodes.csv b/game/localisation/en_GB/mapmodes.csv index 2aa4cd2..0372192 100644 --- a/game/localisation/en_GB/mapmodes.csv +++ b/game/localisation/en_GB/mapmodes.csv @@ -3,6 +3,7 @@ mapmode_province;Province mapmode_region;Region mapmode_terrain;Terrain +mapmode_political;Political mapmode_index;Index mapmode_terrain_type;Terrain Type mapmode_rgo;RGO 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/TerrainMap.gdshader b/game/src/Game/GameSession/TerrainMap.gdshader index 852ccc3..ff8708a 100644 --- a/game/src/Game/GameSession/TerrainMap.gdshader +++ b/game/src/Game/GameSession/TerrainMap.gdshader @@ -14,16 +14,29 @@ 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_nearest; +// The number of times the stripe texture should tile vertically +uniform float stripe_tile_factor; 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, vec2 terrain_uv, vec2 stripe_uv) { 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; + 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); + float stripe = texture(stripe_tex, stripe_uv).b; // Stripe mask value - 0 for base, 1 for stripe + vec4 province_colour = mix(province_base_colour, province_stripe_colour, stripe); + + vec3 terrain_colour = texture(terrain_tex, vec3(terrain_uv, float(terrain_index))).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)); + + float mix_val = 0.1 * (float(province_index == hover_index) + float(province_index == selected_index)); return mix(mixed_colour, highlight_colour, mix_val); } @@ -32,15 +45,17 @@ vec3 mix_terrain_colour(vec2 uv) { vec2 pixel_offset = fract(fma(uv, map_size, vec2(0.5))); 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 = vec2(uv.x * map_size.x / map_size.y, uv.y); + + vec2 terrain_uv = unscaled_uv * terrain_tile_factor; + vec2 stripe_uv = unscaled_uv * stripe_tile_factor; 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), + mix(get_terrain_colour(uv, vec2(-1, -1), half_pixel_size, terrain_uv, stripe_uv), + get_terrain_colour(uv, vec2(+1, -1), half_pixel_size, terrain_uv, stripe_uv), pixel_offset.x), + mix(get_terrain_colour(uv, vec2(-1, +1), half_pixel_size, terrain_uv, stripe_uv), + get_terrain_colour(uv, vec2(+1, +1), half_pixel_size, terrain_uv, stripe_uv), pixel_offset.x), pixel_offset.y); } diff --git a/game/src/Game/GlobalClass/ShaderManager.gd b/game/src/Game/GlobalClass/ShaderManager.gd index fd91e31..1af606c 100644 --- a/game/src/Game/GlobalClass/ShaderManager.gd +++ b/game/src/Game/GlobalClass/ShaderManager.gd @@ -8,6 +8,8 @@ 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" func set_up_shader(material : Material, add_cosmetic_textures : bool) -> Error: # Shader Material @@ -46,4 +48,11 @@ func set_up_shader(material : Material, add_cosmetic_textures : bool) -> Error: return FAILED shader_material.set_shader_parameter(param_terrain_tex, terrain_texture) + # Stripe texture + var stripe_texture := AssetManager.get_texture(&"map/terrain/stripes.dds") + if stripe_texture == null: + push_error("Failed to get stripe texture!") + return FAILED + shader_material.set_shader_parameter(param_stripe_tex, stripe_texture) + return OK -- cgit v1.2.3-56-ga3b1 From aefc61a1aff091e31436c60d004531b5905cecba Mon Sep 17 00:00:00 2001 From: hop311 Date: Fri, 17 Nov 2023 18:45:15 +0000 Subject: Cosmetic terrain map colour tinting --- extension/deps/openvic-simulation | 2 +- game/src/Game/GameSession/TerrainMap.gdshader | 72 +++++++++++++++++++++------ game/src/Game/GlobalClass/ShaderManager.gd | 37 ++++++++++---- 3 files changed, 84 insertions(+), 27 deletions(-) (limited to 'game/src/Game') diff --git a/extension/deps/openvic-simulation b/extension/deps/openvic-simulation index 2607fd6..e76336c 160000 --- a/extension/deps/openvic-simulation +++ b/extension/deps/openvic-simulation @@ -1 +1 @@ -Subproject commit 2607fd63b849788e92174161a9cea72141c88f7a +Subproject commit e76336cd92639f4ec71088fc4c80aea4c25528cd diff --git a/game/src/Game/GameSession/TerrainMap.gdshader b/game/src/Game/GameSession/TerrainMap.gdshader index ff8708a..35a108b 100644 --- a/game/src/Game/GameSession/TerrainMap.gdshader +++ b/game/src/Game/GameSession/TerrainMap.gdshader @@ -15,13 +15,23 @@ 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_nearest; +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, vec2 stripe_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)); uint province_index = uvec2_to_uint(province_data.rg); uint terrain_index = province_data.b; @@ -30,33 +40,63 @@ vec3 get_terrain_colour(vec2 uv, vec2 corner, vec2 half_pixel_size, vec2 terrain 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); - float stripe = texture(stripe_tex, stripe_uv).b; // Stripe mask value - 0 for base, 1 for stripe - vec4 province_colour = mix(province_base_colour, province_stripe_colour, stripe); + 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 mixed_colour = mix(terrain_colour, province_colour.rgb, province_colour.a); + 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); +} - float mix_val = 0.1 * (float(province_index == hover_index) + float(province_index == selected_index)); - return mix(mixed_colour, highlight_colour, 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; - // UV coords adjusted to remove squashing caused by normalisation relative to map dimensions. - vec2 unscaled_uv = vec2(uv.x * map_size.x / map_size.y, uv.y); + // UV coords adjusted to remove squashing caused by normalisation relative to map dimensions + vec2 unscaled_uv = denormalise(uv, map_size); - vec2 terrain_uv = unscaled_uv * terrain_tile_factor; 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, stripe_uv), - get_terrain_colour(uv, vec2(+1, -1), half_pixel_size, terrain_uv, stripe_uv), pixel_offset.x), - mix(get_terrain_colour(uv, vec2(-1, +1), half_pixel_size, terrain_uv, stripe_uv), - get_terrain_colour(uv, vec2(+1, +1), half_pixel_size, terrain_uv, stripe_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 1af606c..ace3c3a 100644 --- a/game/src/Game/GlobalClass/ShaderManager.gd +++ b/game/src/Game/GlobalClass/ShaderManager.gd @@ -10,6 +10,16 @@ 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 @@ -21,38 +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) # Stripe texture - var stripe_texture := AssetManager.get_texture(&"map/terrain/stripes.dds") - if stripe_texture == null: - push_error("Failed to get stripe texture!") - return FAILED - shader_material.set_shader_parameter(param_stripe_tex, stripe_texture) + if _set_shader_texture(shader_material, &"map/terrain/stripes.dds", param_stripe_tex) != OK: + ret = FAILED - return OK + # 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 -- cgit v1.2.3-56-ga3b1