/// <summary> Caches the original world position of the spline points. Very useful for Pivotools. </summary>
 private static void CachePointsDefaultData(ISpline path, RageGroupElement item, int pathPointCount)
 {
     for (int i = 0; i < pathPointCount; i++)
     {
         item.GroupPointCache[i] = new RageGroupPointCache();
         ISplinePoint point = path.GetPointAt(i);
         item.GroupPointCache[i].PointPos   = point.Position;
         item.GroupPointCache[i].InCtrlPos  = point.InTangent;
         item.GroupPointCache[i].OutCtrlPos = point.OutTangent;
     }
 }
    /// <summary> Applies a given position offset to the points and the gradient of a given RageSpline</summary>
    private static void PointsPositionOffset(RageGroupElement groupItem, Vector3 offset)
    {
        var spline      = groupItem.Spline;
        var hasGradient = (spline.FillType == Spline.FillType.Gradient ||
                           spline.Rs.GetOutlineGradient() != RageSpline.OutlineGradient.None);
        var hasTexture = (spline.Rs.GetTexturing1() != RageSpline.UVMapping.None ||
                          spline.Rs.GetTexturing2() != RageSpline.UVMapping.None);

        Vector2 gradientOffsetWorld, textureOffsetWorld;
        Vector2 textureOffset2World = gradientOffsetWorld = textureOffsetWorld = Vector2.zero;

        if (hasGradient)
        {
            gradientOffsetWorld = groupItem.GradientOffsetCache;
        }
        if (hasTexture)
        {
            textureOffsetWorld  = groupItem.TextureOffsetCache;
            textureOffset2World = groupItem.TextureOffsetCache2;
        }

        OffsetSplinePoints(spline, offset);

        if (hasGradient)
        {
            gradientOffsetWorld        = new Vector2(gradientOffsetWorld.x + offset.x, gradientOffsetWorld.y + offset.y);
            spline.FillGradient.Offset = spline.GameObject.transform.InverseTransformPoint(gradientOffsetWorld);
        }
        if (hasTexture)
        {
            textureOffsetWorld  = new Vector2(textureOffsetWorld.x + offset.x, textureOffsetWorld.y + offset.y);
            textureOffset2World = new Vector2(textureOffset2World.x + offset.x, textureOffset2World.y + offset.y);
            spline.Rs.SetTextureOffset(spline.GameObject.transform.InverseTransformPoint(textureOffsetWorld));
            spline.Rs.SetTextureOffset2(spline.GameObject.transform.InverseTransformPoint(textureOffset2World));
        }
        spline.Rs.RefreshMeshInEditor(true, true, true);
    }