private void ReloadNodesAndEdges()
        {
            CloseNodesAndEdges();
            if (Graph == null)
            {
                return;
            }
            var entityMatrix = Entity.PositionComp.WorldMatrix;

            for (var i = 0; i < Nodes.Length; i++)
            {
                MyObjectBuilder_BendyComponent.NodePose data;
                if (_movableNodeData.TryGetValue((uint)i, out data))
                {
                    Nodes[i] = Graph.GetOrCreateNode(Vector3D.Transform((Vector3)data.Position, ref entityMatrix),
                                                     Vector3D.Transform((Vector3)data.Up, ref entityMatrix));
                }
                else
                {
                    Assert.False(Definition.Nodes[i].Movable,
                                 $"Creating movable bendy node {i} for entity {Entity}, component def {Definition.Id} without movable data");

                    var nodeMatrix = Definition.Nodes[i].Position * entityMatrix;
                    Nodes[i] = Graph.GetOrCreateNode(nodeMatrix.Translation, nodeMatrix.Up, !Definition.Nodes[i].Movable);
                    if (!Definition.Nodes[i].Movable)
                    {
                        Nodes[i].Pin(nodeMatrix);
                    }
                }

                if (Nodes[i] != null)
                {
                    NodeAdded?.Invoke(this, Nodes[i]);
                }
            }

            for (var i = 0; i < Edges.Length; i++)
            {
                var def  = Definition.Edges[i];
                var from = Nodes[def.From];
                var to   = Nodes[def.To];
                Edges[i] = Graph.GetEdge(from, to) ?? Graph.CreateEdge(this, from, to, def.Mode, def.Control0, def.Control1);
                if (Edges[i] != null)
                {
                    EdgeAdded?.Invoke(this, Edges[i]);
                    Edges[i].CurveUpdated += OnCurveUpdated;
                }
            }

            EdgeSetupChanged?.Invoke(this);

            if (_skeletonComponent != null)
            {
                OnBonesReloaded(_skeletonComponent);
            }
        }
        private void CloseNodesAndEdges()
        {
            CacheMovableData();
            if (Edges != null)
            {
                for (var i = 0; i < Edges.Length; i++)
                {
                    if (Edges[i] != null)
                    {
                        Edges[i].CurveUpdated -= OnCurveUpdated;
                        EdgeRemoved?.Invoke(this, Edges[i]);
                        Edges[i].Close();
                    }

                    Edges[i] = null;
                }
            }

            // ReSharper disable once InvertIf
            if (Nodes != null)
            {
                for (var i = 0; i < Nodes.Length; i++)
                {
                    if (Nodes[i] != null)
                    {
                        NodeRemoved?.Invoke(this, Nodes[i]);
                        if (!Definition.Nodes[i].Movable)
                        {
                            Nodes[i].UnpinTangent();
                        }
                    }

                    Nodes[i] = null;
                }
            }

            EdgeSetupChanged?.Invoke(this);
        }
 private void OnCurveUpdated(Edge e)
 {
     if (Edges == null)
     {
         return;
     }
     EdgeSetupChanged?.Invoke(this);
     for (var i = 0; i < Edges.Length; i++)
     {
         if (Edges[i] == e)
         {
             var def = Definition.Edges[i];
             if (def.Bones != null && def.Bones.Count > 0)
             {
                 foreach (var b in def.Bones)
                 {
                     MarkBoneDirty(b);
                 }
             }
             break;
         }
     }
 }