riversong code showcase

This commit is contained in:
Daniele Marotta
2026-05-21 15:52:18 +02:00
commit 4c9eea1c02
462 changed files with 23406 additions and 0 deletions

View File

@@ -0,0 +1,59 @@
using System;
using System.Collections.Generic;
using UnityEngine.InputSystem;
namespace DanieleMarotta.RiversongCodeShowcase
{
[Service(typeof(ICancelAction))]
[GameSystemGroup(typeof(LateGameSystemGroup))]
public class CancelActionSystem : GameSystem, IUpdatable, ICancelAction
{
private readonly List<(int, Func<CancelActionType, bool>)> _handlers = new();
private Comparison<(int, Func<CancelActionType, bool>)> _handlerComparison;
public CancelActionSystem(IServiceLocator serviceLocator) : base(serviceLocator)
{
}
public void Update()
{
if (!TryGetCancelActionType(out var cancelActionType)) return;
foreach (var (_, handler) in _handlers)
if (handler.Invoke(cancelActionType))
return;
}
public void AddHandler(int priority, Func<CancelActionType, bool> cancelAction)
{
_handlerComparison ??= (handler, otherHandler) =>
{
var (handlerPriority, _) = handler;
var (otherHandlerPriority, _) = otherHandler;
return otherHandlerPriority.CompareTo(handlerPriority);
};
_handlers.Add((priority, cancelAction));
_handlers.Sort(_handlerComparison);
}
private static bool TryGetCancelActionType(out CancelActionType cancelActionType)
{
if (Keyboard.current.escapeKey.wasPressedThisFrame)
{
cancelActionType = CancelActionType.EscapeKey;
return true;
}
if (Mouse.current.rightButton.wasPressedThisFrame)
{
cancelActionType = CancelActionType.RightMouseButton;
return true;
}
cancelActionType = CancelActionType.None;
return false;
}
}
}

View File

@@ -0,0 +1,11 @@
namespace DanieleMarotta.RiversongCodeShowcase
{
public enum CancelActionType
{
None,
EscapeKey,
RightMouseButton
}
}

View File

@@ -0,0 +1,15 @@
namespace DanieleMarotta.RiversongCodeShowcase
{
public enum CancelActions
{
Invalid,
PauseMenu,
CloseBuildMenu,
CancelEditTool,
CancelSelection
}
}

View File

@@ -0,0 +1,9 @@
using System;
namespace DanieleMarotta.RiversongCodeShowcase
{
public interface ICancelAction
{
void AddHandler(int priority, Func<CancelActionType, bool> cancelAction);
}
}

View File

@@ -0,0 +1,13 @@
using UnityEngine;
namespace DanieleMarotta.RiversongCodeShowcase
{
public interface IPointerService
{
bool IsPointerOverUI { get; }
bool TryGetPositionOnTerrain(out Vector3 position);
bool TryConsumeLeftClick(int maxClickCount = 0);
}
}

View File

@@ -0,0 +1,82 @@
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.UIElements;
namespace DanieleMarotta.RiversongCodeShowcase
{
[Service(typeof(IPointerService))]
[GameSystemGroup(typeof(EarlyGameSystemGroup))]
public class PointerSystem : GameSystem, IUpdatable, IPointerService
{
[InjectService]
private IScene _scene;
[InjectService]
private GameConfig _config;
[InjectService]
private ITileSpace _tileSpace;
[InjectService]
private World _world;
[InjectService]
private UIService _uiService;
private int _leftButtonClickCount;
private Vector3? _positionOnTerrain;
public PointerSystem(IServiceLocator serviceLocator) : base(serviceLocator)
{
}
public bool IsPointerOverUI { get; private set; }
public void Update()
{
_leftButtonClickCount = 0;
UpdateIsPointerOverUIFlag();
UpdatePositionOnTerrain();
}
private void UpdateIsPointerOverUIFlag()
{
var panel = _uiService.UIRoot.RootVisualElement.panel;
var position = Mouse.current.position.ReadValue();
position.y = Screen.height - position.y;
position = RuntimePanelUtils.ScreenToPanel(panel, position);
IsPointerOverUI = panel.Pick(position) != null;
}
private void UpdatePositionOnTerrain()
{
_positionOnTerrain = null;
var ray = _scene.MainCamera.ScreenPointToRay(Mouse.current.position.ReadValue());
if (Physics.Raycast(ray, out var hit, float.PositiveInfinity))
{
if (!Mathf.Approximately(Vector3.Dot(hit.normal, Vector3.up), 1)) return;
if (_tileSpace.GetElevation(hit.point.y) != _config.GeneralSettings.BaseElevation) return;
_positionOnTerrain = hit.point;
}
}
public bool TryGetPositionOnTerrain(out Vector3 position)
{
position = _positionOnTerrain ?? Vector3.zero;
return _positionOnTerrain != null;
}
public bool TryConsumeLeftClick(int maxClickCount = 0)
{
return !IsPointerOverUI && Mouse.current.leftButton.wasPressedThisFrame && _leftButtonClickCount++ <= maxClickCount;
}
}
}