void SPDocument::add_persp3d (Persp3D * const /*persp*/) { SPDefs *defs = SP_ROOT(this->root)->defs; for (SPObject *i = sp_object_first_child(SP_OBJECT(defs)); i != NULL; i = SP_OBJECT_NEXT(i) ) { if (SP_IS_PERSP3D(i)) { g_print ("Encountered a Persp3D in defs\n"); } } g_print ("Adding Persp3D to defs\n"); persp3d_create_xml_element (this); }
/* Create a default perspective in document defs if none is present (which can happen, among other * circumstances, after 'vacuum defs' or when a pre-0.46 file is opened). */ static void sp_box3d_context_ensure_persp_in_defs(SPDocument *document) { SPDefs *defs = (SPDefs *) SP_DOCUMENT_DEFS(document); bool has_persp = false; for (SPObject *child = sp_object_first_child(defs); child != NULL; child = SP_OBJECT_NEXT(child) ) { if (SP_IS_PERSP3D(child)) { has_persp = true; break; } } if (!has_persp) { document->setCurrentPersp3D(persp3d_create_xml_element (document)); } }
SPDocument * sp_document_create(Inkscape::XML::Document *rdoc, gchar const *uri, gchar const *base, gchar const *name, unsigned int keepalive) { SPDocument *document; Inkscape::XML::Node *rroot; Inkscape::Version sodipodi_version; Inkscape::Preferences *prefs = Inkscape::Preferences::get(); rroot = rdoc->root(); document = new SPDocument(); document->keepalive = keepalive; document->rdoc = rdoc; document->rroot = rroot; #ifndef WIN32 prepend_current_dir_if_relative(&(document->uri), uri); #else // FIXME: it may be that prepend_current_dir_if_relative works OK on windows too, test! document->uri = uri? g_strdup(uri) : NULL; #endif // base is simply the part of the path before filename; e.g. when running "inkscape ../file.svg" the base is "../" // which is why we use g_get_current_dir() in calculating the abs path above //This is NULL for a new document if (base) document->base = g_strdup(base); else document->base = NULL; document->name = g_strdup(name); document->root = sp_object_repr_build_tree(document, rroot); sodipodi_version = SP_ROOT(document->root)->version.sodipodi; /* fixme: Not sure about this, but lets assume ::build updates */ rroot->setAttribute("sodipodi:version", SODIPODI_VERSION); rroot->setAttribute("inkscape:version", Inkscape::version_string); /* fixme: Again, I moved these here to allow version determining in ::build (Lauris) */ /* Quick hack 2 - get default image size into document */ if (!rroot->attribute("width")) rroot->setAttribute("width", "100%"); if (!rroot->attribute("height")) rroot->setAttribute("height", "100%"); /* End of quick hack 2 */ /* Quick hack 3 - Set uri attributes */ if (uri) { rroot->setAttribute("sodipodi:docname", uri); } /* End of quick hack 3 */ /* Eliminate obsolete sodipodi:docbase, for privacy reasons */ rroot->setAttribute("sodipodi:docbase", NULL); /* Eliminate any claim to adhere to a profile, as we don't try to */ rroot->setAttribute("baseProfile", NULL); // creating namedview if (!sp_item_group_get_child_by_name((SPGroup *) document->root, NULL, "sodipodi:namedview")) { // if there's none in the document already, Inkscape::XML::Node *rnew = NULL; rnew = rdoc->createElement("sodipodi:namedview"); //rnew->setAttribute("id", "base"); // Add namedview data from the preferences // we can't use getAllEntries because this could produce non-SVG doubles Glib::ustring pagecolor = prefs->getString("/template/base/pagecolor"); if (!pagecolor.empty()) { rnew->setAttribute("pagecolor", pagecolor.data()); } Glib::ustring bordercolor = prefs->getString("/template/base/bordercolor"); if (!bordercolor.empty()) { rnew->setAttribute("bordercolor", bordercolor.data()); } sp_repr_set_svg_double(rnew, "borderopacity", prefs->getDouble("/template/base/borderopacity", 1.0)); sp_repr_set_svg_double(rnew, "objecttolerance", prefs->getDouble("/template/base/objecttolerance", 10.0)); sp_repr_set_svg_double(rnew, "gridtolerance", prefs->getDouble("/template/base/gridtolerance", 10.0)); sp_repr_set_svg_double(rnew, "guidetolerance", prefs->getDouble("/template/base/guidetolerance", 10.0)); sp_repr_set_svg_double(rnew, "inkscape:pageopacity", prefs->getDouble("/template/base/inkscape:pageopacity", 0.0)); sp_repr_set_int(rnew, "inkscape:pageshadow", prefs->getInt("/template/base/inkscape:pageshadow", 2)); sp_repr_set_int(rnew, "inkscape:window-width", prefs->getInt("/template/base/inkscape:window-width", 640)); sp_repr_set_int(rnew, "inkscape:window-height", prefs->getInt("/template/base/inkscape:window-height", 480)); // insert into the document rroot->addChild(rnew, NULL); // clean up Inkscape::GC::release(rnew); } /* Defs */ if (!SP_ROOT(document->root)->defs) { Inkscape::XML::Node *r; r = rdoc->createElement("svg:defs"); rroot->addChild(r, NULL); Inkscape::GC::release(r); g_assert(SP_ROOT(document->root)->defs); } /* Default RDF */ rdf_set_defaults( document ); if (keepalive) { inkscape_ref(); } // Remark: Here, we used to create a "currentpersp3d" element in the document defs. // But this is probably a bad idea since we need to adapt it for every change of selection, which will // completely clutter the undo history. Maybe rather save it to prefs on exit and re-read it on startup? document->current_persp3d = persp3d_document_first_persp(document); if (!document->current_persp3d) { document->current_persp3d = persp3d_create_xml_element (document); } sp_document_set_undo_sensitive(document, true); // reset undo key when selection changes, so that same-key actions on different objects are not coalesced if (!Inkscape::NSApplication::Application::getNewGui()) { g_signal_connect(G_OBJECT(INKSCAPE), "change_selection", G_CALLBACK(sp_document_reset_key), document); g_signal_connect(G_OBJECT(INKSCAPE), "activate_desktop", G_CALLBACK(sp_document_reset_key), document); } else { document->_selection_changed_connection = Inkscape::NSApplication::Editor::connectSelectionChanged (sigc::mem_fun (*document, &SPDocument::reset_key)); document->_desktop_activated_connection = Inkscape::NSApplication::Editor::connectDesktopActivated (sigc::mem_fun (*document, &SPDocument::reset_key)); } return document; }
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; }