mirror of
https://github.com/space-wizards/RobustToolbox.git
synced 2026-06-09 10:06:34 +02:00
More work on tool history/selection
This commit is contained in:
@@ -6,6 +6,7 @@ namespace Robust.Client.Editor.Styling;
|
||||
|
||||
public abstract class BaseEditorStylesheet : CommonEngineStylesheet
|
||||
{
|
||||
public const string StyleClassToolButton = "EditorToolButton";
|
||||
public const string StyleClassLowBackground = "EditorLowBackground";
|
||||
public const string StyleClassEditorDockerLarge = "EditorDockerLarge";
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ using Robust.Client.ResourceManagement;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Client.UserInterface.Stylesheets;
|
||||
using Robust.Shared.Maths;
|
||||
using static Robust.Client.UserInterface.StylesheetHelpers;
|
||||
|
||||
namespace Robust.Client.Editor.Styling.Sheetlets;
|
||||
@@ -16,12 +17,23 @@ internal sealed class ButtonSheetlet : EngineSheetlet<BaseEditorStylesheet>
|
||||
var box = CreateBox(sheet);
|
||||
var selectedBox = new StyleBoxTexture(box) { Modulate = sheet.ButtonBackgroundHover };
|
||||
|
||||
var toolButton = new StyleBoxTexture(box) { Modulate = Color.Transparent };
|
||||
|
||||
return
|
||||
[
|
||||
// Normal buttons
|
||||
Element<ContainerButton>()
|
||||
.Prop(ContainerButton.StylePropertyStyleBox, box),
|
||||
Element<ContainerButton>().Pseudo(ContainerButton.StylePseudoClassHover)
|
||||
.Prop(ContainerButton.StylePropertyStyleBox, selectedBox)
|
||||
.Prop(ContainerButton.StylePropertyStyleBox, selectedBox),
|
||||
|
||||
// Tool buttons
|
||||
Element<ContainerButton>()
|
||||
.Class(BaseEditorStylesheet.StyleClassToolButton)
|
||||
.Prop(ContainerButton.StylePropertyStyleBox, toolButton),
|
||||
Element<ContainerButton>().Pseudo(ContainerButton.StylePseudoClassHover)
|
||||
.Class(BaseEditorStylesheet.StyleClassToolButton)
|
||||
.Prop(ContainerButton.StylePropertyStyleBox, selectedBox),
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -49,6 +49,26 @@ public struct MapEditorToolMakePreviewControl
|
||||
}
|
||||
}
|
||||
|
||||
[ByRefEvent]
|
||||
public struct MapEditorToolCheckEqual
|
||||
{
|
||||
public readonly EntityUid Other;
|
||||
internal bool IsEqual;
|
||||
|
||||
public void SetEqual()
|
||||
{
|
||||
if (IsEqual)
|
||||
throw new InvalidOperationException("Already set!");
|
||||
|
||||
IsEqual = true;
|
||||
}
|
||||
|
||||
internal MapEditorToolCheckEqual(EntityUid other)
|
||||
{
|
||||
Other = other;
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed partial class ClientMapEditorSystem
|
||||
{
|
||||
private static readonly SerializationOptions ToolSerializationOptions = new()
|
||||
@@ -61,9 +81,6 @@ internal sealed partial class ClientMapEditorSystem
|
||||
|
||||
public void SwitchToTool(EntityUid map, Action<Entity<MapEditorToolDataComponent>> ent)
|
||||
{
|
||||
var mapData = Comp<MapEditorClientMapDataComponent>(map);
|
||||
PushActiveToolToHistory((map, mapData));
|
||||
|
||||
var newToolEnt = Spawn(null, new EntityCoordinates(map, Vector2.Zero));
|
||||
var toolData = AddComp<MapEditorToolDataComponent>(newToolEnt);
|
||||
MetaSys.SetEntityName(newToolEnt, "Tool entity");
|
||||
@@ -80,10 +97,53 @@ internal sealed partial class ClientMapEditorSystem
|
||||
DebugTools.Assert(validateEvent.Name != null);
|
||||
|
||||
toolData.ToolName = validateEvent.Name;
|
||||
Log.Debug($"Selected tool: {validateEvent.Name}");
|
||||
|
||||
mapData.ActiveToolEntity = newToolEnt;
|
||||
ActiveToolChanged?.Invoke(map, (newToolEnt, toolData));
|
||||
var mapData = Comp<MapEditorClientMapDataComponent>(map);
|
||||
|
||||
if (mapData.ActiveToolEntity is { } active && AreToolEntitiesEqual(active, newToolEnt))
|
||||
{
|
||||
Log.Debug("New tool ent is equal to active.");
|
||||
Del(newToolEnt);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if tool already exists in history, just pull it out in that case.
|
||||
if (TryGetExistingHistoryTool((map, mapData), newToolEnt, out var foundTool))
|
||||
{
|
||||
Log.Debug("New tool ent is equal to history entry.");
|
||||
Del(newToolEnt);
|
||||
SwitchToHistoryTool(map, foundTool);
|
||||
return;
|
||||
}
|
||||
|
||||
PushActiveToolToHistory((map, mapData));
|
||||
SwitchToToolEntity((map, mapData), newToolEnt);
|
||||
}
|
||||
|
||||
public void SwitchToHistoryTool(EntityUid map, EntityUid historyTool)
|
||||
{
|
||||
var mapData = Comp<MapEditorClientMapDataComponent>(map);
|
||||
|
||||
var index = mapData.ToolEntityHistory.IndexOf(historyTool);
|
||||
if (index < 0)
|
||||
throw new InvalidOperationException("Tool was not in the history!");
|
||||
mapData.ToolEntityHistory.RemoveAt(index);
|
||||
ToolHistoryChanged?.Invoke(map, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, historyTool, index));
|
||||
|
||||
PushActiveToolToHistory((map, mapData));
|
||||
SwitchToToolEntity((map, mapData), historyTool);
|
||||
}
|
||||
|
||||
private void SwitchToToolEntity(Entity<MapEditorClientMapDataComponent> mapData, EntityUid newTool)
|
||||
{
|
||||
if (mapData.Comp.ActiveToolEntity is not null)
|
||||
throw new InvalidOperationException("Already have an active tool!");
|
||||
|
||||
var toolData = Comp<MapEditorToolDataComponent>(newTool);
|
||||
Log.Debug($"Selected tool: {toolData.ToolName}");
|
||||
|
||||
mapData.Comp.ActiveToolEntity = newTool;
|
||||
ActiveToolChanged?.Invoke(mapData, (newTool, toolData));
|
||||
}
|
||||
|
||||
private void PushActiveToolToHistory(Entity<MapEditorClientMapDataComponent> mapData)
|
||||
@@ -127,4 +187,29 @@ internal sealed partial class ClientMapEditorSystem
|
||||
|
||||
return (active, Comp<MapEditorToolDataComponent>(active));
|
||||
}
|
||||
|
||||
private bool TryGetExistingHistoryTool(
|
||||
Entity<MapEditorClientMapDataComponent> mapData,
|
||||
EntityUid newTool,
|
||||
out EntityUid foundTool)
|
||||
{
|
||||
foreach (var historyEntry in mapData.Comp.ToolEntityHistory)
|
||||
{
|
||||
if (AreToolEntitiesEqual(historyEntry, newTool))
|
||||
{
|
||||
foundTool = historyEntry;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
foundTool = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool AreToolEntitiesEqual(EntityUid a, EntityUid b)
|
||||
{
|
||||
var checkEqual = new MapEditorToolCheckEqual(b);
|
||||
RaiseLocalEvent(a, ref checkEqual);
|
||||
return checkEqual.IsEqual;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<ScrollContainer HScrollEnabled="False">
|
||||
<Control Name="ActiveToolContainer" VerticalAlignment="Top">
|
||||
<HBox>
|
||||
<Control Name="ActiveToolPreview" SetSize="32,32" />
|
||||
<Control Name="ActiveToolPreview" StyleClasses="ToolPreview" />
|
||||
<RichTextLabel Name="ActiveToolName" Margin="8, 0, 0, 0" HorizontalExpand="True" />
|
||||
</HBox>
|
||||
<Control Name="ActiveToolInfo" />
|
||||
|
||||
@@ -3,6 +3,7 @@ using System.Collections.ObjectModel;
|
||||
using System.Collections.Specialized;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.Editor.Interface;
|
||||
using Robust.Client.Editor.Styling;
|
||||
using Robust.Client.MapEditor.Interface.Styling;
|
||||
using Robust.Client.ResourceManagement;
|
||||
using Robust.Client.UserInterface;
|
||||
@@ -67,12 +68,14 @@ internal sealed partial class ToolHistoryPanel : EditorPanel
|
||||
{
|
||||
_toolHistoryMirror.Insert(i, (EntityUid)changed.NewItems[i]!);
|
||||
}
|
||||
|
||||
break;
|
||||
case NotifyCollectionChangedAction.Remove:
|
||||
for (var i = 0; i < changed.OldItems!.Count; i++)
|
||||
{
|
||||
_toolHistoryMirror.RemoveAt(changed.OldStartingIndex);
|
||||
}
|
||||
|
||||
break;
|
||||
case NotifyCollectionChangedAction.Replace:
|
||||
case NotifyCollectionChangedAction.Move:
|
||||
@@ -90,11 +93,18 @@ internal sealed partial class ToolHistoryPanel : EditorPanel
|
||||
|
||||
private Control CreateHistoryEntry(EntityUid arg)
|
||||
{
|
||||
var control = new Control
|
||||
var control = new ContainerButton
|
||||
{
|
||||
MouseFilter = MouseFilterMode.Stop,
|
||||
StyleClasses = { MapEditorStyleClasses.ToolHistoryEntry },
|
||||
Children = { ActiveToolPanel.GetPreviewControl(arg, _entityManager, _resourceCache) }
|
||||
StyleClasses = { BaseEditorStylesheet.StyleClassToolButton },
|
||||
Children =
|
||||
{
|
||||
new Control
|
||||
{
|
||||
StyleClasses = { MapEditorStyleClasses.ToolPreview },
|
||||
Children = { ActiveToolPanel.GetPreviewControl(arg, _entityManager, _resourceCache) }
|
||||
}
|
||||
}
|
||||
};
|
||||
control.TooltipSupplier = _ =>
|
||||
{
|
||||
@@ -103,6 +113,12 @@ internal sealed partial class ToolHistoryPanel : EditorPanel
|
||||
tt.SetMessage(comp.ToolName);
|
||||
return tt;
|
||||
};
|
||||
control.OnPressed += _ => SelectFromHistory(arg);
|
||||
return control;
|
||||
}
|
||||
|
||||
private void SelectFromHistory(EntityUid tool)
|
||||
{
|
||||
_mapEditor.SwitchToHistoryTool(_mapData, tool);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using Robust.Client.Editor.Styling;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.Stylesheets;
|
||||
using Robust.Shared.Maths;
|
||||
using static Robust.Client.UserInterface.StylesheetHelpers;
|
||||
|
||||
namespace Robust.Client.MapEditor.Interface.Styling;
|
||||
@@ -9,16 +8,16 @@ namespace Robust.Client.MapEditor.Interface.Styling;
|
||||
[EngineSheetlet]
|
||||
internal sealed class MapEditorSheetlet : EngineSheetlet<BaseEditorStylesheet>
|
||||
{
|
||||
private const float ToolPreviewSize = 64;
|
||||
|
||||
public override StyleRule[] GetRules(BaseEditorStylesheet sheet, object config)
|
||||
{
|
||||
return
|
||||
[
|
||||
Element()
|
||||
.Class(MapEditorStyleClasses.ToolHistoryEntry)
|
||||
.Prop(nameof(Control.Margin), new Thickness(2))
|
||||
.Prop(nameof(Control.SetWidth), 32)
|
||||
.Prop(nameof(Control.SetHeight), 32)
|
||||
|
||||
.Class(MapEditorStyleClasses.ToolPreview)
|
||||
.Prop(nameof(Control.SetWidth), ToolPreviewSize)
|
||||
.Prop(nameof(Control.SetHeight), ToolPreviewSize)
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
|
||||
internal static class MapEditorStyleClasses
|
||||
{
|
||||
public const string ToolHistoryEntry = "ToolHistoryEntry";
|
||||
public const string ToolPreview = "ToolPreview";
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Robust.Client.MapEditor.Interface.Panels;
|
||||
using System.Numerics;
|
||||
using Robust.Client.MapEditor.Interface.Panels;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
@@ -35,6 +36,7 @@ internal sealed class MapEditorToolEntitySystem : EntitySystem
|
||||
|
||||
SubscribeLocalEvent<MapEditorToolEntityComponent, MapEditorToolValidateEvent>(ValidateTool);
|
||||
SubscribeLocalEvent<MapEditorToolEntityComponent, MapEditorToolMakePreviewControl>(MakePreviewControl);
|
||||
SubscribeLocalEvent<MapEditorToolEntityComponent, MapEditorToolCheckEqual>(CheckEqual);
|
||||
}
|
||||
|
||||
public void SwitchToTool(EntityUid mapData, EntProtoId protoId)
|
||||
@@ -66,11 +68,20 @@ internal sealed class MapEditorToolEntitySystem : EntitySystem
|
||||
Entity<MapEditorToolEntityComponent> ent,
|
||||
ref MapEditorToolMakePreviewControl args)
|
||||
{
|
||||
var view = new EntityPrototypeView();
|
||||
var view = new EntityPrototypeView { Scale = new Vector2(2, 2) };
|
||||
view.SetPrototype(ent.Comp.PrototypeId);
|
||||
args.SetControl(view);
|
||||
}
|
||||
|
||||
private void CheckEqual(Entity<MapEditorToolEntityComponent> ent, ref MapEditorToolCheckEqual args)
|
||||
{
|
||||
if (!TryComp(args.Other, out MapEditorToolEntityComponent? otherComp))
|
||||
return;
|
||||
|
||||
if (ent.Comp.PrototypeId == otherComp.PrototypeId)
|
||||
args.SetEqual();
|
||||
}
|
||||
|
||||
internal static bool IsEligible(EntityPrototype prototype)
|
||||
{
|
||||
return !prototype.Abstract && !prototype.Abstract;
|
||||
|
||||
Reference in New Issue
Block a user