Пример #1
0
void create_canvas_line(Geom::Point const &p1, Geom::Point const &p2, guint32 rgba)
{
    SPDesktop *desktop = inkscape_active_desktop();
    SPCtrlLine *line = ControlManager::getManager().createControlLine(sp_desktop_controls(desktop), p1, p2);
    line->setRgba32(rgba);
    sp_canvas_item_show(line);
}
Пример #2
0
VPDrag::VPDrag (SPDocument *document)
{
    this->document = document;
    this->selection = sp_desktop_selection(inkscape_active_desktop());

    this->draggers = NULL;
    this->lines = NULL;
    this->show_lines = true;
    this->front_or_rear_lines = 0x1;

    this->dragging = false;

    this->sel_changed_connection = this->selection->connectChanged(
        sigc::bind (
            sigc::ptr_fun(&vp_drag_sel_changed),
            (gpointer)this )

        );
    this->sel_modified_connection = this->selection->connectModified(
        sigc::bind(
            sigc::ptr_fun(&vp_drag_sel_modified),
            (gpointer)this )
        );

    this->updateDraggers ();
    this->updateLines ();
}
Пример #3
0
VPDragger::VPDragger(VPDrag *parent, Geom::Point p, VanishingPoint &vp)
{
    this->parent = parent;

    this->point = p;
    this->point_original = p;

    this->dragging_started = false;

    if (vp.is_finite()) {
        // create the knot
        this->knot = sp_knot_new (inkscape_active_desktop(), NULL);
        this->knot->setMode(SP_KNOT_MODE_XOR);
        this->knot->setFill(VP_KNOT_COLOR_NORMAL, VP_KNOT_COLOR_NORMAL, VP_KNOT_COLOR_NORMAL);
        this->knot->setStroke(0x000000ff, 0x000000ff, 0x000000ff);
        sp_knot_update_ctrl(this->knot);

        // move knot to the given point
        sp_knot_set_position (this->knot, this->point, SP_KNOT_STATE_NORMAL);
        sp_knot_show (this->knot);

        // connect knot's signals
        g_signal_connect (G_OBJECT (this->knot), "moved", G_CALLBACK (vp_knot_moved_handler), this);
        g_signal_connect (G_OBJECT (this->knot), "grabbed", G_CALLBACK (vp_knot_grabbed_handler), this);
        g_signal_connect (G_OBJECT (this->knot), "ungrabbed", G_CALLBACK (vp_knot_ungrabbed_handler), this);

        // add the initial VP (which may be NULL!)
        this->addVP (vp);
    }
}
Пример #4
0
/**
Create a line from p1 to p2 and add it to the lines list
 */
