aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Spartan322 <Megacake1234@gmail.com>2023-12-30 06:32:13 +0100
committer Spartan322 <Megacake1234@gmail.com>2024-05-07 00:07:50 +0200
commit7def4dd2e7987c20163c6a419bcc0506b5a670d9 (patch)
tree671f5b94ab2f0d9d1a59b7fa11ac393e93101958
parentbf3df0ee900f406a5a2aa56609ecb89c67055351 (diff)
Improve map view and game panel user experience
Minimizes panel mouse obstruction to scripted panel images Prevents map view from hovering inside UI elements Unsets province hover when not over provinces Add `GUINode.click_mask` Prevents mouse interactions not within click_mask Add `GUINode.set_click_mask_from_nodepaths` Generates click_mask from paths relating to GUINode textures Sets nodepaths to MOUSE_FILTER_IGNORE Add CanvasLayer parent to GameSession UI nodes Set mouse_force_pass_scroll_events to GameSession UI nodes Set MapControlPanel mouse_filter to default (MOUSE_FILTER_STOP) Move MapView mouse viewport changes to _input Move MapView _action_drag released check to _input Move MapView processing to _process Remove viewport and window notifications Disable if window is not focused or input is handled: MapView mouse interactions (including edge scrolling and drag panning) MapView province hover Set mouse_filter to MOUSE_FILTER_IGNORE for ProvinceOverviewPanel province_view panel Set ProvinceOverviewPanel click_mask path to `province_view/background` Set mouse_filter to MOUSE_FILTER_IGNORE for Topbar topbar panel Set Topbar click_mask path to `topbar/topbar_bg` and `topbar/topbar_paper`
-rw-r--r--extension/src/openvic-extension/classes/GUINode.cpp159
-rw-r--r--extension/src/openvic-extension/classes/GUINode.hpp30
-rw-r--r--game/src/Game/GameSession/GameSession.tscn70
-rw-r--r--game/src/Game/GameSession/GameSessionMenu.tscn1
-rw-r--r--game/src/Game/GameSession/MapControlPanel/MapControlPanel.tscn2
-rw-r--r--game/src/Game/GameSession/MapView.gd85
-rw-r--r--game/src/Game/GameSession/ProvinceOverviewPanel.gd6
-rw-r--r--game/src/Game/GameSession/Topbar.gd6
-rw-r--r--game/src/Game/Menu/SaveLoadMenu/SaveLoadMenu.tscn1
-rw-r--r--game/src/Game/MusicConductor/MusicPlayer.tscn1
10 files changed, 282 insertions, 79 deletions
diff --git a/extension/src/openvic-extension/classes/GUINode.cpp b/extension/src/openvic-extension/classes/GUINode.cpp
index 73ebb0c..c9af7e2 100644
--- a/extension/src/openvic-extension/classes/GUINode.cpp
+++ b/extension/src/openvic-extension/classes/GUINode.cpp
@@ -1,7 +1,35 @@
#include "GUINode.hpp"
+#include <limits>
+
+#include <godot_cpp/classes/bit_map.hpp>
+#include <godot_cpp/classes/button.hpp>
+#include <godot_cpp/classes/canvas_item.hpp>
+#include <godot_cpp/classes/check_box.hpp>
+#include <godot_cpp/classes/control.hpp>
+#include <godot_cpp/classes/image.hpp>
+#include <godot_cpp/classes/label.hpp>
+#include <godot_cpp/classes/node.hpp>
+#include <godot_cpp/classes/object.hpp>
+#include <godot_cpp/classes/panel.hpp>
+#include <godot_cpp/classes/ref.hpp>
+#include <godot_cpp/classes/style_box.hpp>
#include <godot_cpp/classes/style_box_texture.hpp>
+#include <godot_cpp/classes/texture2d.hpp>
+#include <godot_cpp/classes/texture_progress_bar.hpp>
+#include <godot_cpp/classes/texture_rect.hpp>
+#include <godot_cpp/core/defs.hpp>
+#include <godot_cpp/core/error_macros.hpp>
+#include <godot_cpp/core/object.hpp>
+#include <godot_cpp/core/property_info.hpp>
+#include <godot_cpp/variant/node_path.hpp>
+#include <godot_cpp/variant/rect2.hpp>
+#include <godot_cpp/variant/string.hpp>
+#include <godot_cpp/variant/string_name.hpp>
#include <godot_cpp/variant/utility_functions.hpp>
+#include <godot_cpp/variant/variant.hpp>
+#include <godot_cpp/variant/vector2.hpp>
+#include <godot_cpp/variant/vector2i.hpp>
#include "openvic-extension/utility/ClassBindings.hpp"
#include "openvic-extension/utility/UITools.hpp"
@@ -31,6 +59,15 @@ void GUINode::_bind_methods() {
OV_BIND_METHOD(GUINode::add_gui_element, { "gui_scene", "gui_element", "name" }, DEFVAL(String {}));
OV_BIND_SMETHOD(get_gui_position, { "gui_scene", "gui_position" });
+ OV_BIND_METHOD(GUINode::get_click_mask);
+ OV_BIND_METHOD(GUINode::set_click_mask, { "mask" });
+ ADD_PROPERTY(
+ PropertyInfo(Variant::OBJECT, "click_mask", PROPERTY_HINT_RESOURCE_TYPE, "BitMap"), "set_click_mask", "get_click_mask"
+ );
+
+ OV_BIND_METHOD(GUINode::set_click_mask_from_nodepaths, { "paths" });
+ OV_BIND_METHOD(GUINode::update_click_mask);
+
#define GET_BINDINGS(type, name) \
OV_BIND_SMETHOD(get_##name##_from_node, { "node" }); \
OV_BIND_METHOD(GUINode::get_##name##_from_nodepath, { "path" });
@@ -56,7 +93,7 @@ GUINode::GUINode() {
set_anchors_and_offsets_preset(PRESET_FULL_RECT);
set_h_grow_direction(GROW_DIRECTION_BOTH);
set_v_grow_direction(GROW_DIRECTION_BOTH);
- set_mouse_filter(MOUSE_FILTER_IGNORE);
+ set_mouse_filter(MOUSE_FILTER_STOP);
}
Control* GUINode::generate_gui_element(String const& gui_scene, String const& gui_element, String const& name) {
@@ -196,3 +233,123 @@ String GUINode::format_province_name(String const& province_identifier) {
static const String province_prefix = "PROV";
return province_prefix + province_identifier;
}
+
+Ref<BitMap> GUINode::get_click_mask() const {
+ return _click_mask;
+}
+
+void GUINode::set_click_mask(Ref<BitMap> const& mask) {
+ if (_click_mask == mask) {
+ return;
+ }
+ _click_mask = mask;
+ queue_redraw();
+ update_minimum_size();
+}
+
+bool GUINode::_update_click_mask_for(Ref<Image> const& img, int index) {
+ ERR_FAIL_INDEX_V(index, _mask_controls.size(), false);
+ Control* control = _mask_controls[index];
+ if (!UtilityFunctions::is_instance_valid(control) && !control->is_inside_tree()) {
+ _mask_controls.remove_at(index);
+ return false;
+ }
+ ERR_FAIL_COND_V(img.is_null(), false);
+ Ref<Texture2D> texture = get_texture_from_node(control);
+ ERR_FAIL_COND_V(texture.is_null(), false);
+ Ref<Image> texture_img = texture->get_image();
+ if (img->is_empty()) {
+ img->copy_from(texture_img);
+ } else {
+ if (img->get_format() != texture_img->get_format()) {
+ img->convert(texture_img->get_format());
+ }
+ Vector2i img_size = img->get_size();
+ Vector2i total_size = control->get_screen_position() + texture_img->get_size();
+ Vector2i new_img_size = img_size.max(total_size);
+ if (new_img_size != img_size) {
+ img->crop(new_img_size.x, new_img_size.y);
+ }
+ img->blend_rect(texture_img, texture_img->get_used_rect(), control->get_position());
+ }
+ ERR_FAIL_COND_V(img->is_empty(), false);
+ return true;
+}
+
+void GUINode::update_click_mask() {
+ static constexpr real_t max_real = std::numeric_limits<real_t>::max();
+ static const Point2 max_point { max_real, max_real };
+ if (_mask_controls.size() == 0) {
+ return;
+ }
+
+ if (_click_mask.is_null()) {
+ _click_mask.instantiate();
+ }
+ Ref<Image> img;
+ img.instantiate();
+ Vector2 size = get_size();
+ img->create(size.x, size.y, false, Image::Format::FORMAT_RGBA8);
+ Point2 highest_position = { max_real, max_real };
+ for (int index = 0; index < _mask_controls.size(); index++) {
+ if (!_update_click_mask_for(img, index)) {
+ continue;
+ }
+ Vector2 screen_pos = _mask_controls[index]->get_screen_position();
+ highest_position = highest_position.min(screen_pos);
+ }
+ ERR_FAIL_COND(img.is_null());
+ ERR_FAIL_COND(highest_position == max_point);
+ _texture_region = Rect2(Point2(), img->get_size());
+ _position_rect = Rect2(highest_position, _texture_region.get_size());
+ _click_mask->create_from_image_alpha(img);
+ queue_redraw();
+ update_minimum_size();
+}
+
+void GUINode::set_click_mask_from_nodepaths(TypedArray<NodePath> const& paths) {
+ // TODO: Update to use https://github.com/godotengine/godot/pull/90916
+ // for(godot::Control* control : _mask_controls) {
+ // control->set_mouse_filter(Control::MouseFilter::MOUSE_FILTER_STOP);
+ // }
+ _mask_controls.clear();
+ for (int index = 0; index < paths.size(); index++) {
+ Control* control = _cast_node<Control>(get_node_internal(paths[index]));
+ ERR_CONTINUE(control == nullptr);
+ control->set_mouse_filter(Control::MouseFilter::MOUSE_FILTER_IGNORE);
+ _mask_controls.push_back(control);
+ }
+ update_click_mask();
+}
+
+bool GUINode::_has_point(godot::Vector2 const& p_point) const {
+ if (!_click_mask.is_valid()) {
+ return Control::_has_point(p_point);
+ }
+
+ Point2 point = p_point;
+ Rect2 rect;
+ Size2 mask_size = _click_mask->get_size();
+
+ if (!_position_rect.has_area()) {
+ rect.size = mask_size;
+ } else {
+ // we need to transform the point from our scaled / translated image back to our mask image
+ Point2 ofs = _position_rect.position;
+ Size2 scale = mask_size / _position_rect.size;
+
+ // offset and scale the new point position to adjust it to the bitmask size
+ point -= ofs;
+ point *= scale;
+
+ // finally, we need to check if the point is inside a rectangle with a position >= 0,0 and a size <= mask_size
+ rect.position = _texture_region.position.min(Point2 {});
+ rect.size = mask_size.min(_texture_region.size);
+ }
+
+ if (!rect.has_point(point)) {
+ return false;
+ }
+
+ return _click_mask->get_bitv(point);
+}
diff --git a/extension/src/openvic-extension/classes/GUINode.hpp b/extension/src/openvic-extension/classes/GUINode.hpp
index 3dbe403..8d926cc 100644
--- a/extension/src/openvic-extension/classes/GUINode.hpp
+++ b/extension/src/openvic-extension/classes/GUINode.hpp
@@ -1,17 +1,27 @@
#pragma once
+#include <godot_cpp/classes/bit_map.hpp>
#include <godot_cpp/classes/button.hpp>
#include <godot_cpp/classes/check_box.hpp>
+#include <godot_cpp/classes/control.hpp>
+#include <godot_cpp/classes/image.hpp>
+#include <godot_cpp/classes/input_event.hpp>
#include <godot_cpp/classes/label.hpp>
+#include <godot_cpp/classes/node.hpp>
#include <godot_cpp/classes/panel.hpp>
+#include <godot_cpp/classes/ref.hpp>
+#include <godot_cpp/classes/texture2d.hpp>
#include <godot_cpp/classes/texture_progress_bar.hpp>
#include <godot_cpp/classes/texture_rect.hpp>
+#include <godot_cpp/templates/vector.hpp>
+#include <godot_cpp/variant/node_path.hpp>
+#include <godot_cpp/variant/rect2.hpp>
+#include <godot_cpp/variant/string.hpp>
+#include <godot_cpp/variant/vector2.hpp>
-#include <openvic-simulation/interface/GUI.hpp>
-
-#include "openvic-extension/classes/GFXSpriteTexture.hpp"
#include "openvic-extension/classes/GFXMaskedFlagTexture.hpp"
#include "openvic-extension/classes/GFXPieChartTexture.hpp"
+#include "openvic-extension/classes/GFXSpriteTexture.hpp"
#include "openvic-extension/classes/GUIListBox.hpp"
#include "openvic-extension/classes/GUIOverlappingElementsBox.hpp"
#include "openvic-extension/classes/GUIScrollbar.hpp"
@@ -20,6 +30,11 @@ namespace OpenVic {
class GUINode : public godot::Control {
GDCLASS(GUINode, godot::Control)
+ godot::Ref<godot::BitMap> _click_mask;
+ godot::Vector<Control*> _mask_controls;
+ godot::Rect2 _texture_region;
+ godot::Rect2 _position_rect;
+
protected:
static void _bind_methods();
@@ -73,5 +88,14 @@ namespace OpenVic {
static godot::String int_to_formatted_string(int64_t val);
static godot::String float_to_formatted_string(float val, int32_t decimal_places);
static godot::String format_province_name(godot::String const& province_identifier);
+
+ godot::Ref<godot::BitMap> get_click_mask() const;
+ void set_click_mask(godot::Ref<godot::BitMap> const& mask);
+
+ void set_click_mask_from_nodepaths(godot::TypedArray<godot::NodePath> const& paths);
+ bool _update_click_mask_for(godot::Ref<godot::Image> const& img, int index);
+ void update_click_mask();
+
+ bool _has_point(godot::Vector2 const& point) const override;
};
}
diff --git a/game/src/Game/GameSession/GameSession.tscn b/game/src/Game/GameSession/GameSession.tscn
index d2fc3a3..343ddfe 100644
--- a/game/src/Game/GameSession/GameSession.tscn
+++ b/game/src/Game/GameSession/GameSession.tscn
@@ -28,63 +28,76 @@ grow_horizontal = 2
grow_vertical = 2
mouse_filter = 2
script = ExtResource("1_eklvp")
-_game_session_menu = NodePath("GameSessionMenu")
+_game_session_menu = NodePath("UICanvasLayer/UI/GameSessionMenu")
[node name="MapView" parent="." instance=ExtResource("4_xkg5j")]
-[node name="ProvinceOverviewPanel" type="GUINode" parent="."]
+[node name="UICanvasLayer" type="CanvasLayer" parent="."]
+
+[node name="UI" type="Control" parent="UICanvasLayer"]
+layout_mode = 3
+anchors_preset = 15
+anchor_right = 1.0
+anchor_bottom = 1.0
+grow_horizontal = 2
+grow_vertical = 2
+mouse_filter = 2
+
+[node name="ProvinceOverviewPanel" type="GUINode" parent="UICanvasLayer/UI"]
layout_mode = 1
anchors_preset = 15
+mouse_force_pass_scroll_events = false
script = ExtResource("5_lfv8l")
-[node name="Topbar" type="GUINode" parent="."]
+[node name="Topbar" type="GUINode" parent="UICanvasLayer/UI"]
layout_mode = 1
anchors_preset = 15
+mouse_force_pass_scroll_events = false
script = ExtResource("4_2kbih")
-[node name="ProductionMenu" type="GUINode" parent="Topbar"]
+[node name="ProductionMenu" type="GUINode" parent="UICanvasLayer/UI/Topbar"]
layout_mode = 1
anchors_preset = 15
script = ExtResource("5_16755")
-[node name="BudgetMenu" type="GUINode" parent="Topbar"]
+[node name="BudgetMenu" type="GUINode" parent="UICanvasLayer/UI/Topbar"]
layout_mode = 1
anchors_preset = 15
script = ExtResource("6_vninv")
-[node name="TechnologyMenu" type="GUINode" parent="Topbar"]
+[node name="TechnologyMenu" type="GUINode" parent="UICanvasLayer/UI/Topbar"]
layout_mode = 1
anchors_preset = 15
script = ExtResource("7_r712c")
-[node name="PoliticsMenu" type="GUINode" parent="Topbar"]
+[node name="PoliticsMenu" type="GUINode" parent="UICanvasLayer/UI/Topbar"]
layout_mode = 1
anchors_preset = 15
script = ExtResource("8_ppdek")
-[node name="PopulationMenu" type="GUINode" parent="Topbar"]
+[node name="PopulationMenu" type="GUINode" parent="UICanvasLayer/UI/Topbar"]
layout_mode = 1
anchors_preset = 15
script = ExtResource("10_laee7")
-[node name="TradeMenu" type="GUINode" parent="Topbar"]
+[node name="TradeMenu" type="GUINode" parent="UICanvasLayer/UI/Topbar"]
layout_mode = 1
anchors_preset = 15
script = ExtResource("10_mv1r6")
-[node name="DiplomacyMenu" type="GUINode" parent="Topbar"]
+[node name="DiplomacyMenu" type="GUINode" parent="UICanvasLayer/UI/Topbar"]
layout_mode = 1
anchors_preset = 15
script = ExtResource("11_fu7ys")
-[node name="MilitaryMenu" type="GUINode" parent="Topbar"]
+[node name="MilitaryMenu" type="GUINode" parent="UICanvasLayer/UI/Topbar"]
layout_mode = 1
anchors_preset = 15
script = ExtResource("12_6h6nc")
-[node name="MapControlPanel" parent="." instance=ExtResource("3_afh6d")]
+[node name="MapControlPanel" parent="UICanvasLayer/UI" instance=ExtResource("3_afh6d")]
layout_mode = 1
-anchors_preset = 3
+anchors_preset = -1
anchor_left = 1.0
anchor_top = 1.0
anchor_right = 1.0
@@ -92,7 +105,7 @@ anchor_bottom = 1.0
grow_horizontal = 0
grow_vertical = 0
-[node name="GameSessionMenu" parent="." instance=ExtResource("3_bvmqh")]
+[node name="GameSessionMenu" parent="UICanvasLayer/UI" instance=ExtResource("3_bvmqh")]
visible = false
layout_mode = 1
anchors_preset = 8
@@ -107,11 +120,12 @@ offset_bottom = 165.0
grow_horizontal = 2
grow_vertical = 2
-[node name="OptionsMenu" parent="." instance=ExtResource("6_p5mnx")]
+[node name="OptionsMenu" parent="UICanvasLayer/UI" instance=ExtResource("6_p5mnx")]
visible = false
layout_mode = 1
+mouse_force_pass_scroll_events = false
-[node name="SaveLoadMenu" parent="." instance=ExtResource("8_4g7ko")]
+[node name="SaveLoadMenu" parent="UICanvasLayer/UI" instance=ExtResource("8_4g7ko")]
visible = false
layout_mode = 1
anchors_preset = -1
@@ -120,7 +134,7 @@ anchor_right = 0.5
offset_left = -640.0
offset_right = 640.0
-[node name="MusicPlayer" parent="." instance=ExtResource("2_kt6aa")]
+[node name="MusicPlayer" parent="UICanvasLayer/UI" instance=ExtResource("2_kt6aa")]
layout_mode = 1
anchors_preset = 1
anchor_left = 1.0
@@ -129,15 +143,13 @@ offset_left = -150.0
offset_right = 0.0
grow_horizontal = 0
-[connection signal="map_view_camera_changed" from="MapView" to="MapControlPanel" method="_on_map_view_camera_changed"]
-[connection signal="game_session_menu_button_pressed" from="MapControlPanel" to="." method="_on_game_session_menu_button_pressed"]
-[connection signal="minimap_clicked" from="MapControlPanel" to="MapView" method="_on_minimap_clicked"]
-[connection signal="mouse_entered" from="MapControlPanel" to="MapView" method="_on_mouse_exited_viewport"]
-[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="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"]
-[connection signal="back_button_pressed" from="OptionsMenu" to="MapView" method="enable_processing"]
-[connection signal="back_button_pressed" from="OptionsMenu" to="OptionsMenu" method="hide"]
+[connection signal="map_view_camera_changed" from="MapView" to="UICanvasLayer/UI/MapControlPanel" method="_on_map_view_camera_changed"]
+[connection signal="game_session_menu_button_pressed" from="UICanvasLayer/UI/MapControlPanel" to="." method="_on_game_session_menu_button_pressed"]
+[connection signal="minimap_clicked" from="UICanvasLayer/UI/MapControlPanel" to="MapView" method="_on_minimap_clicked"]
+[connection signal="zoom_in_button_pressed" from="UICanvasLayer/UI/MapControlPanel" to="MapView" method="zoom_in"]
+[connection signal="zoom_out_button_pressed" from="UICanvasLayer/UI/MapControlPanel" to="MapView" method="zoom_out"]
+[connection signal="load_button_pressed" from="UICanvasLayer/UI/GameSessionMenu" to="UICanvasLayer/UI/SaveLoadMenu" method="show_for_load"]
+[connection signal="options_button_pressed" from="UICanvasLayer/UI/GameSessionMenu" to="UICanvasLayer/UI/OptionsMenu" method="show"]
+[connection signal="save_button_pressed" from="UICanvasLayer/UI/GameSessionMenu" to="UICanvasLayer/UI/SaveLoadMenu" method="show_for_save"]
+[connection signal="back_button_pressed" from="UICanvasLayer/UI/OptionsMenu" to="MapView" method="enable_processing"]
+[connection signal="back_button_pressed" from="UICanvasLayer/UI/OptionsMenu" to="UICanvasLayer/UI/OptionsMenu" method="hide"]
diff --git a/game/src/Game/GameSession/GameSessionMenu.tscn b/game/src/Game/GameSession/GameSessionMenu.tscn
index af81f09..9885c7b 100644
--- a/game/src/Game/GameSession/GameSessionMenu.tscn
+++ b/game/src/Game/GameSession/GameSessionMenu.tscn
@@ -7,6 +7,7 @@
[node name="GameSessionMenu" type="PanelContainer" node_paths=PackedStringArray("_main_menu_dialog", "_quit_dialog")]
process_mode = 3
editor_description = "UI-68"
+mouse_force_pass_scroll_events = false
theme = ExtResource("1_2onog")
theme_type_variation = &"SessionPanel"
script = ExtResource("1_usq6o")
diff --git a/game/src/Game/GameSession/MapControlPanel/MapControlPanel.tscn b/game/src/Game/GameSession/MapControlPanel/MapControlPanel.tscn
index 6731358..7578c82 100644
--- a/game/src/Game/GameSession/MapControlPanel/MapControlPanel.tscn
+++ b/game/src/Game/GameSession/MapControlPanel/MapControlPanel.tscn
@@ -17,7 +17,7 @@ events = [SubResource("InputEventAction_5nck3")]
[node name="MapControlPanel" type="PanelContainer" node_paths=PackedStringArray("_mapmodes_grid")]
editor_description = "SS-103, UI-548"
-mouse_filter = 1
+mouse_force_pass_scroll_events = false
script = ExtResource("1_ign64")
_mapmodes_grid = NodePath("MapPanelMargin/MapPanelList/MapDisplayList/MapmodesGrid")
diff --git a/game/src/Game/GameSession/MapView.gd b/game/src/Game/GameSession/MapView.gd
index 2ab7c34..a83c790 100644
--- a/game/src/Game/GameSession/MapView.gd
+++ b/game/src/Game/GameSession/MapView.gd
@@ -16,14 +16,13 @@ const _action_click : StringName = &"map_click"
@export var _camera : Camera3D
-@export var _cardinal_move_speed : float = 1.0
+@export var _cardinal_move_speed : float = 2.5
@export var _edge_move_threshold: float = 0.01
@export var _edge_move_speed: float = 2.5
var _drag_anchor : Vector2
var _drag_active : bool = false
var _mouse_over_viewport : bool = true
-var _window_in_focus : bool = true
@export var _zoom_target_min : float = 0.10
@export var _zoom_target_max : float = 5.0
@@ -122,17 +121,6 @@ func _ready() -> void:
_map_text.generate_map_names()
-func _notification(what : int) -> void:
- match what:
- NOTIFICATION_WM_MOUSE_ENTER: # Mouse inside window
- _on_mouse_entered_viewport()
- NOTIFICATION_WM_MOUSE_EXIT: # Mouse out of window
- _on_mouse_exited_viewport()
- NOTIFICATION_WM_WINDOW_FOCUS_IN: # Window comes into focus
- _on_window_entered_focus()
- NOTIFICATION_WM_WINDOW_FOCUS_OUT: # Window goes out of focus
- _on_window_exited_focus()
-
func _world_to_map_coords(pos : Vector3) -> Vector2:
return (Vector2(pos.x, pos.z) - _map_mesh_corner) / _map_mesh_dims
@@ -163,14 +151,34 @@ func zoom_out() -> void:
# cursor location. I'm not sure if we want to preserve this behavior.
_zoom_position = Vector2()
+func set_hovered_province_index(hover_index : int) -> void:
+ _map_shader_material.set_shader_parameter(GameLoader.ShaderManager.param_hover_index, hover_index)
+
+func set_hovered_province_at(pos : Vector2) -> void:
+ var hover_index := GameSingleton.get_province_index_from_uv_coords(pos)
+ set_hovered_province_index(hover_index)
+
+func unset_hovered_province() -> void:
+ set_hovered_province_index(0)
+
func _on_province_selected(index : int) -> void:
_map_shader_material.set_shader_parameter(GameLoader.ShaderManager.param_selected_index, index)
print("Province selected with index: ", index)
+func _input(event : InputEvent) -> void:
+ if event is InputEventMouseMotion:
+ _mouse_pos_viewport = get_window().get_mouse_position()
+ elif _drag_active and event.is_action_released(_action_drag):
+ _drag_active = false
+
# REQUIREMENTS
# * SS-31
func _unhandled_input(event : InputEvent) -> void:
- if event.is_action_pressed(_action_click):
+ if event is InputEventMouseMotion:
+ _mouse_over_viewport = true
+ set_hovered_province_at(_viewport_to_map_coords(_mouse_pos_viewport))
+
+ elif event.is_action_pressed(_action_click):
if _mouse_over_viewport:
# Check if the mouse is outside of bounds
if _map_mesh.is_valid_uv_coord(_mouse_pos_map):
@@ -182,17 +190,16 @@ func _unhandled_input(event : InputEvent) -> void:
push_warning("Drag being activated while already active!")
_drag_active = true
_drag_anchor = _mouse_pos_map
- elif event.is_action_released(_action_drag):
- if not _drag_active:
- push_warning("Drag being deactivated while already not active!")
- _drag_active = false
elif event.is_action_pressed(_action_zoom_in, true):
zoom_in()
elif event.is_action_pressed(_action_zoom_out, true):
zoom_out()
-func _physics_process(delta : float) -> void:
- _mouse_pos_viewport = get_viewport().get_mouse_position()
+func _process(delta : float) -> void:
+ if _is_viewport_inactive():
+ _mouse_over_viewport = false
+ unset_hovered_province()
+
_viewport_dims = Vector2(Resolution.get_current_resolution())
# Process movement
_movement_process(delta)
@@ -222,7 +229,7 @@ func _movement_process(delta : float) -> void:
# REQUIREMENTS
# * UIFUN-125
func _edge_scrolling_vector() -> Vector2:
- if not _window_in_focus:
+ if _is_viewport_inactive():
return Vector2()
var mouse_vector := _mouse_pos_viewport * GuiScale.get_current_guiscale() / _viewport_dims - Vector2(0.5, 0.5)
# Only scroll if outside the move threshold.
@@ -233,11 +240,12 @@ func _edge_scrolling_vector() -> Vector2:
# REQUIREMENTS
# * SS-75
func _cardinal_movement_vector() -> Vector2:
- var move := Vector2(
- float(Input.is_action_pressed(_action_east)) - float(Input.is_action_pressed(_action_west)),
- float(Input.is_action_pressed(_action_south)) - float(Input.is_action_pressed(_action_north))
- )
- return move * _cardinal_move_speed
+ return Input.get_vector(
+ _action_west,
+ _action_east,
+ _action_north,
+ _action_south
+ ) * _cardinal_move_speed
func _clamp_over_map() -> void:
_camera.position.x = _map_mesh_corner.x + fposmod(_camera.position.x - _map_mesh_corner.x, _map_mesh_dims.x)
@@ -291,23 +299,7 @@ func _update_minimap_viewport() -> void:
map_view_camera_changed.emit(near_left, far_left, far_right, near_right)
func _update_mouse_map_position() -> void:
- if _mouse_over_viewport:
- _mouse_pos_map = _viewport_to_map_coords(_mouse_pos_viewport)
- var hover_index := GameSingleton.get_province_index_from_uv_coords(_mouse_pos_map)
- _map_shader_material.set_shader_parameter(GameLoader.ShaderManager.param_hover_index, hover_index)
-
-func _on_mouse_entered_viewport() -> void:
- _mouse_over_viewport = true
-
-func _on_mouse_exited_viewport() -> void:
- _mouse_over_viewport = false
- _map_shader_material.set_shader_parameter(GameLoader.ShaderManager.param_hover_index, 0)
-
-func _on_window_entered_focus() -> void:
- _window_in_focus = true
-
-func _on_window_exited_focus() -> void:
- _window_in_focus = false
+ _mouse_pos_map = _viewport_to_map_coords(_mouse_pos_viewport)
func _on_minimap_clicked(pos_clicked : Vector2) -> void:
pos_clicked *= _map_mesh_dims
@@ -315,10 +307,13 @@ func _on_minimap_clicked(pos_clicked : Vector2) -> void:
_camera.position.z = pos_clicked.y
_clamp_over_map()
+func _is_viewport_inactive() -> bool:
+ return not get_window().has_focus() or get_window().is_input_handled()
+
func enable_processing() -> void:
set_process_unhandled_input(true)
- set_physics_process(true)
+ set_process(true)
func disable_processing() -> void:
set_process_unhandled_input(false)
- set_physics_process(false)
+ set_process(false)
diff --git a/game/src/Game/GameSession/ProvinceOverviewPanel.gd b/game/src/Game/GameSession/ProvinceOverviewPanel.gd
index 13e7111..42f6765 100644
--- a/game/src/Game/GameSession/ProvinceOverviewPanel.gd
+++ b/game/src/Game/GameSession/ProvinceOverviewPanel.gd
@@ -125,6 +125,12 @@ func _ready() -> void:
push_error("Failed to generate province overview panel!")
return
+ # Disables all consuming invisible panel
+ var prov_view := get_panel_from_nodepath(^"./province_view")
+ if prov_view:
+ prov_view.mouse_filter = Control.MOUSE_FILTER_IGNORE
+ set_click_mask_from_nodepaths([^"./province_view/background"])
+
var close_button : Button = get_button_from_nodepath(^"./province_view/close_button")
if close_button:
close_button.pressed.connect(_on_close_button_pressed)
diff --git a/game/src/Game/GameSession/Topbar.gd b/game/src/Game/GameSession/Topbar.gd
index 92ee75a..8da15e0 100644
--- a/game/src/Game/GameSession/Topbar.gd
+++ b/game/src/Game/GameSession/Topbar.gd
@@ -27,6 +27,12 @@ func _ready() -> void:
const player_country : String = "SLV"
+ # Disables all consuming invisible panel
+ var topbar := get_panel_from_nodepath(^"./topbar")
+ if topbar:
+ topbar.mouse_filter = Control.MOUSE_FILTER_IGNORE
+ set_click_mask_from_nodepaths([^"./topbar/topbar_bg", ^"./topbar/topbar_paper"])
+
# Player country info
var player_flag_texture : GFXMaskedFlagTexture = get_gfx_masked_flag_texture_from_nodepath(^"./topbar/player_flag")
if player_flag_texture:
diff --git a/game/src/Game/Menu/SaveLoadMenu/SaveLoadMenu.tscn b/game/src/Game/Menu/SaveLoadMenu/SaveLoadMenu.tscn
index adc9bdc..38b915c 100644
--- a/game/src/Game/Menu/SaveLoadMenu/SaveLoadMenu.tscn
+++ b/game/src/Game/Menu/SaveLoadMenu/SaveLoadMenu.tscn
@@ -33,6 +33,7 @@ _overwrite_dialog = NodePath("OverwriteDialog")
[node name="SaveLoadPanel" type="PanelContainer" parent="."]
layout_mode = 2
+mouse_force_pass_scroll_events = false
[node name="SaveLoadList" type="VBoxContainer" parent="SaveLoadPanel"]
layout_mode = 2
diff --git a/game/src/Game/MusicConductor/MusicPlayer.tscn b/game/src/Game/MusicConductor/MusicPlayer.tscn
index 27bb476..ef57eac 100644
--- a/game/src/Game/MusicConductor/MusicPlayer.tscn
+++ b/game/src/Game/MusicConductor/MusicPlayer.tscn
@@ -21,6 +21,7 @@ editor_description = "UI-105, UI-107, UI-110, UIFUN-92"
custom_minimum_size = Vector2(150, 0)
layout_mode = 2
focus_mode = 0
+mouse_force_pass_scroll_events = false
alignment = 1
text_overrun_behavior = 3
fit_to_longest_item = false