From d2559c72de61955ec610cd3ec5954f2ee6a647ec Mon Sep 17 00:00:00 2001 From: copygirl Date: Mon, 10 May 2021 19:19:11 +0200 Subject: [PATCH] Add radial menu selection Pressing middle mouse now shows a radial menu HUD element that allows selecting active controlled element. At the moment there only is "Creative Building" but in the future you may be able to select weapons and such. Currently not networked. - Add IntegratedServer to ClientScene - Prevent _Draw from being called by making Player invisible on server - Use _UnhandledInput in CreativeBuilding - Add Cursor.ScreenPosition property --- project.godot | 5 ++ scene/ClientScene.tscn | 41 +++++++++-- scene/Player.tscn | 12 +++- src/CreativeBuilding.cs | 61 ++++++++-------- src/Cursor.cs | 5 +- src/EscapeMenu.cs | 4 +- src/EscapeMenuMultiplayer.cs | 49 +++++-------- src/{Network => IO}/WorldSave.cs | 0 src/Network/IntegratedServer.cs | 6 +- src/Objects/LocalPlayer.cs | 1 + src/Objects/Player.cs | 3 + src/RadialMenu.cs | 115 +++++++++++++++++++++++++++++++ src/Scenes/Client.cs | 6 +- src/World.cs | 2 +- 14 files changed, 236 insertions(+), 74 deletions(-) rename src/{Network => IO}/WorldSave.cs (100%) create mode 100644 src/RadialMenu.cs diff --git a/project.godot b/project.godot index e4e204e..f53cc80 100644 --- a/project.godot +++ b/project.godot @@ -78,6 +78,11 @@ move_jump={ , Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":1,"pressure":0.0,"pressed":false,"script":null) ] } +interact_select={ +"deadzone": 0.5, +"events": [ Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"button_mask":0,"position":Vector2( 0, 0 ),"global_position":Vector2( 0, 0 ),"factor":1.0,"button_index":3,"pressed":false,"doubleclick":false,"script":null) + ] +} interact_place={ "deadzone": 0.5, "events": [ Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"button_mask":0,"position":Vector2( 0, 0 ),"global_position":Vector2( 0, 0 ),"factor":1.0,"button_index":1,"pressed":false,"doubleclick":false,"script":null) diff --git a/scene/ClientScene.tscn b/scene/ClientScene.tscn index cdd2d76..156907d 100644 --- a/scene/ClientScene.tscn +++ b/scene/ClientScene.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=9 format=2] +[gd_scene load_steps=12 format=2] [ext_resource path="res://scene/GameScene.tscn" type="PackedScene" id=1] [ext_resource path="res://src/Cursor.cs" type="Script" id=2] @@ -8,18 +8,26 @@ [ext_resource path="res://src/Viewport.cs" type="Script" id=6] [ext_resource path="res://scene/EscapeMenu.tscn" type="PackedScene" id=7] [ext_resource path="res://src/Scenes/Client.cs" type="Script" id=8] +[ext_resource path="res://src/Network/IntegratedServer.cs" type="Script" id=9] +[ext_resource path="res://ui_theme.tres" type="Theme" id=10] +[ext_resource path="res://src/RadialMenu.cs" type="Script" id=11] [node name="Client" instance=ExtResource( 1 )] script = ExtResource( 8 ) +IntegratedServerPath = NodePath("IntegratedServer") CursorPath = NodePath("CursorLayer/Cursor") -[node name="Viewport" type="Node" parent="." index="0"] +[node name="IntegratedServer" type="Node" parent="." index="0"] +script = ExtResource( 9 ) + +[node name="Viewport" type="Node" parent="." index="1"] script = ExtResource( 6 ) -[node name="Background" type="TextureRect" parent="." index="1"] +[node name="Background" type="TextureRect" parent="." index="2"] modulate = Color( 0.278431, 0.286275, 0.301961, 1 ) margin_right = 1280.0 margin_bottom = 720.0 +mouse_filter = 2 texture = ExtResource( 4 ) stretch_mode = 2 script = ExtResource( 5 ) @@ -28,12 +36,33 @@ __meta__ = { "_edit_use_anchors_": false } -[node name="HUD" type="CanvasLayer" parent="." index="3"] +[node name="HUD" type="CanvasLayer" parent="." index="4"] + +[node name="RadialMenu" type="Node2D" parent="HUD" index="0"] +visible = false +script = ExtResource( 11 ) + +[node name="ActiveName" type="Label" parent="HUD/RadialMenu" index="0"] +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +margin_left = -36.0 +margin_top = -16.0 +margin_right = 36.0 +margin_bottom = 16.0 +theme = ExtResource( 10 ) +align = 1 +valign = 1 +autowrap = true +__meta__ = { +"_edit_use_anchors_": false +} -[node name="EscapeMenu" parent="HUD" index="0" instance=ExtResource( 7 )] +[node name="EscapeMenu" parent="HUD" index="1" instance=ExtResource( 7 )] visible = false -[node name="CursorLayer" type="CanvasLayer" parent="." index="4"] +[node name="CursorLayer" type="CanvasLayer" parent="." index="5"] layer = 2 follow_viewport_enable = true diff --git a/scene/Player.tscn b/scene/Player.tscn index beaeb26..c65acd6 100644 --- a/scene/Player.tscn +++ b/scene/Player.tscn @@ -1,9 +1,10 @@ -[gd_scene load_steps=6 format=2] +[gd_scene load_steps=7 format=2] [ext_resource path="res://ui_theme.tres" type="Theme" id=1] [ext_resource path="res://gfx/player.png" type="Texture" id=2] [ext_resource path="res://src/Objects/Player.cs" type="Script" id=3] [ext_resource path="res://src/CreativeBuilding.cs" type="Script" id=4] +[ext_resource path="res://gfx/block.png" type="Texture" id=6] [sub_resource type="CircleShape2D" id=1] radius = 8.0 @@ -38,5 +39,12 @@ __meta__ = { z_index = -5 texture = ExtResource( 2 ) -[node name="CreativeBuilding" type="Node2D" parent="."] +[node name="Items" type="Node2D" parent="."] + +[node name="Creative Building" type="Node2D" parent="Items"] +visible = false script = ExtResource( 4 ) + +[node name="Icon" type="Sprite" parent="Items/Creative Building"] +visible = false +texture = ExtResource( 6 ) diff --git a/src/CreativeBuilding.cs b/src/CreativeBuilding.cs index 78bf99b..26c7495 100644 --- a/src/CreativeBuilding.cs +++ b/src/CreativeBuilding.cs @@ -30,38 +30,43 @@ public class CreativeBuilding : Node2D _blockTex = GD.Load("res://gfx/block.png"); Cursor = this.GetClient()?.Cursor; - Player = GetParent(); + Player = GetParent().GetParent(); + } + + public override void _UnhandledInput(InputEvent ev) + { + if (!(Player is LocalPlayer) || !Visible) return; + + if (ev.IsActionPressed("interact_place")) { + GetTree().SetInputAsHandled(); + _currentMode = (((_currentMode == null) && _canBuild) ? BuildMode.Placing : (BuildMode?)null); + } + if (ev.IsActionPressed("interact_break")) { + GetTree().SetInputAsHandled(); + _currentMode = ((_currentMode == null) ? BuildMode.Breaking : (BuildMode?)null); + } + // NOTE: These ternary operations require extra brackets for some + // reason or else the syntax highlighting in VS Code breaks?! } public override void _Process(float delta) { if (!(Player is LocalPlayer)) return; - Update(); // Make sure _Draw is being called. + if (!Visible) _currentMode = null; + + if (_currentMode == BuildMode.Placing) { + if (!_canBuild) _currentMode = null; + else if (!Input.IsActionPressed("interact_place")) { + RpcId(1, nameof(PlaceLine), _startPos.X, _startPos.Y, _direction, _length); + _currentMode = null; + } + } - if (EscapeMenu.Instance.Visible || !Cursor.Visible) - { _currentMode = null; return; } - - switch (_currentMode) { - case null: - if (Input.IsActionJustPressed("interact_place")) - if (_canBuild) _currentMode = BuildMode.Placing; - if (Input.IsActionJustPressed("interact_break")) - _currentMode = BuildMode.Breaking; - break; - case BuildMode.Placing: - if (Input.IsActionJustPressed("interact_break")) _currentMode = null; - else if (!Input.IsActionPressed("interact_place")) { - if (_canBuild) RpcId(1, nameof(PlaceLine), _startPos.X, _startPos.Y, _direction, _length); - _currentMode = null; - } - break; - case BuildMode.Breaking: - if (Input.IsActionJustPressed("interact_place")) _currentMode = null; - else if (!Input.IsActionPressed("interact_break")) { - RpcId(1, nameof(BreakLine), _startPos.X, _startPos.Y, _direction, _length); - _currentMode = null; - } - break; + if (_currentMode == BuildMode.Breaking) { + if (!Input.IsActionPressed("interact_break")) { + RpcId(1, nameof(BreakLine), _startPos.X, _startPos.Y, _direction, _length); + _currentMode = null; + } } if (_currentMode != null) { @@ -77,11 +82,13 @@ public class CreativeBuilding : Node2D var world = this.GetWorld(); bool IsBlockAt(BlockPos pos) => world.GetBlockAt(pos) != null; _canBuild = !IsBlockAt(_startPos) && Facings.All.Any(pos => IsBlockAt(_startPos + pos.ToBlockPos())); + + Update(); // Make sure _Draw is being called. } public override void _Draw() { - if ((this.GetGame() is Server) || !Cursor.Visible || EscapeMenu.Instance.Visible) return; + if (!Cursor.Visible || EscapeMenu.Instance.Visible) return; var green = Color.FromHsv(1.0F / 3, 1.0F, 1.0F, 0.4F); var red = Color.FromHsv(0.0F, 1.0F, 1.0F, 0.4F); diff --git a/src/Cursor.cs b/src/Cursor.cs index 48214b4..1da9c34 100644 --- a/src/Cursor.cs +++ b/src/Cursor.cs @@ -2,6 +2,8 @@ using Godot; public class Cursor : Node2D { + public Vector2 ScreenPosition { get; private set; } + public override void _Ready() { Input.SetMouseMode(Input.MouseMode.Hidden); @@ -19,6 +21,7 @@ public class Cursor : Node2D public override void _Process(float delta) { - Position = GetGlobalMousePosition() - GetViewport().CanvasTransform.origin; + ScreenPosition = GetGlobalMousePosition(); + Position = ScreenPosition - GetViewport().CanvasTransform.origin; } } diff --git a/src/EscapeMenu.cs b/src/EscapeMenu.cs index c9416ce..9176d41 100644 --- a/src/EscapeMenu.cs +++ b/src/EscapeMenu.cs @@ -15,9 +15,7 @@ public class EscapeMenu : Control } public override void _UnhandledInput(InputEvent @event) - { - if (@event.IsActionPressed("ui_menu")) Toggle(); - } + { if (@event.IsActionPressed("ui_menu")) Toggle(); } public void Toggle() diff --git a/src/EscapeMenuMultiplayer.cs b/src/EscapeMenuMultiplayer.cs index cf03e08..913c19f 100644 --- a/src/EscapeMenuMultiplayer.cs +++ b/src/EscapeMenuMultiplayer.cs @@ -19,8 +19,6 @@ public class EscapeMenuMultiplayer : Container public Button ClientDisConnect { get; private set; } public LineEdit ClientAddress { get; private set; } - public IntegratedServer IntegratedServer { get; private set; } - public override void _Ready() { Status = GetNode