using System; using System.Collections.Generic; using System.Linq; using Godot; using VirtualChemistry.Chemistry.Atoms.Implements; using VirtualChemistry.Chemistry.Atoms.Resolver; using VirtualChemistry.Chemistry.Bonds.Implements; using VirtualChemistry.Chemistry.Compounds.Implements; using VirtualChemistry.Chemistry.Mixtures.Implements; public partial class CompoundConstructor : Panel { private HeterogeneousMixture HeterogeneousMixture { get; set; } public HomogeneousMixture HomogeneousMixture { get; set; } public HashSet Atoms { get; set; } = new(); public BaseBond ConnectPending { get; set; } = BaseBond.Null; public Atom PendingAtom { get; set; } public Dictionary> BondMap { get; set; } = new(); // Called when the node enters the scene tree for the first time. public override void _Ready() { GlobalScene.CompoundConstructor = this; HeterogeneousMixture = new(); HomogeneousMixture = HeterogeneousMixture.AddLayer(); } // Called every frame. 'delta' is the elapsed time since the previous frame. public override void _Process(double delta) { } public override bool _CanDropData(Vector2 atPosition, Variant data) { return true; } public override void _DropData(Vector2 atPosition, Variant data) { Atom a = data.As(); a.Position = atPosition; if(BondMap.ContainsKey(a)) foreach (Bond b in BondMap[a]) b.BondUpdate(); } public void AddAtomOf(int idx) { BaseAtom a = AtomResolver.Resolve(idx); Compound c = a.GrabCompound; c.Amount = 1; a.Compound = c; Atom at = ResourceLoader.Load("res://Scenes/Atom.tscn").Instantiate(); at.BaseAtom = a; AddChild(at); at.Position = new(500, 500); HomogeneousMixture.AddCompound(c, true, true); Atoms.Add(at); } public void RemoveAtomOf(Atom atom) { foreach (BaseBond b in atom.BaseAtom.ConnectedBonds) b.Disconnect(); Bond[] toRemove = Array.Empty(); if (BondMap.TryGetValue(atom, out HashSet value)) toRemove = value.ToArray(); foreach (Bond b in toRemove) { BondMap[b.AtomFrom].Remove(b); BondMap[b.AtomTo].Remove(b); RemoveChild(b); } atom.BaseAtom.Compound.HomogeneousMixture.Compounds.Remove(atom.BaseAtom.Compound); atom.BaseAtom.Compound.HomogeneousMixture = HomogeneousMixture.Null; atom.BaseAtom.Compound = Compound.Null; RemoveChild(atom); Atoms.Remove(atom); } public void ConnectAtoms(Atom a, BaseBond b) { b.Connect(ConnectPending); Bond bond = ResourceLoader.Load("res://Scenes/Bond.tscn").Instantiate(); bond.AtomFrom = PendingAtom; bond.AtomTo = a; bond.TypeA = ConnectPending.BondType; bond.TypeB = b.BondType; if (!BondMap.ContainsKey(a)) BondMap[a] = new HashSet(); BondMap[a].Add(bond); if (!BondMap.ContainsKey(PendingAtom!)) BondMap[PendingAtom] = new HashSet(); BondMap[PendingAtom].Add(bond); ConnectPending = BaseBond.Null; a.AtomActions.BuildMenu(); PendingAtom.AtomActions.BuildMenu(); PendingAtom = null; AddChild(bond); bond.BondUpdate(); } private void Back() { GlobalScene.MainScene.SwitchToDemo(); } private void Build() { HeterogeneousMixture.Container = GlobalScene.Demo.SelectedBottle; GlobalScene.Demo.SelectedBottle.Content = HeterogeneousMixture; GlobalScene.Demo.SelectedBottle.BuildMenu(); Clear(); } private void Clear(bool save = true) { if (!save) { foreach (Atom atom in Atoms) RemoveAtomOf(atom); return; } HashSet removedBonds = new(); foreach (Atom atom in Atoms) { RemoveChild(atom); if (!BondMap.ContainsKey(atom)) continue; foreach (Bond bond in BondMap[atom]) { if (!removedBonds.Contains(bond)) RemoveChild(bond); removedBonds.Add(bond); } } Atoms = new(); BondMap = new(); HeterogeneousMixture = new HeterogeneousMixture(); HomogeneousMixture = HeterogeneousMixture.AddLayer(); } private void ForceClear() => Clear(false); }