3D Switches

This commit is contained in:
Marco 2025-06-13 17:46:44 +02:00
commit cb60226ced
20 changed files with 267 additions and 14 deletions

View file

@ -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();
}
}

View file

@ -48,8 +48,12 @@ public partial class IsoActivationProvider: Area3D, IModule<PlayerState, Charact
StateMachine = machine;
_selectorController.Hide();
// TODO: Create selector UI element and link the signals
if (Hud.Instance is not null)
{
Hud.Instance.CreateSelector(_selectorController);
}
// if (SelectorScene is not null && _selector is null)
// {
@ -65,7 +69,9 @@ public partial class IsoActivationProvider: Area3D, IModule<PlayerState, Charact
public void PhysicsProcess(double delta)
{
_selectorController.PhysicsProcess(delta);
HandleInteraction();
}
public void HandleInteraction()

View file

@ -118,7 +118,7 @@ public partial class SelectorController : Node
{
if (SelectedInteractable != null)
{
EmitSignalChangePosition(SelectedInteractable.GetGlobalPosition());
EmitSignalChangePosition(SelectedInteractable.GetScreenPosition());
EmitSignalShowSelector();
}
else
@ -136,4 +136,10 @@ public partial class SelectorController : Node
{
EmitSignalHideSelector();
}
public void PhysicsProcess(double delta)
{
if (SelectedInteractable is null) return;
EmitSignalChangePosition(SelectedInteractable.GetScreenPosition());
}
}

View file

@ -3,6 +3,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using Cirno.Scripts;
using Cirno.Scripts.Components.FSM._3DPlayer;
using Cirno.Scripts.Resources;
using Cirno.Scripts.UI;
using Cirno.Scripts.Utils;
@ -405,5 +406,25 @@ public partial class Hud : CanvasLayer
//AddInventoryItem(item.Item, item.Count);
}
public void CreateSelector(SelectorController controller)
{
var instance = SelectorScene.Instantiate<Control>();
this.AddChild(instance);
controller.ShowSelector += () =>
{
instance.Show();
};
controller.HideSelector += () =>
{
instance.Hide();
};
controller.ChangePosition += position =>
{
instance.GlobalPosition = position;
};
}
}

View file

@ -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();
}

View file

@ -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);
}
}

View file

@ -0,0 +1 @@
uid://7rcv7ip052ug

View file

@ -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<Node> 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<AudioStreamPlayer>(_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;
}
}

View file

@ -0,0 +1 @@
uid://qxh76ahgexqa

View file

@ -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);
}

View file

@ -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<Node3D>(TargetPath);
if (_target == null)
{

View file

@ -138,7 +138,7 @@ public partial class Selector : Node2D
{
if (SelectedInteractable != null)
{
this.GlobalPosition = SelectedInteractable.GetGlobalPosition();
this.GlobalPosition = SelectedInteractable.GetGlobalPosition2D();
this.Visible = true;
}
else

View file

@ -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();
}
}