diff options
Diffstat (limited to 'src/persp3d.cpp')
| -rw-r--r-- | src/persp3d.cpp | 112 |
1 files changed, 70 insertions, 42 deletions
diff --git a/src/persp3d.cpp b/src/persp3d.cpp index d2c6978bb..b21fd6cab 100644 --- a/src/persp3d.cpp +++ b/src/persp3d.cpp @@ -19,6 +19,7 @@ #include "vanishing-point.h" #include "ui/tools/box3d-tool.h" #include "box3d.h" +#include "svg/stringstream.h" #include "xml/document.h" #include "xml/node-event-vector.h" #include "desktop-handles.h" @@ -30,9 +31,6 @@ using Inkscape::DocumentUndo; static void persp3d_on_repr_attr_changed (Inkscape::XML::Node * repr, const gchar *key, const gchar *oldval, const gchar *newval, bool is_interactive, void * data); -static void persp3d_update_with_point (Persp3DImpl *persp_impl, Proj::Axis const axis, Proj::Pt2 const &new_image); -static gchar * persp3d_pt_to_str (Persp3DImpl *persp_impl, Proj::Axis const axis); - static int global_counter = 0; #include "sp-factory.h" @@ -102,36 +100,48 @@ void Persp3D::release() { // FIXME: Currently we only read the finite positions of vanishing points; // should we move VPs into their own repr (as it's done for SPStop, e.g.)? void Persp3D::set(unsigned key, gchar const *value) { - Persp3DImpl *persp_impl = this->perspective_impl; + + // Read values are in 'user units'. + double scale_x = 1.0; + double scale_y = 1.0; + SPRoot *root = document->getRoot(); + if( root->viewBox_set ) { + scale_x = root->width.computed / root->viewBox.width(); + scale_y = root->height.computed / root->viewBox.height(); + } switch (key) { case SP_ATTR_INKSCAPE_PERSP3D_VP_X: { if (value) { - Proj::Pt2 new_image (value); - persp3d_update_with_point (persp_impl, Proj::X, new_image); + Proj::Pt2 pt (value); + Proj::Pt2 ptn ( pt[0]*scale_x, pt[1]*scale_y, pt[2] ); + perspective_impl->tmat.set_image_pt( Proj::X, ptn ); } break; } case SP_ATTR_INKSCAPE_PERSP3D_VP_Y: { if (value) { - Proj::Pt2 new_image (value); - persp3d_update_with_point (persp_impl, Proj::Y, new_image); - break; + Proj::Pt2 pt (value); + Proj::Pt2 ptn ( pt[0]*scale_x, pt[1]*scale_y, pt[2] ); + perspective_impl->tmat.set_image_pt( Proj::Y, ptn ); } + break; } case SP_ATTR_INKSCAPE_PERSP3D_VP_Z: { if (value) { - Proj::Pt2 new_image (value); - persp3d_update_with_point (persp_impl, Proj::Z, new_image); - break; + Proj::Pt2 pt (value); + Proj::Pt2 ptn ( pt[0]*scale_x, pt[1]*scale_y, pt[2] ); + perspective_impl->tmat.set_image_pt( Proj::Z, ptn ); } + break; } case SP_ATTR_INKSCAPE_PERSP3D_ORIGIN: { if (value) { - Proj::Pt2 new_image (value); - persp3d_update_with_point (persp_impl, Proj::W, new_image); - break; + Proj::Pt2 pt (value); + Proj::Pt2 ptn ( pt[0]*scale_x, pt[1]*scale_y, pt[2] ); + perspective_impl->tmat.set_image_pt( Proj::W, ptn ); } + break; } default: { SPObject::set(key, value); @@ -169,10 +179,19 @@ Persp3D *persp3d_create_xml_element(SPDocument *document, Persp3DImpl *dup) {// repr = xml_doc->createElement("inkscape:perspective"); repr->setAttribute("sodipodi:type", "inkscape:persp3d"); - Proj::Pt2 proj_vp_x = Proj::Pt2 (0.0, document->getHeight().value("px")/2, 1.0); - Proj::Pt2 proj_vp_y = Proj::Pt2 (0.0, 1000.0, 0.0); - Proj::Pt2 proj_vp_z = Proj::Pt2 (document->getWidth().value("px"), document->getHeight().value("px")/2, 1.0); - Proj::Pt2 proj_origin = Proj::Pt2 (document->getWidth().value("px")/2, document->getHeight().value("px")/3, 1.0); + // Use 'user-units' + double width = document->getWidth().value("px"); + double height = document->getHeight().value("px"); + if( document->getRoot()->viewBox_set ) { + Geom::Rect vb = document->getRoot()->viewBox; + width = vb.width(); + height = vb.height(); + } + + Proj::Pt2 proj_vp_x = Proj::Pt2 (0.0, height/2.0, 1.0); + Proj::Pt2 proj_vp_y = Proj::Pt2 (0.0, 1000.0, 0.0); + Proj::Pt2 proj_vp_z = Proj::Pt2 (width, height/2.0, 1.0); + Proj::Pt2 proj_origin = Proj::Pt2 (width/2.0, height/3.0, 1.0 ); if (dup) { proj_vp_x = dup->tmat.column (Proj::X); @@ -217,7 +236,6 @@ Persp3D *persp3d_document_first_persp(SPDocument *document) * Virtual write: write object attributes to repr. */ Inkscape::XML::Node* Persp3D::write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags) { - Persp3DImpl *persp_impl = this->perspective_impl; if ((flags & SP_OBJECT_WRITE_BUILD & SP_OBJECT_WRITE_EXT) && !repr) { // this is where we end up when saving as plain SVG (also in other circumstances?); @@ -226,18 +244,39 @@ Inkscape::XML::Node* Persp3D::write(Inkscape::XML::Document *xml_doc, Inkscape:: } if (flags & SP_OBJECT_WRITE_EXT) { - gchar *str = NULL; // FIXME: Should this be freed each time we set an attribute or only in the end or at all? - str = persp3d_pt_to_str (persp_impl, Proj::X); - repr->setAttribute("inkscape:vp_x", str); - - str = persp3d_pt_to_str (persp_impl, Proj::Y); - repr->setAttribute("inkscape:vp_y", str); - str = persp3d_pt_to_str (persp_impl, Proj::Z); - repr->setAttribute("inkscape:vp_z", str); - - str = persp3d_pt_to_str (persp_impl, Proj::W); - repr->setAttribute("inkscape:persp3d-origin", str); + // Written values are in 'user units'. + double scale_x = 1.0; + double scale_y = 1.0; + SPRoot *root = document->getRoot(); + if( root->viewBox_set ) { + scale_x = root->viewBox.width() / root->width.computed; + scale_y = root->viewBox.height() / root->height.computed; + } + { + Proj::Pt2 pt = perspective_impl->tmat.column( Proj::X ); + Inkscape::SVGOStringStream os; + os << pt[0] * scale_x << " : " << pt[1] * scale_y << " : " << pt[2]; + repr->setAttribute("inkscape:vp_x", os.str().c_str()); + } + { + Proj::Pt2 pt = perspective_impl->tmat.column( Proj::Y ); + Inkscape::SVGOStringStream os; + os << pt[0] * scale_x << " : " << pt[1] * scale_y << " : " << pt[2]; + repr->setAttribute("inkscape:vp_y", os.str().c_str()); + } + { + Proj::Pt2 pt = perspective_impl->tmat.column( Proj::Z ); + Inkscape::SVGOStringStream os; + os << pt[0] * scale_x << " : " << pt[1] * scale_y << " : " << pt[2]; + repr->setAttribute("inkscape:vp_z", os.str().c_str()); + } + { + Proj::Pt2 pt = perspective_impl->tmat.column( Proj::W ); + Inkscape::SVGOStringStream os; + os << pt[0] * scale_x << " : " << pt[1] * scale_y << " : " << pt[2]; + repr->setAttribute("inkscape:persp3d-origin", os.str().c_str()); + } } SPObject::write(xml_doc, repr, flags); @@ -329,23 +368,12 @@ persp3d_rotate_VP (Persp3D *persp, Proj::Axis axis, double angle, bool alt_press } void -persp3d_update_with_point (Persp3DImpl *persp_impl, Proj::Axis const axis, Proj::Pt2 const &new_image) { - persp_impl->tmat.set_image_pt (axis, new_image); -} - -void persp3d_apply_affine_transformation (Persp3D *persp, Geom::Affine const &xform) { persp->perspective_impl->tmat *= xform; persp3d_update_box_reprs(persp); persp->updateRepr(SP_OBJECT_WRITE_EXT); } -gchar * -persp3d_pt_to_str (Persp3DImpl *persp_impl, Proj::Axis const axis) -{ - return persp_impl->tmat.pt_to_str(axis); -} - void persp3d_add_box (Persp3D *persp, SPBox3D *box) { Persp3DImpl *persp_impl = persp->perspective_impl; |
