| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936 |
- using System.Linq;
- using System.Numerics;
- using Content.Client.Administration.Managers;
- using Content.Client.ContextMenu.UI;
- using Content.Client.Decals;
- using Content.Client.Gameplay;
- using Content.Client.UserInterface.Controls;
- using Content.Client.UserInterface.Systems.Gameplay;
- using Content.Client.Verbs;
- using Content.Shared.Administration;
- using Content.Shared.Decals;
- using Content.Shared.Input;
- using Content.Shared.Maps;
- using Robust.Client.GameObjects;
- using Robust.Client.Graphics;
- using Robust.Client.Input;
- using Robust.Client.Placement;
- using Robust.Client.ResourceManagement;
- using Robust.Client.UserInterface;
- using Robust.Client.UserInterface.CustomControls;
- using Robust.Shared.Enums;
- using Robust.Shared.Input.Binding;
- using Robust.Shared.Map;
- using Robust.Shared.Player;
- using Robust.Shared.Prototypes;
- using Robust.Shared.Serialization.Markdown.Sequence;
- using Robust.Shared.Serialization.Markdown.Value;
- using Robust.Shared.Timing;
- using Robust.Shared.Utility;
- using static System.StringComparison;
- using static Robust.Client.UserInterface.Controls.BaseButton;
- using static Robust.Client.UserInterface.Controls.LineEdit;
- using static Robust.Client.UserInterface.Controls.OptionButton;
- using static Robust.Shared.Input.Binding.PointerInputCmdHandler;
- namespace Content.Client.Mapping;
- public sealed class MappingState : GameplayStateBase
- {
- [Dependency] private readonly IClientAdminManager _admin = default!;
- [Dependency] private readonly IEntityManager _entityManager = default!;
- [Dependency] private readonly IEntityNetworkManager _entityNetwork = default!;
- [Dependency] private readonly IInputManager _input = default!;
- [Dependency] private readonly ILogManager _log = default!;
- [Dependency] private readonly IMapManager _mapMan = default!;
- [Dependency] private readonly MappingManager _mapping = default!;
- [Dependency] private readonly IOverlayManager _overlays = default!;
- [Dependency] private readonly IPlacementManager _placement = default!;
- [Dependency] private readonly IPrototypeManager _prototypeManager = default!;
- [Dependency] private readonly IResourceCache _resources = default!;
- [Dependency] private readonly IGameTiming _timing = default!;
- private EntityMenuUIController _entityMenuController = default!;
- private DecalPlacementSystem _decal = default!;
- private SpriteSystem _sprite = default!;
- private TransformSystem _transform = default!;
- private VerbSystem _verbs = default!;
- private readonly ISawmill _sawmill;
- private readonly GameplayStateLoadController _loadController;
- private bool _setup;
- private readonly List<MappingPrototype> _allPrototypes = new();
- private readonly Dictionary<IPrototype, MappingPrototype> _allPrototypesDict = new();
- private readonly Dictionary<Type, Dictionary<string, MappingPrototype>> _idDict = new();
- private readonly List<MappingPrototype> _prototypes = new();
- private (TimeSpan At, MappingSpawnButton Button)? _lastClicked;
- private Control? _scrollTo;
- private bool _updatePlacement;
- private bool _updateEraseDecal;
- private MappingScreen Screen => (MappingScreen) UserInterfaceManager.ActiveScreen!;
- private MainViewport Viewport => UserInterfaceManager.ActiveScreen!.GetWidget<MainViewport>()!;
- public CursorState State { get; set; }
- public MappingState()
- {
- IoCManager.InjectDependencies(this);
- _sawmill = _log.GetSawmill("mapping");
- _loadController = UserInterfaceManager.GetUIController<GameplayStateLoadController>();
- }
- protected override void Startup()
- {
- EnsureSetup();
- base.Startup();
- UserInterfaceManager.LoadScreen<MappingScreen>();
- _loadController.LoadScreen();
- var context = _input.Contexts.GetContext("common");
- context.AddFunction(ContentKeyFunctions.MappingUnselect);
- context.AddFunction(ContentKeyFunctions.SaveMap);
- context.AddFunction(ContentKeyFunctions.MappingEnablePick);
- context.AddFunction(ContentKeyFunctions.MappingEnableDelete);
- context.AddFunction(ContentKeyFunctions.MappingPick);
- context.AddFunction(ContentKeyFunctions.MappingRemoveDecal);
- context.AddFunction(ContentKeyFunctions.MappingCancelEraseDecal);
- context.AddFunction(ContentKeyFunctions.MappingOpenContextMenu);
- Screen.DecalSystem = _decal;
- Screen.Prototypes.SearchBar.OnTextChanged += OnSearch;
- Screen.Prototypes.CollapseAllButton.OnPressed += OnCollapseAll;
- Screen.Prototypes.ClearSearchButton.OnPressed += OnClearSearch;
- Screen.Prototypes.GetPrototypeData += OnGetData;
- Screen.Prototypes.SelectionChanged += OnSelected;
- Screen.Prototypes.CollapseToggled += OnCollapseToggled;
- Screen.Pick.OnPressed += OnPickPressed;
- Screen.Delete.OnPressed += OnDeletePressed;
- Screen.EntityReplaceButton.OnToggled += OnEntityReplacePressed;
- Screen.EntityPlacementMode.OnItemSelected += OnEntityPlacementSelected;
- Screen.EraseEntityButton.OnToggled += OnEraseEntityPressed;
- Screen.EraseDecalButton.OnToggled += OnEraseDecalPressed;
- _placement.PlacementChanged += OnPlacementChanged;
- CommandBinds.Builder
- .Bind(ContentKeyFunctions.MappingUnselect, new PointerInputCmdHandler(HandleMappingUnselect, outsidePrediction: true))
- .Bind(ContentKeyFunctions.SaveMap, new PointerInputCmdHandler(HandleSaveMap, outsidePrediction: true))
- .Bind(ContentKeyFunctions.MappingEnablePick, new PointerStateInputCmdHandler(HandleEnablePick, HandleDisablePick, outsidePrediction: true))
- .Bind(ContentKeyFunctions.MappingEnableDelete, new PointerStateInputCmdHandler(HandleEnableDelete, HandleDisableDelete, outsidePrediction: true))
- .Bind(ContentKeyFunctions.MappingPick, new PointerInputCmdHandler(HandlePick, outsidePrediction: true))
- .Bind(ContentKeyFunctions.MappingRemoveDecal, new PointerInputCmdHandler(HandleEditorCancelPlace, outsidePrediction: true))
- .Bind(ContentKeyFunctions.MappingCancelEraseDecal, new PointerInputCmdHandler(HandleCancelEraseDecal, outsidePrediction: true))
- .Bind(ContentKeyFunctions.MappingOpenContextMenu, new PointerInputCmdHandler(HandleOpenContextMenu, outsidePrediction: true))
- .Register<MappingState>();
- _overlays.AddOverlay(new MappingOverlay(this));
- _prototypeManager.PrototypesReloaded += OnPrototypesReloaded;
- Screen.Prototypes.UpdateVisible(_prototypes);
- }
- private void OnPrototypesReloaded(PrototypesReloadedEventArgs obj)
- {
- if (!obj.WasModified<EntityPrototype>() &&
- !obj.WasModified<ContentTileDefinition>() &&
- !obj.WasModified<DecalPrototype>())
- {
- return;
- }
- ReloadPrototypes();
- }
- private bool HandleOpenContextMenu(in PointerInputCmdArgs args)
- {
- Deselect();
- var coords = args.Coordinates.ToMap(_entityManager, _transform);
- if (_verbs.TryGetEntityMenuEntities(coords, out var entities))
- _entityMenuController.OpenRootMenu(entities);
- return true;
- }
- protected override void Shutdown()
- {
- CommandBinds.Unregister<MappingState>();
- Screen.Prototypes.SearchBar.OnTextChanged -= OnSearch;
- Screen.Prototypes.CollapseAllButton.OnPressed -= OnCollapseAll;
- Screen.Prototypes.ClearSearchButton.OnPressed -= OnClearSearch;
- Screen.Prototypes.GetPrototypeData -= OnGetData;
- Screen.Prototypes.SelectionChanged -= OnSelected;
- Screen.Prototypes.CollapseToggled -= OnCollapseToggled;
- Screen.Pick.OnPressed -= OnPickPressed;
- Screen.Delete.OnPressed -= OnDeletePressed;
- Screen.EntityReplaceButton.OnToggled -= OnEntityReplacePressed;
- Screen.EntityPlacementMode.OnItemSelected -= OnEntityPlacementSelected;
- Screen.EraseEntityButton.OnToggled -= OnEraseEntityPressed;
- Screen.EraseDecalButton.OnToggled -= OnEraseDecalPressed;
- _placement.PlacementChanged -= OnPlacementChanged;
- _prototypeManager.PrototypesReloaded -= OnPrototypesReloaded;
- UserInterfaceManager.ClearWindows();
- _loadController.UnloadScreen();
- UserInterfaceManager.UnloadScreen();
- var context = _input.Contexts.GetContext("common");
- context.RemoveFunction(ContentKeyFunctions.MappingUnselect);
- context.RemoveFunction(ContentKeyFunctions.SaveMap);
- context.RemoveFunction(ContentKeyFunctions.MappingEnablePick);
- context.RemoveFunction(ContentKeyFunctions.MappingEnableDelete);
- context.RemoveFunction(ContentKeyFunctions.MappingPick);
- context.RemoveFunction(ContentKeyFunctions.MappingRemoveDecal);
- context.RemoveFunction(ContentKeyFunctions.MappingCancelEraseDecal);
- context.RemoveFunction(ContentKeyFunctions.MappingOpenContextMenu);
- _overlays.RemoveOverlay<MappingOverlay>();
- base.Shutdown();
- }
- private void EnsureSetup()
- {
- if (_setup)
- return;
- _setup = true;
- _entityMenuController = UserInterfaceManager.GetUIController<EntityMenuUIController>();
- _decal = _entityManager.System<DecalPlacementSystem>();
- _sprite = _entityManager.System<SpriteSystem>();
- _transform = _entityManager.System<TransformSystem>();
- _verbs = _entityManager.System<VerbSystem>();
- ReloadPrototypes();
- }
- private void ReloadPrototypes()
- {
- var entities = new MappingPrototype(null, Loc.GetString("mapping-entities")) { Children = new List<MappingPrototype>() };
- _prototypes.Add(entities);
- var mappings = new Dictionary<string, MappingPrototype>();
- foreach (var entity in _prototypeManager.EnumeratePrototypes<EntityPrototype>())
- {
- Register(entity, entity.ID, entities);
- }
- Sort(mappings, entities);
- mappings.Clear();
- var tiles = new MappingPrototype(null, Loc.GetString("mapping-tiles")) { Children = new List<MappingPrototype>() };
- _prototypes.Add(tiles);
- foreach (var tile in _prototypeManager.EnumeratePrototypes<ContentTileDefinition>())
- {
- Register(tile, tile.ID, tiles);
- }
- Sort(mappings, tiles);
- mappings.Clear();
- var decals = new MappingPrototype(null, Loc.GetString("mapping-decals")) { Children = new List<MappingPrototype>() };
- _prototypes.Add(decals);
- foreach (var decal in _prototypeManager.EnumeratePrototypes<DecalPrototype>())
- {
- Register(decal, decal.ID, decals);
- }
- Sort(mappings, decals);
- mappings.Clear();
- }
- private void Sort(Dictionary<string, MappingPrototype> prototypes, MappingPrototype topLevel)
- {
- static int Compare(MappingPrototype a, MappingPrototype b)
- {
- return string.Compare(a.Name, b.Name, OrdinalIgnoreCase);
- }
- topLevel.Children ??= new List<MappingPrototype>();
- foreach (var prototype in prototypes.Values)
- {
- if (prototype.Parents == null && prototype != topLevel)
- {
- prototype.Parents = new List<MappingPrototype> { topLevel };
- topLevel.Children.Add(prototype);
- }
- prototype.Parents?.Sort(Compare);
- prototype.Children?.Sort(Compare);
- }
- topLevel.Children.Sort(Compare);
- }
- private MappingPrototype? Register<T>(T? prototype, string id, MappingPrototype topLevel) where T : class, IPrototype, IInheritingPrototype
- {
- {
- if (prototype == null &&
- _prototypeManager.TryIndex(id, out prototype) &&
- prototype is EntityPrototype entity)
- {
- if (entity.HideSpawnMenu || entity.Abstract)
- prototype = null;
- }
- }
- if (prototype == null)
- {
- if (!_prototypeManager.TryGetMapping(typeof(T), id, out var node))
- {
- _sawmill.Error($"No {nameof(T)} found with id {id}");
- return null;
- }
- var ids = _idDict.GetOrNew(typeof(T));
- if (ids.TryGetValue(id, out var mapping))
- {
- return mapping;
- }
- else
- {
- var name = node.TryGet("name", out ValueDataNode? nameNode)
- ? nameNode.Value
- : id;
- if (node.TryGet("suffix", out ValueDataNode? suffix))
- name = $"{name} [{suffix.Value}]";
- mapping = new MappingPrototype(prototype, name);
- _allPrototypes.Add(mapping);
- ids.Add(id, mapping);
- if (node.TryGet("parent", out ValueDataNode? parentValue))
- {
- var parent = Register<T>(null, parentValue.Value, topLevel);
- if (parent != null)
- {
- mapping.Parents ??= new List<MappingPrototype>();
- mapping.Parents.Add(parent);
- parent.Children ??= new List<MappingPrototype>();
- parent.Children.Add(mapping);
- }
- }
- else if (node.TryGet("parent", out SequenceDataNode? parentSequence))
- {
- foreach (var parentNode in parentSequence.Cast<ValueDataNode>())
- {
- var parent = Register<T>(null, parentNode.Value, topLevel);
- if (parent != null)
- {
- mapping.Parents ??= new List<MappingPrototype>();
- mapping.Parents.Add(parent);
- parent.Children ??= new List<MappingPrototype>();
- parent.Children.Add(mapping);
- }
- }
- }
- else
- {
- topLevel.Children ??= new List<MappingPrototype>();
- topLevel.Children.Add(mapping);
- mapping.Parents ??= new List<MappingPrototype>();
- mapping.Parents.Add(topLevel);
- }
- return mapping;
- }
- }
- else
- {
- var ids = _idDict.GetOrNew(typeof(T));
- if (ids.TryGetValue(id, out var mapping))
- {
- return mapping;
- }
- else
- {
- var entity = prototype as EntityPrototype;
- var name = entity?.Name ?? prototype.ID;
- if (!string.IsNullOrWhiteSpace(entity?.EditorSuffix))
- name = $"{name} [{entity.EditorSuffix}]";
- mapping = new MappingPrototype(prototype, name);
- _allPrototypes.Add(mapping);
- _allPrototypesDict.Add(prototype, mapping);
- ids.Add(prototype.ID, mapping);
- }
- if (prototype.Parents == null)
- {
- topLevel.Children ??= new List<MappingPrototype>();
- topLevel.Children.Add(mapping);
- mapping.Parents ??= new List<MappingPrototype>();
- mapping.Parents.Add(topLevel);
- return mapping;
- }
- foreach (var parentId in prototype.Parents)
- {
- var parent = Register<T>(null, parentId, topLevel);
- if (parent != null)
- {
- mapping.Parents ??= new List<MappingPrototype>();
- mapping.Parents.Add(parent);
- parent.Children ??= new List<MappingPrototype>();
- parent.Children.Add(mapping);
- }
- }
- return mapping;
- }
- }
- private void OnPlacementChanged(object? sender, EventArgs e)
- {
- _updatePlacement = true;
- }
- protected override void OnKeyBindStateChanged(ViewportBoundKeyEventArgs args)
- {
- if (args.Viewport == null)
- base.OnKeyBindStateChanged(new ViewportBoundKeyEventArgs(args.KeyEventArgs, Viewport.Viewport));
- else
- base.OnKeyBindStateChanged(args);
- }
- private void OnSearch(LineEditEventArgs args)
- {
- if (string.IsNullOrEmpty(args.Text))
- {
- Screen.Prototypes.PrototypeList.Visible = true;
- Screen.Prototypes.SearchList.Visible = false;
- return;
- }
- var matches = new List<MappingPrototype>();
- foreach (var prototype in _allPrototypes)
- {
- if (prototype.Name.Contains(args.Text, OrdinalIgnoreCase))
- matches.Add(prototype);
- }
- matches.Sort(static (a, b) => string.Compare(a.Name, b.Name, OrdinalIgnoreCase));
- Screen.Prototypes.PrototypeList.Visible = false;
- Screen.Prototypes.SearchList.Visible = true;
- Screen.Prototypes.Search(matches);
- }
- private void OnCollapseAll(ButtonEventArgs args)
- {
- foreach (var child in Screen.Prototypes.PrototypeList.Children)
- {
- if (child is not MappingSpawnButton button)
- continue;
- Collapse(button);
- }
- Screen.Prototypes.ScrollContainer.SetScrollValue(new Vector2(0, 0));
- }
- private void OnClearSearch(ButtonEventArgs obj)
- {
- Screen.Prototypes.SearchBar.Text = string.Empty;
- OnSearch(new LineEditEventArgs(Screen.Prototypes.SearchBar, string.Empty));
- }
- private void OnGetData(IPrototype prototype, List<Texture> textures)
- {
- switch (prototype)
- {
- case EntityPrototype entity:
- textures.AddRange(SpriteComponent.GetPrototypeTextures(entity, _resources).Select(t => t.Default));
- break;
- case DecalPrototype decal:
- textures.Add(_sprite.Frame0(decal.Sprite));
- break;
- case ContentTileDefinition tile:
- if (tile.Sprite?.ToString() is { } sprite)
- textures.Add(_resources.GetResource<TextureResource>(sprite).Texture);
- break;
- }
- }
- private void OnSelected(MappingPrototype mapping)
- {
- if (mapping.Prototype == null)
- return;
- var chain = new Stack<MappingPrototype>();
- chain.Push(mapping);
- var parent = mapping.Parents?.FirstOrDefault();
- while (parent != null)
- {
- chain.Push(parent);
- parent = parent.Parents?.FirstOrDefault();
- }
- _lastClicked = null;
- Control? last = null;
- var children = Screen.Prototypes.PrototypeList.Children;
- foreach (var prototype in chain)
- {
- foreach (var child in children)
- {
- if (child is MappingSpawnButton button &&
- button.Prototype == prototype)
- {
- UnCollapse(button);
- OnSelected(button, prototype.Prototype);
- children = button.ChildrenPrototypes.Children;
- last = child;
- break;
- }
- }
- }
- if (last != null && Screen.Prototypes.PrototypeList.Visible)
- _scrollTo = last;
- }
- private void OnSelected(MappingSpawnButton button, IPrototype? prototype)
- {
- var time = _timing.CurTime;
- if (prototype is DecalPrototype)
- Screen.SelectDecal(prototype.ID);
- // Double-click functionality if it's collapsible.
- if (_lastClicked is { } lastClicked &&
- lastClicked.Button == button &&
- lastClicked.At > time - TimeSpan.FromSeconds(0.333) &&
- string.IsNullOrEmpty(Screen.Prototypes.SearchBar.Text) &&
- button.CollapseButton.Visible)
- {
- button.CollapseButton.Pressed = !button.CollapseButton.Pressed;
- ToggleCollapse(button);
- button.Button.Pressed = true;
- Screen.Prototypes.Selected = button;
- _lastClicked = null;
- return;
- }
- // Toggle if it's the same button (at least if we just unclicked it).
- if (!button.Button.Pressed && button.Prototype?.Prototype != null && _lastClicked?.Button == button)
- {
- _lastClicked = null;
- Deselect();
- return;
- }
- _lastClicked = (time, button);
- if (button.Prototype == null)
- return;
- if (Screen.Prototypes.Selected is { } oldButton &&
- oldButton != button)
- {
- Deselect();
- }
- Screen.EntityContainer.Visible = false;
- Screen.DecalContainer.Visible = false;
- switch (prototype)
- {
- case EntityPrototype entity:
- {
- var placementId = Screen.EntityPlacementMode.SelectedId;
- var placement = new PlacementInformation
- {
- PlacementOption = placementId > 0 ? EntitySpawnWindow.InitOpts[placementId] : entity.PlacementMode,
- EntityType = entity.ID,
- IsTile = false
- };
- Screen.EntityContainer.Visible = true;
- _decal.SetActive(false);
- _placement.BeginPlacing(placement);
- break;
- }
- case DecalPrototype decal:
- _placement.Clear();
- _decal.SetActive(true);
- _decal.UpdateDecalInfo(decal.ID, Color.White, 0, true, 0, false);
- Screen.DecalContainer.Visible = true;
- break;
- case ContentTileDefinition tile:
- {
- var placement = new PlacementInformation
- {
- PlacementOption = "AlignTileAny",
- TileType = tile.TileId,
- IsTile = true
- };
- _decal.SetActive(false);
- _placement.BeginPlacing(placement);
- break;
- }
- default:
- _placement.Clear();
- break;
- }
- Screen.Prototypes.Selected = button;
- button.Button.Pressed = true;
- }
- private void Deselect()
- {
- if (Screen.Prototypes.Selected is { } selected)
- {
- selected.Button.Pressed = false;
- Screen.Prototypes.Selected = null;
- if (selected.Prototype?.Prototype is DecalPrototype)
- {
- _decal.SetActive(false);
- Screen.DecalContainer.Visible = false;
- }
- if (selected.Prototype?.Prototype is EntityPrototype)
- {
- _placement.Clear();
- }
- if (selected.Prototype?.Prototype is ContentTileDefinition)
- {
- _placement.Clear();
- }
- }
- }
- private void OnCollapseToggled(MappingSpawnButton button, ButtonToggledEventArgs args)
- {
- ToggleCollapse(button);
- }
- private void OnPickPressed(ButtonEventArgs args)
- {
- if (args.Button.Pressed)
- EnablePick();
- else
- DisablePick();
- }
- private void OnDeletePressed(ButtonEventArgs obj)
- {
- if (obj.Button.Pressed)
- EnableDelete();
- else
- DisableDelete();
- }
- private void OnEntityReplacePressed(ButtonToggledEventArgs args)
- {
- _placement.Replacement = args.Pressed;
- }
- private void OnEntityPlacementSelected(ItemSelectedEventArgs args)
- {
- Screen.EntityPlacementMode.SelectId(args.Id);
- if (_placement.CurrentMode != null)
- {
- var placement = new PlacementInformation
- {
- PlacementOption = EntitySpawnWindow.InitOpts[args.Id],
- EntityType = _placement.CurrentPermission!.EntityType,
- TileType = _placement.CurrentPermission.TileType,
- Range = 2,
- IsTile = _placement.CurrentPermission.IsTile,
- };
- _placement.BeginPlacing(placement);
- }
- }
- private void OnEraseEntityPressed(ButtonEventArgs args)
- {
- if (args.Button.Pressed == _placement.Eraser)
- return;
- if (args.Button.Pressed)
- EnableEraser();
- else
- DisableEraser();
- }
- private void OnEraseDecalPressed(ButtonToggledEventArgs args)
- {
- _placement.Clear();
- Deselect();
- Screen.EraseEntityButton.Pressed = false;
- _updatePlacement = true;
- _updateEraseDecal = args.Pressed;
- }
- private void EnableEraser()
- {
- if (_placement.Eraser)
- return;
- _placement.Clear();
- _placement.ToggleEraser();
- Screen.EntityPlacementMode.Disabled = true;
- Screen.EraseDecalButton.Pressed = false;
- Deselect();
- }
- private void DisableEraser()
- {
- if (!_placement.Eraser)
- return;
- _placement.ToggleEraser();
- Screen.EntityPlacementMode.Disabled = false;
- }
- private void EnablePick()
- {
- Screen.UnPressActionsExcept(Screen.Pick);
- State = CursorState.Pick;
- }
- private void DisablePick()
- {
- Screen.Pick.Pressed = false;
- State = CursorState.None;
- }
- private void EnableDelete()
- {
- Screen.UnPressActionsExcept(Screen.Delete);
- State = CursorState.Delete;
- EnableEraser();
- }
- private void DisableDelete()
- {
- Screen.Delete.Pressed = false;
- State = CursorState.None;
- DisableEraser();
- }
- private bool HandleMappingUnselect(in PointerInputCmdArgs args)
- {
- if (Screen.Prototypes.Selected is not { Prototype.Prototype: DecalPrototype })
- return false;
- Deselect();
- return true;
- }
- private bool HandleSaveMap(in PointerInputCmdArgs args)
- {
- #if FULL_RELEASE
- return false;
- #endif
- if (!_admin.IsAdmin(true) || !_admin.HasFlag(AdminFlags.Host))
- return false;
- SaveMap();
- return true;
- }
- private bool HandleEnablePick(ICommonSession? session, EntityCoordinates coords, EntityUid uid)
- {
- EnablePick();
- return true;
- }
- private bool HandleDisablePick(ICommonSession? session, EntityCoordinates coords, EntityUid uid)
- {
- DisablePick();
- return true;
- }
- private bool HandleEnableDelete(ICommonSession? session, EntityCoordinates coords, EntityUid uid)
- {
- EnableDelete();
- return true;
- }
- private bool HandleDisableDelete(ICommonSession? session, EntityCoordinates coords, EntityUid uid)
- {
- DisableDelete();
- return true;
- }
- private bool HandlePick(ICommonSession? session, EntityCoordinates coords, EntityUid uid)
- {
- if (State != CursorState.Pick)
- return false;
- MappingPrototype? button = null;
- // Try and get tile under it
- // TODO: Separate mode for decals.
- if (!uid.IsValid())
- {
- var mapPos = _transform.ToMapCoordinates(coords);
- if (_mapMan.TryFindGridAt(mapPos, out var gridUid, out var grid) &&
- _entityManager.System<SharedMapSystem>().TryGetTileRef(gridUid, grid, coords, out var tileRef) &&
- _allPrototypesDict.TryGetValue(tileRef.GetContentTileDefinition(), out button))
- {
- OnSelected(button);
- return true;
- }
- }
- if (button == null)
- {
- if (uid == EntityUid.Invalid ||
- _entityManager.GetComponentOrNull<MetaDataComponent>(uid) is not { EntityPrototype: { } prototype } ||
- !_allPrototypesDict.TryGetValue(prototype, out button))
- {
- // we always block other input handlers if pick mode is enabled
- // this makes you not accidentally place something in space because you
- // miss-clicked while holding down the pick hotkey
- return true;
- }
- // Selected an entity
- OnSelected(button);
- // Match rotation
- _placement.Direction = _entityManager.GetComponent<TransformComponent>(uid).LocalRotation.GetDir();
- }
- return true;
- }
- private bool HandleEditorCancelPlace(ICommonSession? session, EntityCoordinates coords, EntityUid uid)
- {
- if (!Screen.EraseDecalButton.Pressed)
- return false;
- _entityNetwork.SendSystemNetworkMessage(new RequestDecalRemovalEvent(_entityManager.GetNetCoordinates(coords)));
- return true;
- }
- private bool HandleCancelEraseDecal(in PointerInputCmdArgs args)
- {
- if (!Screen.EraseDecalButton.Pressed)
- return false;
- Screen.EraseDecalButton.Pressed = false;
- return true;
- }
- private async void SaveMap()
- {
- await _mapping.SaveMap();
- }
- private void ToggleCollapse(MappingSpawnButton button)
- {
- if (button.CollapseButton.Pressed)
- {
- if (button.Prototype?.Children != null)
- {
- foreach (var child in button.Prototype.Children)
- {
- Screen.Prototypes.Insert(button.ChildrenPrototypes, child, true);
- }
- }
- button.CollapseButton.Label.Text = "▼";
- }
- else
- {
- button.ChildrenPrototypes.DisposeAllChildren();
- button.CollapseButton.Label.Text = "▶";
- }
- }
- private void Collapse(MappingSpawnButton button)
- {
- if (!button.CollapseButton.Pressed)
- return;
- button.CollapseButton.Pressed = false;
- ToggleCollapse(button);
- }
- private void UnCollapse(MappingSpawnButton button)
- {
- if (button.CollapseButton.Pressed)
- return;
- button.CollapseButton.Pressed = true;
- ToggleCollapse(button);
- }
- public EntityUid? GetHoveredEntity()
- {
- if (UserInterfaceManager.CurrentlyHovered is not IViewportControl viewport ||
- _input.MouseScreenPosition is not { IsValid: true } position)
- {
- return null;
- }
- var mapPos = viewport.PixelToMap(position.Position);
- return GetClickedEntity(mapPos);
- }
- public override void FrameUpdate(FrameEventArgs e)
- {
- if (_updatePlacement)
- {
- _updatePlacement = false;
- if (!_placement.IsActive && _decal.GetActiveDecal().Decal == null)
- Deselect();
- Screen.EraseEntityButton.Pressed = _placement.Eraser;
- Screen.EraseDecalButton.Pressed = _updateEraseDecal;
- Screen.EntityPlacementMode.Disabled = _placement.Eraser;
- }
- if (_scrollTo is not { } scrollTo)
- return;
- // this is not ideal but we wait until the control's height is computed to use
- // its position to scroll to
- if (scrollTo.Height > 0 && Screen.Prototypes.PrototypeList.Visible)
- {
- var y = scrollTo.GlobalPosition.Y - Screen.Prototypes.ScrollContainer.Height / 2 + scrollTo.Height;
- var scroll = Screen.Prototypes.ScrollContainer;
- scroll.SetScrollValue(scroll.GetScrollValue() + new Vector2(0, y));
- _scrollTo = null;
- }
- }
- // TODO this doesn't handle pressing down multiple state hotkeys at the moment
- public enum CursorState
- {
- None,
- Pick,
- Delete
- }
- }
|