Exemplo n.º 1
0
    public void _CloseCurve()
    {
        Curve3D c = path.curve;

        if (!IsInstanceValid(c))
        {
            return;
        }
        if (c.GetPointCount() < 2)
        {
            return;
        }
        c.AddPoint(c.GetPointPosition(0), c.GetPointIn(0), c.GetPointOut(0));
    }
Exemplo n.º 2
0
    public override object GetHandleValue(int index)
    {
        Curve3D c = path.curve;

        if (!IsInstanceValid(c))
        {
            GD.Print("Invalid curve");
            return(null);
        }

        if (index < c.GetPointCount())
        {
            original = c.GetPointPosition(index);
            return(original);
        }

        index = index - c.GetPointCount() + 1;

        int idx = index / 2;
        int t   = index % 2;

        Vector3 ofs;

        if (t == 0)
        {
            ofs = c.GetPointIn(idx);
        }
        else
        {
            ofs = c.GetPointOut(idx);
        }

        original = ofs + c.GetPointPosition(idx);

        return(ofs);
    }
Exemplo n.º 3
0
    public override void SetHandle(int index, Camera camera, Vector2 point)
    {
        Curve3D c = path.curve;

        if (!IsInstanceValid(c))
        {
            GD.Print("Invalid curve");
            return;
        }

        Transform gt       = path.GlobalTransform;
        Transform gi       = gt.AffineInverse();
        Vector3   ray_from = camera.ProjectRayOrigin(point);
        Vector3   ray_dir  = camera.ProjectRayNormal(point);

        // Setting curve point positions
        if (index < c.GetPointCount())
        {
            var   org = gt.Xform(original);
            Plane pp  = new Plane();
            pp.Normal = camera.Transform.basis.GetColumn(2);
            pp.D      = pp.Normal.Dot(org);

            Vector3?_inters = pp.IntersectRay(ray_from, ray_dir);

            if (_inters != null)
            {
                Vector3 _nnInters = (Vector3)_inters;
                if (plugin.snapEnabled)
                {
                    _nnInters = _nnInters.Snapped(new Vector3(plugin.snapLength, plugin.snapLength, plugin.snapLength));
                }

                _nnInters = plugin.RestrictPoint(org, _nnInters);

                Vector3 local = gi.Xform(_nnInters);
                c.SetPointPosition(index, local);
            }
            return;
        }

        index = index - c.GetPointCount() + 1;

        int idx = index / 2;
        int t   = index % 2;

        var     porig   = gt.Xform(original);
        Vector3 basePos = c.GetPointPosition(idx);

        Plane p = new Plane();

        p.Normal = camera.Transform.basis.GetColumn(2);
        p.D      = p.Normal.Dot(porig);

        Vector3?inters = p.IntersectRay(ray_from, ray_dir);

        // Setting curve in/out positions
        if (inters != null)
        {
            Vector3 nnInters = (Vector3)inters;
            if (!plugin.handleClicked)
            {
                origInLength  = c.GetPointIn(idx).Length();
                origOutLenght = c.GetPointOut(idx).Length();
                plugin.SetHandleClicked(true);
            }
            Vector3 orig  = gi.Xform(porig) - basePos;
            Vector3 local = gi.Xform(nnInters) - basePos;
            if (plugin.snapEnabled)
            {
                local = local.Snapped(new Vector3(plugin.snapLength, plugin.snapLength, plugin.snapLength));
            }

            local = plugin.RestrictPoint(orig, local);

            if (t == 0)
            {
                c.SetPointIn(idx, local);
                if (plugin.mirrorHandleAngle)
                {
                    c.SetPointOut(idx, plugin.mirrorHandleLength ? -local : (-local.Normalized() * origOutLenght));
                }
            }
            else
            {
                c.SetPointOut(idx, local);
                if (plugin.mirrorHandleAngle)
                {
                    c.SetPointIn(idx, plugin.mirrorHandleLength ? -local : (-local.Normalized() * origInLength));
                }
            }
        }
    }