void
VPDrag::addLine (Geom::Point p1, Geom::Point p2, guint32 rgba)
{
    SPCanvasItem *line = sp_canvas_item_new(sp_desktop_controls(inkscape_active_desktop()), SP_TYPE_CTRLLINE, NULL);
    sp_ctrlline_set_coords(SP_CTRLLINE(line), p1, p2);
    if (rgba != VP_LINE_COLOR_FILL) // fill is the default, so don't set color for it to speed up redraw
        sp_ctrlline_set_rgba32 (SP_CTRLLINE(line), rgba);
    sp_canvas_item_show (line);
    this->lines = g_slist_append (this->lines, line);
}
Пример #5
0
void create_canvas_point(Geom::Point const &pos, double size, guint32 rgba)
{
    SPDesktop *desktop = inkscape_active_desktop();
    SPCanvasItem * canvas_pt = sp_canvas_item_new(sp_desktop_controls(desktop), SP_TYPE_CTRL,
                          "size", size,
                          "filled", 1,
                          "fill_color", rgba,
                          "stroked", 1,
                          "stroke_color", 0x000000ff,
                          NULL);
    SP_CTRL(canvas_pt)->moveto(pos);
}
Пример #6
0
std::set<VanishingPoint*, less_ptr>
VPDragger::VPsOfSelectedBoxes() {
    std::set<VanishingPoint*, less_ptr> sel_vps;
    VanishingPoint *vp;
    // FIXME: Should we take the selection from the parent VPDrag? I guess it shouldn't make a difference.
    Inkscape::Selection *sel = sp_desktop_selection(inkscape_active_desktop());
    for (GSList const* i = sel->itemList(); i != NULL; i = i->next) {
        if (!SP_IS_BOX3D(i->data))
            continue;
        SPBox3D *box = SP_BOX3D(i->data);
        vp = this->findVPWithBox(box);
        if (vp) {
            sel_vps.insert (vp);
        }
    }
    return sel_vps;
}
Пример #7
0
static void
vp_knot_moved_handler (SPKnot */*knot*/, Geom::Point const *ppointer, guint state, gpointer data)
{
    VPDragger *dragger = (VPDragger *) data;
    VPDrag *drag = dragger->parent;

    Geom::Point p = *ppointer;

    // FIXME: take from prefs
    double snap_dist = SNAP_DIST / inkscape_active_desktop()->current_zoom();

    /*
     * We use dragging_started to indicate if we have already checked for the need to split Draggers up.
     * This only has the purpose of avoiding costly checks in the routine below.
     */
    if (!dragger->dragging_started && (state & GDK_SHIFT_MASK)) {
        /* with Shift; if there is more than one box linked to this VP
           we need to split it and create a new perspective */
        if (dragger->numberOfBoxes() > 1) { // FIXME: Don't do anything if *all* boxes of a VP are selected
            std::set<VanishingPoint*, less_ptr> sel_vps = dragger->VPsOfSelectedBoxes();

            std::list<SPBox3D *> sel_boxes;
            for (std::set<VanishingPoint*, less_ptr>::iterator vp = sel_vps.begin(); vp != sel_vps.end(); ++vp) {
                // for each VP that has selected boxes:
                Persp3D *old_persp = (*vp)->get_perspective();
                sel_boxes = (*vp)->selectedBoxes(sp_desktop_selection(inkscape_active_desktop()));

                // we create a new perspective ...
                Persp3D *new_persp = persp3d_create_xml_element (dragger->parent->document, old_persp);

                /* ... unlink the boxes from the old one and
                   FIXME: We need to unlink the _un_selected boxes of each VP so that
                          the correct boxes are kept with the VP being moved */
                std::list<SPBox3D *> bx_lst = persp3d_list_of_boxes(old_persp);
                for (std::list<SPBox3D *>::iterator i = bx_lst.begin(); i != bx_lst.end(); ++i) {
                    if (std::find(sel_boxes.begin(), sel_boxes.end(), *i) == sel_boxes.end()) {
                        /* if a box in the VP is unselected, move it to the
                           newly created perspective so that it doesn't get dragged **/
                        box3d_switch_perspectives(*i, old_persp, new_persp);
                    }
                }
            }
            // FIXME: Do we need to create a new dragger as well?
            dragger->updateZOrders ();
            sp_document_done (sp_desktop_document (inkscape_active_desktop()), SP_VERB_CONTEXT_3DBOX,
                              _("Split vanishing points"));
            return;
        }
    }

    if (!(state & GDK_SHIFT_MASK)) {
        // without Shift; see if we need to snap to another dragger
        for (GList *di = dragger->parent->draggers; di != NULL; di = di->next) {
            VPDragger *d_new = (VPDragger *) di->data;
            if ((d_new != dragger) && (Geom::L2 (d_new->point - p) < snap_dist)) {
                if (have_VPs_of_same_perspective (dragger, d_new)) {
                    // this would result in degenerate boxes, which we disallow for the time being
                    continue;
                }

                // update positions ... (this is needed so that the perspectives are detected as identical)
                // FIXME: This is called a bit too often, isn't it?
                for (std::list<VanishingPoint>::iterator j = dragger->vps.begin(); j != dragger->vps.end(); ++j) {
                    (*j).set_pos(d_new->point);
                }

                // ... join lists of VPs ...
                d_new->vps.merge(dragger->vps);

                // ... delete old dragger ...
                drag->draggers = g_list_remove (drag->draggers, dragger);
                delete dragger;
                dragger = NULL;

                // ... and merge any duplicate perspectives
                d_new->mergePerspectives();

                // TODO: Update the new merged dragger
                d_new->updateTip();

                d_new->parent->updateBoxDisplays (); // FIXME: Only update boxes in current dragger!
                d_new->updateZOrders ();

                drag->updateLines ();

                // TODO: Undo machinery; this doesn't work yet because perspectives must be created and
                //       deleted according to changes in the svg representation, not based on any user input
                //       as is currently the case.

                sp_document_done (sp_desktop_document (inkscape_active_desktop()), SP_VERB_CONTEXT_3DBOX,
                                  _("Merge vanishing points"));

                return;
            }
        }
    }


    dragger->point = p; // FIXME: Brauchen wir dragger->point überhaupt?

    dragger->updateVPs(p);
    dragger->updateBoxDisplays();
    dragger->parent->updateBoxHandles (); // FIXME: Only update the handles of boxes on this dragger (not on all)
    dragger->updateZOrders();

    drag->updateLines();

    dragger->dragging_started = true;
}
Пример #8
0
/**
 * Depending on the value of all_lines, draw the front and/or rear perspective lines starting from the given corners.
 */
