diff --git a/3D/MapScenes/TestLevel.tscn b/3D/MapScenes/TestLevel.tscn index 17fbe8b4..c13d6775 100644 --- a/3D/MapScenes/TestLevel.tscn +++ b/3D/MapScenes/TestLevel.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=490 format=4 uid="uid://c8gtrjf2xeue7"] +[gd_scene load_steps=491 format=4 uid="uid://c8gtrjf2xeue7"] [ext_resource type="Script" uid="uid://kno58homctew" path="res://addons/func_godot/src/map/func_godot_map.gd" id="1_n6h0p"] [ext_resource type="Resource" uid="uid://cx41lsryg5wpm" path="res://3D/TrenchBroom/map_settings.tres" id="2_i0sba"] @@ -37,6 +37,7 @@ [ext_resource type="Script" uid="uid://crjplbs250g75" path="res://3D/TrenchBroom/EntityScripts/Lights/light_spot.gd" id="31_c2mph"] [ext_resource type="Material" uid="uid://l3g1l0y47c7r" path="res://textures/Manual/Electric_Panel_Wall.tres" id="32_k4tgc"] [ext_resource type="PackedScene" uid="uid://c2enjjxlfb5or" path="res://3D/Scenes/Props/barrel_3d.tscn" id="33_8pgky"] +[ext_resource type="PackedScene" uid="uid://du6hlcoq0iip4" path="res://3D/Scenes/Props/control_pad_3d.tscn" id="35_c4mw0"] [ext_resource type="Script" uid="uid://cyr7ypanl8drq" path="res://Scripts/Actors/Elevator3D.cs" id="36_3x0wn"] [ext_resource type="PackedScene" uid="uid://cq6tw87ei4by3" path="res://3D/Scenes/Props/elevator_3d.tscn" id="36_b3evc"] [ext_resource type="PackedScene" uid="uid://bhh7qq1plw53i" path="res://Scenes/Interactable/AreaTrigger3D.tscn" id="38_vqonp"] @@ -3180,6 +3181,10 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 28.5, 1.5, 17.5) [node name="Props" type="Node3D" parent="."] +[node name="ControlPad" parent="Props" node_paths=PackedStringArray("Target") instance=ExtResource("35_c4mw0")] +transform = Transform3D(0.175436, 0, 0.178108, 0, 0.25, 0, -0.178108, 0, 0.175436, 5.36001, 1.84412, 22.5297) +Target = NodePath("../TestElevator/Path3D/PathFollow3D") + [node name="Mainframe3d" parent="Props" instance=ExtResource("16_u5cc4")] transform = Transform3D(0.25, 0, 0, 0, 0.25, 0, 0, 0, 0.25, 22.6824, 1.30461, 12.0268) diff --git a/3D/Scenes/Props/control_pad_3d.tscn b/3D/Scenes/Props/control_pad_3d.tscn new file mode 100644 index 00000000..62b02f55 --- /dev/null +++ b/3D/Scenes/Props/control_pad_3d.tscn @@ -0,0 +1,29 @@ +[gd_scene load_steps=5 format=3 uid="uid://du6hlcoq0iip4"] + +[ext_resource type="Script" uid="uid://qxh76ahgexqa" path="res://Scripts/Interactables/Switch3D.cs" id="1_papkq"] +[ext_resource type="Texture2D" uid="uid://d24g1qb40t72l" path="res://Sprites/Button_Small.png" id="2_ldivl"] +[ext_resource type="AudioStream" uid="uid://bjvklk7qmlivd" path="res://SFX/288963__littlerobotsoundfactory__click_electronic_14.wav" id="3_ldivl"] + +[sub_resource type="SphereShape3D" id="SphereShape3D_itd0i"] +radius = 0.868968 + +[node name="ControlPad" type="Area3D" groups=["Interactable"]] +transform = Transform3D(0.701743, 0, 0.71243, 0, 1, 0, -0.71243, 0, 0.701743, 0, 0, 0) +collision_layer = 32 +collision_mask = 0 +script = ExtResource("1_papkq") +metadata/_edit_group_ = true + +[node name="Sprite3D" type="Sprite3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 0.707107, 0.707107, 0, -0.707107, 0.707107, 0, 0, 0) +pixel_size = 0.1 +texture_filter = 0 +texture = ExtResource("2_ldivl") +hframes = 4 + +[node name="CollisionShape3D" type="CollisionShape3D" parent="."] +shape = SubResource("SphereShape3D_itd0i") + +[node name="ActivationSound" type="AudioStreamPlayer3D" parent="."] +stream = ExtResource("3_ldivl") +bus = &"Effects" diff --git a/Scenes/Actors/IsoPlayer_FSM.tscn b/Scenes/Actors/IsoPlayer_FSM.tscn index 19bc91b7..22e5a5b2 100644 --- a/Scenes/Actors/IsoPlayer_FSM.tscn +++ b/Scenes/Actors/IsoPlayer_FSM.tscn @@ -117,3 +117,6 @@ script = ExtResource("11_4cdxq") [node name="AudioStreamPlayer" type="AudioStreamPlayer" parent="ActivationProvider"] stream = ExtResource("13_2ffwi") bus = &"Effects" + +[node name="AudioListener3D" type="AudioListener3D" parent="."] +current = true diff --git a/Scenes/HUD/HUD.tscn b/Scenes/HUD/HUD.tscn index ec145b4a..272059c0 100644 --- a/Scenes/HUD/HUD.tscn +++ b/Scenes/HUD/HUD.tscn @@ -1,6 +1,7 @@ -[gd_scene load_steps=37 format=3 uid="uid://dkwi1hu1bixoe"] +[gd_scene load_steps=38 format=3 uid="uid://dkwi1hu1bixoe"] [ext_resource type="Script" uid="uid://baf6pxbvhqmjk" path="res://Scripts/Hud.cs" id="1_m0hb0"] +[ext_resource type="PackedScene" uid="uid://dsaj5dx82brsg" path="res://Scenes/HUD/UiSelector.tscn" id="2_jidad"] [ext_resource type="PackedScene" uid="uid://cd3ee1adstcrw" path="res://Scenes/HUD/HudItemContainer.tscn" id="2_mattb"] [ext_resource type="LabelSettings" uid="uid://buk3e7bbwmnv1" path="res://Resources/Styles/Hud_Text_Style.tres" id="2_x7kl7"] [ext_resource type="Texture2D" uid="uid://dde36pgb8fbwc" path="res://Sprites/selector_big.png" id="3_hee3i"] @@ -90,6 +91,7 @@ font_color = Color(0, 0.737255, 0.113725, 1) [node name="HUD" type="CanvasLayer" node_paths=PackedStringArray("_healthLabel", "_healthBar", "_shieldLabel", "_shieldBar", "_motivationLabel", "_itemsContainer", "_gameOverPanel", "_fairyTerminatedPanel", "_hudInfoPanel", "NotificationsContainer", "WeaponContainer", "PauseMenuContainer", "DebugMenuHolder")] process_mode = 3 script = ExtResource("1_m0hb0") +SelectorScene = ExtResource("2_jidad") WeaponContainerTemplate = ExtResource("2_mattb") ItemNotificationTemplate = ExtResource("3_mw35l") _healthLabel = NodePath("HudInfo/HealthBarContainer/HealthLabel") diff --git a/Scenes/HUD/UiSelector.tscn b/Scenes/HUD/UiSelector.tscn new file mode 100644 index 00000000..5d88cc2c --- /dev/null +++ b/Scenes/HUD/UiSelector.tscn @@ -0,0 +1,45 @@ +[gd_scene load_steps=6 format=3 uid="uid://dsaj5dx82brsg"] + +[ext_resource type="Texture2D" uid="uid://dde36pgb8fbwc" path="res://Sprites/selector_big.png" id="1_undfg"] +[ext_resource type="Script" uid="uid://w85hem1ec8cq" path="res://Scripts/Tools/AnimatedTextureRect.gd" id="2_cjotf"] + +[sub_resource type="AtlasTexture" id="AtlasTexture_vxp1j"] +atlas = ExtResource("1_undfg") +region = Rect2(0, 0, 16, 16) + +[sub_resource type="AtlasTexture" id="AtlasTexture_bnh43"] +atlas = ExtResource("1_undfg") +region = Rect2(16, 0, 16, 16) + +[sub_resource type="SpriteFrames" id="SpriteFrames_0vbph"] +animations = [{ +"frames": [{ +"duration": 1.0, +"texture": SubResource("AtlasTexture_vxp1j") +}, { +"duration": 1.0, +"texture": SubResource("AtlasTexture_bnh43") +}], +"loop": true, +"name": &"default", +"speed": 5.0 +}] + +[node name="UiSelector" type="Control"] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="TextureRect" type="TextureRect" parent="."] +layout_mode = 0 +offset_left = -8.0 +offset_top = -8.0 +offset_right = 8.0 +offset_bottom = 8.0 +texture = SubResource("AtlasTexture_vxp1j") +stretch_mode = 2 +script = ExtResource("2_cjotf") +Frames = SubResource("SpriteFrames_0vbph") diff --git a/Scenes/Interactable.cs b/Scenes/Interactable.cs index df71286b..70275221 100644 --- a/Scenes/Interactable.cs +++ b/Scenes/Interactable.cs @@ -4,6 +4,7 @@ using System.Diagnostics; using System.Linq; using Cirno.Scripts; using Cirno.Scripts.Interactables; +using Cirno.Scripts.Misc; using Cirno.Scripts.Resources; using Godot.Collections; @@ -53,4 +54,20 @@ public partial class Interactable : Area2D, IInteractable { return true; } + + public Vector2 GetScreenPosition() + { + if (CameraController.Instance is null) + { + return this.GlobalPosition; + } + + return this.GlobalPosition - CameraController.Instance.GlobalPosition + + (GetViewport().GetVisibleRect().Size / 2); + } + + public Vector2 GetGlobalPosition2D() + { + return GetGlobalPosition(); + } } diff --git a/Scripts/Activables/NPC.cs b/Scripts/Activables/NPC.cs index 6559a122..6068ba62 100644 --- a/Scripts/Activables/NPC.cs +++ b/Scripts/Activables/NPC.cs @@ -1,4 +1,5 @@ using Cirno.Scripts.Interactables; +using Cirno.Scripts.Misc; using Cirno.Scripts.Resources.Events; using Godot; using Godot.Collections; @@ -32,4 +33,20 @@ public partial class NPC : Area2D, IInteractable { return true; } + + public Vector2 GetScreenPosition() + { + if (CameraController.Instance is null) + { + return this.GlobalPosition; + } + + return this.GlobalPosition - CameraController.Instance.GlobalPosition + + (GetViewport().GetVisibleRect().Size / 2); + } + + public Vector2 GetGlobalPosition2D() + { + return GetGlobalPosition(); + } } \ No newline at end of file diff --git a/Scripts/Components/FSM/3DPlayer/IsoActivationProvider.cs b/Scripts/Components/FSM/3DPlayer/IsoActivationProvider.cs index 8c2003cf..7b0f0f06 100644 --- a/Scripts/Components/FSM/3DPlayer/IsoActivationProvider.cs +++ b/Scripts/Components/FSM/3DPlayer/IsoActivationProvider.cs @@ -48,8 +48,12 @@ public partial class IsoActivationProvider: Area3D, IModule(); + this.AddChild(instance); + + controller.ShowSelector += () => + { + instance.Show(); + }; + + controller.HideSelector += () => + { + instance.Hide(); + }; + + controller.ChangePosition += position => + { + instance.GlobalPosition = position; + }; + } } diff --git a/Scripts/Interactables/IInteractable.cs b/Scripts/Interactables/IInteractable.cs index e190a7b6..168d6a6d 100644 --- a/Scripts/Interactables/IInteractable.cs +++ b/Scripts/Interactables/IInteractable.cs @@ -7,6 +7,8 @@ public interface IInteractable public bool Activate(ActivationType activationType = ActivationType.Toggle); public bool CanActivate(); - public Vector2 GetGlobalPosition(); + public Vector2 GetGlobalPosition2D(); + + public Vector2 GetScreenPosition(); //protected bool MeetsRequirements(); } \ No newline at end of file diff --git a/Scripts/Interactables/Interactable3D.cs b/Scripts/Interactables/Interactable3D.cs new file mode 100644 index 00000000..f88ffc1b --- /dev/null +++ b/Scripts/Interactables/Interactable3D.cs @@ -0,0 +1,37 @@ +using Cirno.Scripts.Misc; +using Godot; + +namespace Cirno.Scripts.Interactables; + +public partial class Interactable3D : Area3D, IInteractable +{ + public virtual bool Activate(ActivationType activationType = ActivationType.Toggle) + { + return true; + } + + protected virtual bool MeetsRequirements() + { + return true; + } + + public virtual bool CanActivate() + { + return true; + } + + public Vector2 GetGlobalPosition2D() + { + return new Vector2(this.GlobalPosition.X, this.GlobalPosition.Z); + } + + public Vector2 GetScreenPosition() + { + if (CameraController3D.Instance is null) + { + return this.GetGlobalPosition2D(); + } + + return CameraController3D.Instance.UnprojectPosition(this.GlobalPosition); + } +} \ No newline at end of file diff --git a/Scripts/Interactables/Interactable3D.cs.uid b/Scripts/Interactables/Interactable3D.cs.uid new file mode 100644 index 00000000..06d88009 --- /dev/null +++ b/Scripts/Interactables/Interactable3D.cs.uid @@ -0,0 +1 @@ +uid://7rcv7ip052ug diff --git a/Scripts/Interactables/Switch3D.cs b/Scripts/Interactables/Switch3D.cs new file mode 100644 index 00000000..78f2f576 --- /dev/null +++ b/Scripts/Interactables/Switch3D.cs @@ -0,0 +1,46 @@ +using System.Linq; +using Godot; +using Godot.Collections; + +namespace Cirno.Scripts.Interactables; + +public partial class Switch3D : Interactable3D +{ + [Export] public Node Target { get; set; } + [Export] public Array Targets { get; private set; } = []; + [Export] public ActivationType ActivationType { get; set; } = ActivationType.Toggle; + + [Signal] + public delegate void OnActivatedEventHandler(ActivationType activationType); + + private AudioStreamPlayer _activationSound; + + private readonly string _activationSoundName = "ActivationSound"; + + public override void _Ready() + { + _activationSound = GetNodeOrNull(_activationSoundName); + } + + public override bool Activate(ActivationType activationType = ActivationType.Toggle) + { + var activationTypeToUse = activationType is ActivationType.Use ? ActivationType : activationType; + + if (!MeetsRequirements()) return false; + _activationSound?.Play(); + + EmitSignal(SignalName.OnActivated, (int)activationTypeToUse); + + // Compatibility for old single system + bool success = ActivateTarget(Target, activationTypeToUse); + + return Targets.Aggregate(success, (current, target) => ActivateTarget(target, activationTypeToUse) | success); + } + + private bool ActivateTarget(Node target, ActivationType activationType = ActivationType.Toggle) + { + if (target is not IActivable activable) return false; + activable?.Activate(activationType); + return true; + } +} \ No newline at end of file diff --git a/Scripts/Interactables/Switch3D.cs.uid b/Scripts/Interactables/Switch3D.cs.uid new file mode 100644 index 00000000..718e7af7 --- /dev/null +++ b/Scripts/Interactables/Switch3D.cs.uid @@ -0,0 +1 @@ +uid://qxh76ahgexqa diff --git a/Scripts/Misc/CameraController.cs b/Scripts/Misc/CameraController.cs index 2397d96f..2039b5b1 100644 --- a/Scripts/Misc/CameraController.cs +++ b/Scripts/Misc/CameraController.cs @@ -6,6 +6,7 @@ namespace Cirno.Scripts.Misc; public partial class CameraController : Camera2D { + public static CameraController Instance { get; private set; } [Export] public bool PixelSnap { get; set; } = true; [Export] public bool EnableSmoothing { get; set; } = true; @@ -41,6 +42,7 @@ public partial class CameraController : Camera2D public override void _Ready() { + Instance = this; AddToGroup(CameraControllersGroupName); } diff --git a/Scripts/Misc/CameraController3D.cs b/Scripts/Misc/CameraController3D.cs index e3a7f48e..03541017 100644 --- a/Scripts/Misc/CameraController3D.cs +++ b/Scripts/Misc/CameraController3D.cs @@ -4,6 +4,8 @@ namespace Cirno.Scripts.Misc; public partial class CameraController3D : Camera3D { + public static CameraController3D Instance { get; private set; } + [Export] public bool EnableSmoothing = true; [Export] public bool FollowTargeting = true; @@ -27,6 +29,7 @@ public partial class CameraController3D : Camera3D public override void _Ready() { + Instance = this; _target = GetNode(TargetPath); if (_target == null) { diff --git a/Scripts/Selector.cs b/Scripts/Selector.cs index 64f8df5a..d1a5a586 100644 --- a/Scripts/Selector.cs +++ b/Scripts/Selector.cs @@ -138,7 +138,7 @@ public partial class Selector : Node2D { if (SelectedInteractable != null) { - this.GlobalPosition = SelectedInteractable.GetGlobalPosition(); + this.GlobalPosition = SelectedInteractable.GetGlobalPosition2D(); this.Visible = true; } else diff --git a/Scripts/UI/Selector3D.cs b/Scripts/UI/Selector3D.cs index b045fd17..52a9c435 100644 --- a/Scripts/UI/Selector3D.cs +++ b/Scripts/UI/Selector3D.cs @@ -1,6 +1,16 @@ -namespace Cirno.Scripts.UI; +using Cirno.Scripts.Interactables; +using Godot; -public partial class Selector3D +namespace Cirno.Scripts.UI; + +public partial class Selector3D : Control { - + public IInteractable Target { get; set; } + + public override void _Process(double delta) + { + if (Target is null) return; + + this.GlobalPosition = Target.GetScreenPosition(); + } } \ No newline at end of file diff --git a/Sprites/Button_Small.png.import b/Sprites/Button_Small.png.import index 0a4f6024..1f80d374 100644 --- a/Sprites/Button_Small.png.import +++ b/Sprites/Button_Small.png.import @@ -15,13 +15,13 @@ dest_files=["res://.godot/imported/Button_Small.png-98a4c5460459fa0da24d50dc27d2 [params] -compress/mode=0 +compress/mode=3 compress/high_quality=false compress/lossy_quality=0.7 compress/hdr_compression=1 compress/normal_map=0 compress/channel_pack=0 -mipmaps/generate=false +mipmaps/generate=true mipmaps/limit=-1 roughness/mode=0 roughness/src_normal="" @@ -31,4 +31,4 @@ process/normal_map_invert_y=false process/hdr_as_srgb=false process/hdr_clamp_exposure=false process/size_limit=0 -detect_3d/compress_to=1 +detect_3d/compress_to=0