Exemplo n.º 4
0
    public override void Redraw( )
    {
        Clear();
        //GD.Print($"Redraw {GD.Randi()%100}");
        var     pathMaterial     = gizmoPlugin.GetMaterial("path_material", this);
        var     pathThinMaterial = gizmoPlugin.GetMaterial("path_thin_material", this);
        var     handlesMaterial  = gizmoPlugin.GetMaterial("handles", this);
        Curve3D c = path.curve;

        if (!IsInstanceValid(c))
        {
            GD.Print("Invalid curve");
            return;
        }

        var v3a = c.Tessellate();
        //PoolVector<Vector3> v3a=c.get_baked_points();

        int v3s = v3a.Length;

        if (v3s == 0)
        {
            return;
        }
        var v3p      = new Vector3[v3s * 2];
        int v3pCount = 0;

        // BUG: the following won't work when v3s, avoid drawing as a temporary workaround.
        for (int i = 0; i < v3s - 1; i++)
        {
            v3p = v3p.Add(ref v3pCount, v3a[i]);
            v3p = v3p.Add(ref v3pCount, v3a[i + 1]);
            //v3p.push_back(r[i]);
            //v3p.push_back(r[i]+Vector3(0,0.2,0));
        }

        if (v3pCount > 1)
        {
            v3p = v3p.Trim(ref v3pCount);
            AddLines((Vector3[])v3p.Clone(), pathMaterial);
            AddCollisionSegments((Vector3[])v3p.Clone());
        }

        if (plugin.path == path)
        {
            v3p = v3p.Clear(ref v3pCount, true);
            int pointCount      = c.GetPointCount();
            var handles         = new Vector3[pointCount];
            int handlesCount    = 0;
            var secHandles      = new Vector3[pointCount];
            int secHandlesCount = 0;

            for (int i = 0; i < pointCount; i++)
            {
                Vector3 p = c.GetPointPosition(i);
                handles = handles.Add(ref handlesCount, p);
                if (i > 0)
                {
                    v3p        = v3p.Add(ref v3pCount, p);
                    v3p        = v3p.Add(ref v3pCount, p + c.GetPointIn(i));
                    secHandles = secHandles.Add(ref secHandlesCount, p + c.GetPointIn(i));
                }

                if (i < pointCount - 1)
                {
                    v3p        = v3p.Add(ref v3pCount, p);
                    v3p        = v3p.Add(ref v3pCount, p + c.GetPointOut(i));
                    secHandles = secHandles.Add(ref secHandlesCount, p + c.GetPointOut(i));
                }
            }

            v3p        = v3p.Trim(ref v3pCount);
            handles    = handles.Trim(ref handlesCount);
            secHandles = secHandles.Trim(ref secHandlesCount);

            if (v3pCount > 1)
            {
                AddLines(v3p, pathThinMaterial);
            }
            if (handlesCount > 0)
            {
                AddHandles(handles, handlesMaterial);
            }
            if (secHandlesCount > 0)
            {
                AddHandles(secHandles, handlesMaterial, false, true);
            }
        }
    }