void
VPDrag::drawLinesForFace (const SPBox3D *box, Proj::Axis axis) //, guint corner1, guint corner2, guint corner3, guint corner4)
{
    guint color;
    switch (axis) {
        // TODO: Make color selectable by user
        case Proj::X: color = VP_LINE_COLOR_STROKE_X; break;
        case Proj::Y: color = VP_LINE_COLOR_STROKE_Y; break;
        case Proj::Z: color = VP_LINE_COLOR_STROKE_Z; break;
        default: g_assert_not_reached();
    }

    Geom::Point corner1, corner2, corner3, corner4;
    box3d_corners_for_PLs (box, axis, corner1, corner2, corner3, corner4);

    g_return_if_fail (box3d_get_perspective(box));
    Proj::Pt2 vp = persp3d_get_VP (box3d_get_perspective(box), axis);
    if (vp.is_finite()) {
        // draw perspective lines for finite VPs
        Geom::Point pt = vp.affine();
        if (this->front_or_rear_lines & 0x1) {
            // draw 'front' perspective lines
            this->addLine (corner1, pt, color);
            this->addLine (corner2, pt, color);
        }
        if (this->front_or_rear_lines & 0x2) {
            // draw 'rear' perspective lines
            this->addLine (corner3, pt, color);
            this->addLine (corner4, pt, color);
        }
    } else {
        // draw perspective lines for infinite VPs
        boost::optional<Geom::Point> pt1, pt2, pt3, pt4;
        Persp3D *persp = box3d_get_perspective(box);
        SPDesktop *desktop = inkscape_active_desktop (); // FIXME: Store the desktop in VPDrag
        Box3D::PerspectiveLine pl (corner1, axis, persp);
        pt1 = pl.intersection_with_viewbox(desktop);

        pl = Box3D::PerspectiveLine (corner2, axis, persp);
        pt2 = pl.intersection_with_viewbox(desktop);

        pl = Box3D::PerspectiveLine (corner3, axis, persp);
        pt3 = pl.intersection_with_viewbox(desktop);

        pl = Box3D::PerspectiveLine (corner4, axis, persp);
        pt4 = pl.intersection_with_viewbox(desktop);

        if (!pt1 || !pt2 || !pt3 || !pt4) {
            // some perspective lines s are outside the canvas; currently we don't draw any of them
            return;
        }
        if (this->front_or_rear_lines & 0x1) {
            // draw 'front' perspective lines
            this->addLine (corner1, *pt1, color);
            this->addLine (corner2, *pt2, color);
        }
        if (this->front_or_rear_lines & 0x2) {
            // draw 'rear' perspective lines
            this->addLine (corner3, *pt3, color);
            this->addLine (corner4, *pt4, color);
        }
    }
}