private static void AddLink(IDictionary <Bone, HashSet <RollNodeView> > links, int index, RollNodeView view, NodeList nodes)
        {
            if (index == 0)
            {
                return;
            }
            var bone = nodes.GetBone(index);

            if (bone == null)
            {
                return;
            }
            if (!links.ContainsKey(bone))
            {
                links.Add(bone, new HashSet <RollNodeView> {
                    view
                });
                view.LinkIndicatorButtonContainer.EnableIndication <BoneLinkIndicatorButton>().AddLinkedNode(bone);
            }
            else if (!links[bone].Contains(view))
            {
                links[bone].Add(view);
                view.LinkIndicatorButtonContainer.EnableIndication <BoneLinkIndicatorButton>().AddLinkedNode(bone);
            }
        }
        private static void ProcessLinks <TLinkIndicatorButton, TNode, TGear, TSpline>(IReadOnlyDictionary <TNode, HashSet <TGear> > links, TNode node, RollNodeView view)
            where TLinkIndicatorButton : LinkIndicatorButton, new()
            where TNode : Node
            where TSpline : Node
            where TGear : Node
        {
            if (!links.ContainsKey(node))
            {
                view.RefreshLabelColor();
                return;
            }
            var indication = view.LinkIndicatorButtonContainer.EnableIndication <TLinkIndicatorButton>();
            var gears      = links[node];

            if (gears.Count > 1)
            {
                if (!(node is TSpline))
                {
                    view.Label.Color = indication.Color = Theme.Colors.RedText;
                }
                indication.Tooltip = $"Linked to {gears.Count} {typeof(TGear).Name}s";
            }
            else
            {
                view.RefreshLabelColor();
                indication.Color   = Color4.White;
                indication.Tooltip = $"Linked to {typeof(TGear).Name}";
            }
            foreach (var gear in gears)
            {
                indication.AddLinkedNode(gear);
            }
        }
 private static void AddLinks(IDictionary <Bone, HashSet <RollNodeView> > links, SkinningWeights skinningWeights, RollNodeView view, NodeList nodes)
 {
     if (skinningWeights?.IsEmpty() ?? true)
     {
         return;
     }
     AddLink(links, skinningWeights.Bone0.Index, view, nodes);
     AddLink(links, skinningWeights.Bone1.Index, view, nodes);
     AddLink(links, skinningWeights.Bone2.Index, view, nodes);
     AddLink(links, skinningWeights.Bone3.Index, view, nodes);
 }
 private static void Link <TLinkIndicatorButton, TNode, TGear>(IDictionary <TNode, HashSet <TGear> > links, TGear gear, TNode node, RollNodeView view)
     where TLinkIndicatorButton : LinkIndicatorButton, new()
     where TNode : Node
 {
     if (node == null)
     {
         return;
     }
     if (!links.ContainsKey(node))
     {
         links.Add(node, new HashSet <TGear> {
             gear
         });
     }
     else
     {
         links[node].Add(gear);
     }
     view.LinkIndicatorButtonContainer.EnableIndication <TLinkIndicatorButton>().AddLinkedNode(node);
 }
 private void ProcessNode3DLinks(IReadOnlyDictionary <Node3D, HashSet <SplineGear3D> > links, Node3D node3D, RollNodeView view) =>
 ProcessLinks <SplineGear3DLinkIndicatorButton, Node3D, SplineGear3D, Spline3D>(links, node3D, view);
 private void ProcessWidgetLinks(IReadOnlyDictionary <Widget, HashSet <SplineGear> > links, Widget widget, RollNodeView view) =>
 ProcessLinks <SplineGearLinkIndicatorButton, Widget, SplineGear, Spline>(links, widget, view);
 private void LinkNode3D(IDictionary <Node3D, HashSet <SplineGear3D> > links, SplineGear3D splineGear3D, Node3D node3D, RollNodeView view) =>
 Link <SplineGear3DLinkIndicatorButton, Node3D, SplineGear3D>(links, splineGear3D, node3D, view);
 private void LinkWidget(IDictionary <Widget, HashSet <SplineGear> > links, SplineGear splineGear, Widget widget, RollNodeView view) =>
 Link <SplineGearLinkIndicatorButton, Widget, SplineGear>(links, splineGear, widget, view);