Exemplo n.º 5
0
    public override void CommitHandle(int index, object restore, bool cancel)
    {
        Curve3D c = path.curve;

        if (!IsInstanceValid(c))
        {
            return;
        }

        UndoRedo ur = plugin.GetUndoRedo();

        if (index < c.GetPointCount())
        {
            if (cancel)
            {
                c.SetPointPosition(index, (Vector3)restore);
                return;
            }
            ur.CreateAction(("Set Curve Point Position"));
            ur.AddDoMethod(c, "set_point_position", index, c.GetPointPosition(index));
            ur.AddUndoMethod(c, "set_point_position", index, restore);
            ur.CommitAction();

            return;
        }

        index = index - c.GetPointCount() + 1;

        int idx = index / 2;
        int t   = index % 2;

        if (t == 0)
        {
            if (cancel)
            {
                c.SetPointIn(index, (Vector3)restore);
                return;
            }

            ur.CreateAction(("Set Curve In Position"));
            ur.AddDoMethod(c, "set_point_in", idx, c.GetPointIn(idx));
            ur.AddUndoMethod(c, "set_point_in", idx, restore);

            if (plugin.mirrorHandleAngle)
            {
                ur.AddDoMethod(c, "set_point_out", idx, plugin.mirrorHandleLength ? -c.GetPointIn(idx) : (-c.GetPointIn(idx).Normalized() * origOutLenght));
                ur.AddUndoMethod(c, "set_point_out", idx, plugin.mirrorHandleLength ? -(Vector3)restore : (-((Vector3)restore).Normalized() * origOutLenght));
            }
            ur.CommitAction();
        }
        else
        {
            if (cancel)
            {
                c.SetPointOut(idx, (Vector3)restore);
                return;
            }

            ur.CreateAction(("Set Curve Out Position"));
            ur.AddDoMethod(c, "set_point_out", idx, c.GetPointOut(idx));
            ur.AddUndoMethod(c, "set_point_out", idx, restore);

            if (plugin.mirrorHandleAngle)
            {
                ur.AddDoMethod(c, "set_point_in", idx, plugin.mirrorHandleLength ? -c.GetPointOut(idx) : (-c.GetPointOut(idx).Normalized() * origInLength));
                ur.AddUndoMethod(c, "set_point_in", idx, plugin.mirrorHandleLength ? -(Vector3)(restore) : (-((Vector3)restore).Normalized() * origInLength));
            }
            ur.CommitAction();
        }
    }
