Files
Net.Like.Xue.Tokyo/Packages-Local/Com.Project.B.Unity/UX/UXMark.cs
2025-06-24 23:49:13 +08:00

243 lines
9.1 KiB
C#

using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using BITKit;
using BITKit.Entities;
using BITKit.UX;
using Cysharp.Threading.Tasks;
using Cysharp.Threading.Tasks.Triggers;
using Net.BITKit.BitMask;
using Net.BITKit.Localization;
using Net.BITKit.UX;
using Net.Project.B.AI;
using Net.Project.B.Faction;
using Net.Project.B.Item;
using Net.Project.B.Mark;
using Net.Project.B.Quest;
using Net.Project.B.WorldNode;
using Project.B.Entities;
using Project.B.Item;
using Project.B.Player;
using Project.B.UX;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.UIElements;
namespace Net.Project.B.UX
{
public static class UXMarkUtils{
public static void SetUp(int id,Func<VisualElement> createFactor,bool forceCreate=false)
{
BITApp.ServiceProvider.QueryComponents(out IManagedItemService itemService,out IEntitiesService entitiesService,out ILocalizationService localizationService);
if (itemService.Items.TryGetValue(id, out var item) && forceCreate)
{
var ve = createFactor();
UXInventoryUtils.Setup(ve, item).Forget();
return;
}
if (entitiesService.TryGetEntity(id, out var entity))
{
var serviceProvider = entity.ServiceProvider;
try
{
var className = (serviceProvider) switch
{
not null when serviceProvider.QueryComponents(out NameMark nameMark)=>nameMark.Name,
not null when serviceProvider.QueryComponents(out IMarkComponent markComponent) && forceCreate =>
markComponent.GetType().Name,
not null when serviceProvider.QueryComponents(out LandMark landMark) && string.IsNullOrEmpty(landMark.IconName) is false=>
landMark.IconName,
not null when serviceProvider.QueryComponents(out UnitySubwayNode _)=>
nameof(UnitySubwayNode),
not null when serviceProvider.QueryComponents(out IRuntimeItemContainer _) && forceCreate=>
nameof(IRuntimeItemContainer),
not null when serviceProvider.QueryComponents(out UnityVehicleNode vehicleNode)&& forceCreate=>
vehicleNode.GetType().Name,
not null when serviceProvider.QueryComponents(out UnityEvacuateNode evacuateNode)=>
evacuateNode.GetType().Name,
not null when serviceProvider.QueryComponents(out IFactionType factionType) && forceCreate =>
factionType.GetType().Name,
not null when serviceProvider.QueryComponents(out UnityDoorNode doorNode) && forceCreate =>
doorNode.GetType().Name,
not null when serviceProvider.QueryComponents(out UnityBuyStationNode buyStationNode) =>
buyStationNode.GetType().Name,
not null when serviceProvider.QueryComponents(out IQuestNode questNode) => questNode.GetType()
.Name,
_ => throw new OperationCanceledException()
};
var ve = createFactor();
ve.AddToClassList(className);
ve.viewDataKey = ve[0].viewDataKey = className;
ve.tooltip = ve[0].tooltip = localizationService.GetLocalizedString(className);
ve.AddToClassList(UXLocalization.USS);
ve[0].AddToClassList(UXLocalization.USS);
return;
}
catch (OperationCanceledException)
{
}
}
if (forceCreate)
{
createFactor();
}
}
}
public class UXMark<TPanel> : UIToolkitSubPanel<TPanel>,IUXMark, IDisposable where TPanel : IUXPanel
{
private readonly IPlayerFactory _playerFactory;
private readonly IMarkService _markService;
private readonly IEntitiesService _entitiesService;
private readonly IAfterTicker _ticker;
private readonly ConcurrentDictionary<int, VisualElement> _visualElements = new();
private readonly Dictionary<int, Vector2> _visualElementPositions = new();
private readonly IManagedItemService _itemService;
private readonly ScriptableBitMask _factionMask;
private readonly Dictionary<int, ScriptableItem> _scriptableItems=new();
private readonly IPlayerKeyMap<InputAction> _playerKey;
private readonly InputActionGroup _inputActionGroup=new();
private IFactionType _playerFaction;
public UXMark(IServiceProvider serviceProvider, IMarkService markService, IAfterTicker ticker, IEntitiesService entitiesService, IManagedItemService itemService, IPlayerKeyMap<InputAction> playerKey, IPlayerFactory playerFactory) : base(serviceProvider)
{
_markService = markService;
_ticker = ticker;
_entitiesService = entitiesService;
_itemService = itemService;
_playerKey = playerKey;
_playerFactory = playerFactory;
_markService.OnMark += OnMark;
_ticker.Add(OnAfterTick);
foreach (var item in _entitiesService.QueryComponents<ScriptableItem>())
{
_scriptableItems[item.Id] = item;
}
foreach (var mask in _entitiesService.QueryComponents<ScriptableBitMask>())
{
if(mask.Type != typeof(IFactionType))continue;
_factionMask = mask;
}
_playerFactory.OnEntityCreated += OnEntityCreated;
}
private UniTask OnEntityCreated(string arg1, IEntity arg2)
{
arg2.ServiceProvider.QueryComponents(out _playerFaction);
return UniTask.CompletedTask;
}
[UXBindPath("mark-container")] private VisualElement _markContainer;
private VisualTreeAsset _template;
protected override void OnInitiated()
{
base.OnInitiated();
_template = _markContainer.Q<TemplateContainer>().templateSource;
if (_template is null)
{
throw new Exception("mark-container is null");
}
_markContainer.Clear();
_inputActionGroup.RegisterCallback(_playerKey.MarkKey, OnMark);
_inputActionGroup.allowInput.AddElement(this);
}
private void OnMark(InputAction.CallbackContext obj)
{
if (obj.JustPressed() is false)return;
var center = _markContainer.layout.size/2;
foreach (var (id,pos) in _visualElementPositions)
{
var centersPos =pos + _visualElements[id].layout.size / 2;
if (Vector2.Distance(center, centersPos) < 32)
{
_markService.CancelMark(id);
return;
}
}
}
private void OnMark(int arg1, bool arg2)
{
if (arg2)
{
UXMarkUtils.SetUp(arg1,Create,true);
VisualElement Create()
{
return _visualElements[arg1] = _markContainer.Create(_template);
}
}
else if (_visualElements.TryRemove(arg1, out var container))
{
container.RemoveFromHierarchy();
_visualElementPositions.TryRemove(arg1);
}
}
private void OnAfterTick(float obj)
{
foreach (var (id,visualElement) in _visualElements)
{
if(_entitiesService.TryGetEntity(id,out var entity) is false)continue;
var serviceProvider = entity.ServiceProvider;
if (serviceProvider.QueryComponents(out Transform transform) is false || !transform)
{
continue;
}
if (serviceProvider.QueryComponents(out AIBlackBoard blackBoard))
{
_visualElements[id].Get<VisualElement>(1).style.height =
new StyleLength(Length.Percent(blackBoard.AlertValue*100));
}
var pos =
visualElement.SetPosition(entity.ServiceProvider.QueryComponents(out Collider collider)
?
collider.bounds.center+Vector3.up*(collider.bounds.extents.y*1.2f)
:
transform.position);
_visualElementPositions[id] = pos;
}
}
public void Dispose()
{
_markService.OnMark -= OnMark;
_inputActionGroup.Dispose();
_ticker.Remove(OnAfterTick);
}
}
}