Files
Enigmos/Boards/BaseBoard.cs
2024-06-29 06:35:23 +08:00

197 lines
6.8 KiB
C#

using Enigmos.Cables;
using Enigmos.Modules;
using Enigmos.Modules.ControllingModules;
using Enigmos.Modules.ProgrammableModules;
using Enigmos.Modules.TerminalModules;
using Enigmos.Ports.DataPorts;
using Godot;
using Nocturnis.DataStructures;
using Nocturnis.Enigmos.Boards;
using Nocturnis.Enigmos.Cables;
using Nocturnis.Enigmos.Modules;
using Nocturnis.Enigmos.Ports;
using Nocturnis.Inventories.Items;
using Nocturnis.Inventories.Items.Items;
using Nocturnis.UIElements;
using Nocturnis.UIElements.Layers;
using TabulaSmaragdina;
using TabulaSmaragdina.Controls;
namespace Enigmos.Boards;
public abstract partial class BaseBoard : Panel, IBaseBoard
{
public bool CableVisualMode { get; set; }
public bool LabelVisualMode { get; set; }
public HashSet<IBaseCable> FocusedCables { get; set; } = new();
public void SetCableVisualMode(bool mode)
{
CableVisualMode = mode;
foreach (BaseCable cable in GetChildren().OfType<BaseCable>())
cable.Modulate = Color.Color8(255, 255, 255, (Byte)(mode ? 20 : 255));
}
public void SetLabelVisualMode(bool mode)
{
LabelVisualMode = mode;
foreach (BaseModule module in GetChildren().OfType<BaseModule>())
if(module.HasLabel())
module.Label!.Visible = !mode;
}
public void AddCable(IBaseCable cable)
{
AddChild(cable.AsNode);
cable.Modulate = Color.Color8(255, 255, 255, (Byte)(CableVisualMode ? 20 : 255));
}
public IModuleManualLayer? ModuleManualLayer { get; set; }
public bool ManualOpened { get; set; }
protected HashSet<IBaseModule> Modules { get; set; } = new();
protected IEnumerable<ProgrammableModule> ProgrammableModules() =>
Modules
.OfType<ProgrammableModule>();
public IEnumerable<TerminalModule> TerminalModules() =>
Modules
.OfType<TerminalModule>()
.Union(ProgrammableModules().SelectMany(module => module.UnderlyingBoard.TerminalModules()));
protected HashSet<IBasePort> Ports => Modules.SelectMany(module => module.Ports).ToHashSet();
public IPanelViewer? PanelViewer { get; set; }
public Dictionary<IBasePort, IBaseCable> CablePairing { get; set; } = new();
public IBasePort? ConnectPending { get; set; }
public IBoardControlLayer? CircuitBoardControlLayer { get; set; }
public IModuleMovingLayer? ModuleMovingLayer { get; set; }
public virtual void Init()
{
CablePairing = new Dictionary<IBasePort, IBaseCable>();
Modules = new HashSet<IBaseModule>();
FocusedCables = new HashSet<IBaseCable>();
ConnectPending = null;
}
public override void _Ready()
{
base._Ready();
ModuleManualLayer = GetNode<IModuleManualLayer>("ModuleManualLayer");
ModuleMovingLayer = GetNode<IModuleMovingLayer>("ModuleMovingLayer");
ModuleMovingLayer.Board = this;
PanelViewer = GetNode<IPanelViewer>("PanelViewer");
CircuitBoardControlLayer = GetNode<IBoardControlLayer>("CircuitBoardControlLayer");
CircuitBoardControlLayer.Board = this;
}
protected virtual void AddModule(IBaseModule module, Vector2 pos)
{
module.Board = this;
AddChild(module.AsNode);
if (module is ICompositeModule compositeModule)
foreach (IBaseModule subModule in compositeModule.SubModules())
subModule.Board = this;
module.Position = pos;
Modules.Add(module);
}
public virtual void Reset()
{
foreach (IBaseModule module in Modules)
{
if (module is RootModule rootModule)
rootModule.ActionFinished = false;
if (module is ICompositeModule compositeModule)
{
foreach (IBaseModule subModule in compositeModule.SubModules())
{
foreach (DataOutPort port in subModule.Ports.OfType<DataOutPort>())
{
port.DataUpdated = false;
}
}
}
if (module is ProgrammableModule programmableModule)
{
programmableModule.UnderlyingBoard.Reset();
foreach (DataOutPort outPort in programmableModule.ExplicitPorts().OfType<DataOutPort>())
outPort.DataUpdated = false;
foreach (DataOutPort outPort in programmableModule.ImplicitPorts().OfType<DataOutPort>())
outPort.DataUpdated = false;
}
if (module is ControllingModule controllingModule)
controllingModule.Visited = false;
if (module is TerminalModule terminalModule)
terminalModule.Finished = false;
foreach (DataOutPort port in module.Ports.OfType<DataOutPort>())
port.DataUpdated = false;
}
}
public override bool _CanDropData(Vector2 atPosition, Variant data)
{
IVariantWithType vData = data.As<IVariantWithType>();
if (vData.TypeHint != "Module")
{
if(vData.TypeHint != "Item")
return false;
IBaseItem item = vData.UnderlyingData.As<IBaseItem>();
if (item is IBaseModuleItem moduleItem)
{
foreach (IBaseModule module in Modules)
if (GlobalProvider.UIProvider.Overlap(atPosition, moduleItem.ContentModule.Size, module.Position, module.Size))
return false;
return true;
}
return false;
}
BaseModule? moduleData = vData.UnderlyingData.As<BaseModule?>();
if (moduleData == null)
return false;
Vector2 pos = atPosition - moduleData.PivotOffset;
foreach (IBaseModule module in Modules)
{
if(module == moduleData)
continue;
if (GlobalProvider.UIProvider.Overlap(pos, moduleData.Size, module.Position, module.Size))
return false;
}
return true;
}
public override void _DropData(Vector2 atPosition, Variant data)
{
IVariantWithType vData = data.As<IVariantWithType>();
if(vData.TypeHint == "Module")
{
BaseModule vModule = vData.UnderlyingData.As<BaseModule>();
vModule.Position = atPosition - vModule.PivotOffset;
vModule.UpdateCables();
}
else
{
IBaseModuleItem moduleItem = vData.UnderlyingData.As<IBaseModuleItem>();
AddModule(moduleItem.ContentModule, atPosition);
ItemDraggingControl.Instance.DraggingFrom!.Item = null;
}
}
protected T GetModule<T>(NodePath path) where T : BaseModule
{
T res = GetNode<T>(path);
res.Init();
Modules.Add(res);
res.Board = this;
return res;
}
}