Exemplo n.º 6
0
    public override bool ForwardSpatialGuiInput(Camera camera, InputEvent @event)
    {
        if (!IsInstanceValid(path))
        {
            return(false);
        }
        Curve3D c = path.curve;

        if (!IsInstanceValid(c))
        {
            return(false);
        }
        Transform gt = path.GlobalTransform;
        Transform it = gt.AffineInverse();

        if (@event is InputEventMouseButton mb)
        {
            Vector2 mbPos = mb.Position;

            if (!mb.Pressed)
            {
                SetHandleClicked(false);
            }

            if (mb.Pressed && mb.ButtonIndex == (int)ButtonList.Left && (curveCreate.Pressed || (curveEdit.Pressed && mb.Control)))
            {
                //click into curve, break it down
                Vector3[] v3a             = c.Tessellate();
                int       idx             = 0;
                int       rc              = v3a.Length;
                int       closestSeg      = -1;
                Vector3   closestSegPoint = new Vector3();
                float     closest_d       = float.MaxValue;

                if (rc >= 2)
                {
                    if (camera.UnprojectPosition(gt.Xform(c.GetPointPosition(0))).DistanceTo(mbPos) < clickDist)
                    {
                        return(false); //nope, existing
                    }
                    for (int i = 0; i < c.GetPointCount() - 1; i++)
                    {
                        //find the offset and point index of the place to break up
                        int j = idx;
                        if (camera.UnprojectPosition(gt.Xform(c.GetPointPosition(i + 1))).DistanceTo(mbPos) < clickDist)
                        {
                            return(false); //nope, existing
                        }
                        while (j < rc && c.GetPointPosition(i + 1) != v3a[j])
                        {
                            Vector3 from  = v3a[j];
                            Vector3 to    = v3a[j + 1];
                            float   cdist = from.DistanceTo(to);
                            from = gt.Xform(from);
                            to   = gt.Xform(to);
                            if (cdist > 0)
                            {
                                Vector2[] s = new Vector2[2];
                                s[0] = camera.UnprojectPosition(from);
                                s[1] = camera.UnprojectPosition(to);
                                Vector2 inters = GetClosestPointToSegment2D(mbPos, s);
                                float   d      = inters.DistanceTo(mbPos);

                                if (d < 10 && d < closest_d)
                                {
                                    closest_d  = d;
                                    closestSeg = i;
                                    Vector3 ray_from = camera.ProjectRayOrigin(mbPos);
                                    Vector3 ray_dir  = camera.ProjectRayNormal(mbPos);

                                    Vector3 ra, rb;
                                    GetClosestPointsBetweenSegments(ray_from, ray_from + ray_dir * 4096, from, to, out ra, out rb);

                                    closestSegPoint = it.Xform(rb);
                                }
                            }
                            j++;
                        }
                        if (idx == j)
                        {
                            idx++; //force next
                        }
                        else
                        {
                            idx = j; //swap
                        }
                        if (j == rc)
                        {
                            break;
                        }
                    }
                }

                var ur = GetUndoRedo();
                if (closestSeg != -1)
                {
                    //subdivide

                    ur.CreateAction("Split Path");
                    ur.AddDoMethod(c, "add_point", closestSegPoint, new Vector3(), new Vector3(), closestSeg + 1);
                    ur.AddUndoMethod(c, "remove_point", closestSeg + 1);
                    ur.CommitAction();
                    return(true);
                }
                else
                {
                    Vector3 org;
                    if (c.GetPointCount() == 0)
                    {
                        org = path.Transform.origin;
                    }
                    else
                    {
                        org = gt.Xform(c.GetPointPosition(c.GetPointCount() - 1));
                    }
                    Plane p = new Plane();
                    p.Normal = camera.Transform.basis.GetColumn(2);
                    p.D      = p.Normal.Dot(org);
                    Vector3 ray_from = camera.ProjectRayOrigin(mbPos);
                    Vector3 ray_dir  = camera.ProjectRayNormal(mbPos);

                    Vector3?inters = p.IntersectRay(ray_from, ray_dir);
                    if (inters != null)
                    {
                        ur.CreateAction("Add Point to Curve");
                        ur.AddDoMethod(c, "add_point", it.Xform((Vector3)inters), new Vector3(), new Vector3(), -1);
                        ur.AddUndoMethod(c, "remove_point", c.GetPointCount());
                        ur.CommitAction();
                        return(true);
                    }

                    //add new at pos
                }
            }
            else if (mb.Pressed && ((mb.ButtonIndex == (int)ButtonList.Left && curveDel.Pressed) || (mb.ButtonIndex == (int)ButtonList.Right && curveEdit.Pressed)))
            {
                for (int i = 0; i < c.GetPointCount(); i++)
                {
                    float dist_to_p     = camera.UnprojectPosition(gt.Xform(c.GetPointPosition(i))).DistanceTo(mbPos);
                    float dist_to_p_out = camera.UnprojectPosition(gt.Xform(c.GetPointPosition(i) + c.GetPointOut(i))).DistanceTo(mbPos);
                    float dist_to_p_in  = camera.UnprojectPosition(gt.Xform(c.GetPointPosition(i) + c.GetPointIn(i))).DistanceTo(mbPos);

                    // Find the offset and point index of the place to break up.
                    // Also check for the control points.
                    var ur = GetUndoRedo();
                    if (dist_to_p < clickDist)
                    {
                        ur.CreateAction("Remove Path Point");
                        ur.AddDoMethod(c, "remove_point", i);
                        ur.AddUndoMethod(c, "add_point", c.GetPointPosition(i), c.GetPointIn(i), c.GetPointOut(i), i);
                        ur.CommitAction();
                        return(true);
                    }
                    else if (dist_to_p_out < clickDist)
                    {
                        ur.CreateAction(("Remove Out-Control Point"));
                        ur.AddDoMethod(c, "set_point_out", i, new Vector3());
                        ur.AddUndoMethod(c, "set_point_out", i, c.GetPointOut(i));
                        ur.CommitAction();
                        return(true);
                    }
                    else if (dist_to_p_in < clickDist)
                    {
                        ur.CreateAction(("Remove In-Control Point"));
                        ur.AddDoMethod(c, "set_point_in", i, new Vector3());
                        ur.AddUndoMethod(c, "set_point_in", i, c.GetPointOut(i));
                        ur.CommitAction();
                        return(true);
                    }
                }
            }
        }

        return(false);
    }