diff --git a/Boards/BaseBoard.cs b/Boards/BaseBoard.cs new file mode 100644 index 0000000..efb4a37 --- /dev/null +++ b/Boards/BaseBoard.cs @@ -0,0 +1,196 @@ +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 FocusedCables { get; set; } = new(); + + public void SetCableVisualMode(bool mode) + { + CableVisualMode = mode; + foreach (BaseCable cable in GetChildren().OfType()) + cable.Modulate = Color.Color8(255, 255, 255, (Byte)(mode ? 20 : 255)); + } + + public void SetLabelVisualMode(bool mode) + { + LabelVisualMode = mode; + foreach (BaseModule module in GetChildren().OfType()) + 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 Modules { get; set; } = new(); + + protected IEnumerable ProgrammableModules() => + Modules + .OfType(); + + public IEnumerable TerminalModules() => + Modules + .OfType() + .Union(ProgrammableModules().SelectMany(module => module.UnderlyingBoard.TerminalModules())); + + protected HashSet Ports => Modules.SelectMany(module => module.Ports).ToHashSet(); + public IPanelViewer? PanelViewer { get; set; } + public Dictionary 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(); + Modules = new HashSet(); + FocusedCables = new HashSet(); + ConnectPending = null; + } + + public override void _Ready() + { + base._Ready(); + ModuleManualLayer = GetNode("ModuleManualLayer"); + ModuleMovingLayer = GetNode("ModuleMovingLayer"); + ModuleMovingLayer.Board = this; + PanelViewer = GetNode("PanelViewer"); + CircuitBoardControlLayer = GetNode("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()) + { + port.DataUpdated = false; + } + } + } + + if (module is ProgrammableModule programmableModule) + { + programmableModule.UnderlyingBoard.Reset(); + foreach (DataOutPort outPort in programmableModule.ExplicitPorts().OfType()) + outPort.DataUpdated = false; + foreach (DataOutPort outPort in programmableModule.ImplicitPorts().OfType()) + 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()) + port.DataUpdated = false; + + } + } + + public override bool _CanDropData(Vector2 atPosition, Variant data) + { + IVariantWithType vData = data.As(); + if (vData.TypeHint != "Module") + { + if(vData.TypeHint != "Item") + return false; + IBaseItem item = vData.UnderlyingData.As(); + 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(); + 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(); + if(vData.TypeHint == "Module") + { + BaseModule vModule = vData.UnderlyingData.As(); + vModule.Position = atPosition - vModule.PivotOffset; + vModule.UpdateCables(); + } + else + { + IBaseModuleItem moduleItem = vData.UnderlyingData.As(); + AddModule(moduleItem.ContentModule, atPosition); + ItemDraggingControl.Instance.DraggingFrom!.Item = null; + } + } + + protected T GetModule(NodePath path) where T : BaseModule + { + T res = GetNode(path); + res.Init(); + Modules.Add(res); + res.Board = this; + return res; + } +} diff --git a/Boards/IBaseBoard.cs b/Boards/IBaseBoard.cs deleted file mode 100644 index 08ab2d9..0000000 --- a/Boards/IBaseBoard.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Enigmos.Boards; - -public interface IBaseBoard -{ - -} \ No newline at end of file diff --git a/Cables/BaseCable.cs b/Cables/BaseCable.cs new file mode 100644 index 0000000..7e03939 --- /dev/null +++ b/Cables/BaseCable.cs @@ -0,0 +1,24 @@ +using Godot; +using Nocturnis.Enigmos.Cables; +using Nocturnis.Enigmos.Ports; + +namespace Enigmos.Cables; + +public abstract partial class BaseCable : Line2D, IBaseCable +{ + protected Line2D InFill { get; set; } + public IBasePort PortFrom { get; set; } + public IBasePort PortTo { get; set; } + + public void Init() + { + InFill = GetNode("InFill"); + } + + /// + /// Update points of line + /// + public abstract void LineUpdate(); + + public Node AsNode => this; +} \ No newline at end of file diff --git a/Enigmos.csproj b/Enigmos.csproj index 52f4be3..ff303e8 100644 --- a/Enigmos.csproj +++ b/Enigmos.csproj @@ -10,4 +10,10 @@ + + + + + + diff --git a/Exceptions/ModuleExecutionTimeout.cs b/Exceptions/ModuleExecutionTimeout.cs new file mode 100644 index 0000000..993b886 --- /dev/null +++ b/Exceptions/ModuleExecutionTimeout.cs @@ -0,0 +1,6 @@ +namespace Enigmos.Exceptions; + +public class ModuleExecutionTimeout : Exception +{ + public static readonly ModuleExecutionTimeout Exception = new ModuleExecutionTimeout(); +} \ No newline at end of file diff --git a/Manual/CommunicatorPairTab.cs b/Manual/CommunicatorPairTab.cs new file mode 100644 index 0000000..23afe8d --- /dev/null +++ b/Manual/CommunicatorPairTab.cs @@ -0,0 +1,45 @@ +using Enigmos.Modules.Extensions; +using Godot; +using Nocturnis.Communicators; +using Nocturnis.Enigmos.ModuleManuals; +using Nocturnis.Enigmos.Modules; + +namespace Enigmos.Manual; +public partial class CommunicatorPairTab : Panel, IModuleManualTab +{ + private bool InitFlag { get; set; } + public string FullName() => "Pair"; + + public void Init(ICommunicateModule module) + { + Module = module; + InitFlag = true; + } + + public ICommunicateModule Module { get; set; } + private OptionButton CommunicatorOptions { get; set; } + public override void _Ready() + { + if (!InitFlag) + throw new Exception("TODO - NEED INIT FIRST"); + CommunicatorOptions = GetNode("CommunicatorOptions"); + IBaseCommunicator[] options = Module.CompatibleCommunicators(); + for(int idx = 0; idx < options.Length; idx ++ ) + { + CommunicatorOptions.AddIconItem + ( + options[idx].IconTexture, + $"{options[idx].CustomName} " + (options[idx].Paired ? "(Already Paired)" : ""), + idx + ); + } + + Name = "Pair"; + base._Ready(); + } + + private void SelectHandler(int idx) + { + Module.Pair(Module.CompatibleCommunicators()[idx]); + } +} diff --git a/Manual/ErrorHandlerTab.cs b/Manual/ErrorHandlerTab.cs new file mode 100644 index 0000000..1485b3d --- /dev/null +++ b/Manual/ErrorHandlerTab.cs @@ -0,0 +1,27 @@ +using Godot; +using Nocturnis.Enigmos.ModuleManuals; +using Nocturnis.Enigmos.Modules; + +namespace Enigmos.Manual; + +public partial class ErrorHandlerTab : Panel, IModuleManualTab +{ + public string FullName() => "Error Handling"; + private bool InitFlag { get; set; } + private OptionButton Options { get; set; } + + public void Init(IErrorHandlerModule module) + { + Module = module; + Options = GetNode("Options"); + Options.Clear(); + for (int i = 0; i < module.HandlingOptions().Length; i++) + Options.AddItem(module.HandlingOptions()[i], i); + InitFlag = true; + + } + + private IErrorHandlerModule Module { get; set; } + + private void SelectHandle(int idx) => Module.SelectedOption = idx; +} \ No newline at end of file diff --git a/Manual/ModuleBoolValueParameterSetter.cs b/Manual/ModuleBoolValueParameterSetter.cs new file mode 100644 index 0000000..eb0c641 --- /dev/null +++ b/Manual/ModuleBoolValueParameterSetter.cs @@ -0,0 +1,38 @@ +using Godot; +using Nocturnis.DataStructures.ConfigurableParameters; + +namespace Enigmos.Manual; + +public partial class ModuleBoolValueParameterSetter : ModuleParameterSetter +{ + private CheckButton ToggleSetter { get; set; } + private Label TrueLabel { get; set; } + private Label FalseLabel { get; set; } + + public void Init(IBoolParameter parameter) + { + UnderlyingParameter = parameter; + InitFlag = true; + } + + public new IBoolParameter UnderlyingParameter + { + get => (base.UnderlyingParameter as IBoolParameter)!; + set => base.UnderlyingParameter = value; + } + + public override void _Ready() + { + if (!InitFlag) + throw new Exception("TODO - INIT NEED"); + ToggleSetter = GetNode("ToggleSetter"); + TrueLabel = GetNode