X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=src%2Fdesktop.cpp;h=932d79ff2e7dadfe24d1c6e3cee85e5db55c0d79;hb=9e973c4fb2183b877bb600a7e9c75e93b3e7d6d1;hp=d159fbc78d236df8f3996087c59092ea28bfc74f;hpb=2338d0f7bcdb2ca35667da4b02dd03ede37e4a65;p=inkscape.git diff --git a/src/desktop.cpp b/src/desktop.cpp index d159fbc78..932d79ff2 100644 --- a/src/desktop.cpp +++ b/src/desktop.cpp @@ -11,7 +11,8 @@ * John Bintz * Johan Engelen * - * Copyright (C) 2006-2007 Johan Engelen + * Copyright (C) 2007 Jon A. Cruz + * Copyright (C) 2006-2008 Johan Engelen * Copyright (C) 2006 John Bintz * Copyright (C) 2004 MenTaLguY * Copyright (C) 1999-2002 Lauris Kaplinski @@ -54,6 +55,7 @@ #include #include +#include #include "macros.h" #include "inkscape-private.h" @@ -75,13 +77,22 @@ #include "display/gnome-canvas-acetate.h" #include "display/sodipodi-ctrlrect.h" #include "display/sp-canvas-util.h" +#include "display/canvas-temporary-item-list.h" +#include "display/snap-indicator.h" #include "libnr/nr-matrix-div.h" #include "libnr/nr-rect-ops.h" #include "ui/dialog/dialog-manager.h" #include "xml/repr.h" #include "message-context.h" +#include "device-manager.h" +#include "layer-fns.h" #include "layer-manager.h" #include "event-log.h" +#include "display/canvas-grid.h" +#include "widgets/desktop-widget.h" +#include "box3d-context.h" + +#include "display/sp-canvas.h" namespace Inkscape { namespace XML { class Node; }} @@ -101,48 +112,65 @@ static void _update_snap_distances (SPDesktop *desktop); * \pre namedview != NULL. * \pre canvas != NULL. */ -SPDesktop::SPDesktop() -{ - _dlg_mgr = NULL; - _widget = 0; - namedview = NULL; - selection = NULL; - acetate = NULL; - main = NULL; - grid = NULL; - guides = NULL; - drawing = NULL; - sketch = NULL; - controls = NULL; - event_context = 0; - layer_manager = 0; - +SPDesktop::SPDesktop() : + _dlg_mgr( 0 ), + namedview( 0 ), + canvas( 0 ), + selection( 0 ), + event_context( 0 ), + layer_manager( 0 ), + event_log( 0 ), + temporary_item_list( 0 ), + snapindicator( 0 ), + acetate( 0 ), + main( 0 ), + gridgroup( 0 ), + guides( 0 ), + drawing( 0 ), + sketch( 0 ), + controls( 0 ), + tempgroup ( 0 ), + table( 0 ), + page( 0 ), + page_border( 0 ), + current( 0 ), + zooms_past( 0 ), + zooms_future( 0 ), + dkey( 0 ), + number( 0 ), + window_state(0), + interaction_disabled_counter( 0 ), + waiting_cursor( false ), + guides_active( false ), + gr_item( 0 ), + gr_point_type( 0 ), + gr_point_i( 0 ), + gr_fill_or_stroke( true ), + _layer_hierarchy( 0 ), + _reconstruction_old_layer_id( 0 ), + _display_mode(Inkscape::RENDERMODE_NORMAL), + _saved_display_mode(Inkscape::RENDERMODE_NORMAL), + _widget( 0 ), + _inkscape( 0 ), + _guides_message_context( 0 ), + _active( false ), + _w2d(), + _d2w(), + _doc2dt( NR::Matrix(NR::scale(1, -1)) ), + grids_visible( false ) +{ _d2w.set_identity(); _w2d.set_identity(); - _doc2dt = NR::Matrix(NR::scale(1, -1)); - - guides_active = false; - - zooms_past = NULL; - zooms_future = NULL; - is_fullscreen = false; - - gr_item = NULL; - gr_point_type = 0; - gr_point_i = 0; - gr_fill_or_stroke = true; - - _layer_hierarchy = NULL; - _active = false; - - selection = Inkscape::GC::release (new Inkscape::Selection (this)); + selection = Inkscape::GC::release( new Inkscape::Selection(this) ); } void SPDesktop::init (SPNamedView *nv, SPCanvas *aCanvas) - { + // Temporary workaround for link order issues: + Inkscape::DeviceManager::getManager().getDevices(); + _guides_message_context = new Inkscape::MessageContext(const_cast(messageStack())); current = sp_repr_css_attr_inherited (inkscape_get_repr (INKSCAPE, "desktop"), "style"); @@ -155,7 +183,7 @@ SPDesktop::init (SPNamedView *nv, SPCanvas *aCanvas) sp_document_ensure_up_to_date (document); /* Setup Dialog Manager */ - _dlg_mgr = new Inkscape::UI::Dialog::DialogManager(); + _dlg_mgr = &Inkscape::UI::Dialog::DialogManager::getInstance(); dkey = sp_item_display_key_new (1); @@ -198,10 +226,11 @@ SPDesktop::init (SPNamedView *nv, SPCanvas *aCanvas) setDisplayModeNormal(); } - grid = (SPCanvasGroup *) sp_canvas_item_new (main, SP_TYPE_CANVAS_GROUP, NULL); + gridgroup = (SPCanvasGroup *) sp_canvas_item_new (main, SP_TYPE_CANVAS_GROUP, NULL); guides = (SPCanvasGroup *) sp_canvas_item_new (main, SP_TYPE_CANVAS_GROUP, NULL); sketch = (SPCanvasGroup *) sp_canvas_item_new (main, SP_TYPE_CANVAS_GROUP, NULL); controls = (SPCanvasGroup *) sp_canvas_item_new (main, SP_TYPE_CANVAS_GROUP, NULL); + tempgroup = (SPCanvasGroup *) sp_canvas_item_new (main, SP_TYPE_CANVAS_GROUP, NULL); /* Push select tool to the bottom of stack */ /** \todo @@ -258,9 +287,7 @@ SPDesktop::init (SPNamedView *nv, SPCanvas *aCanvas) _reconstruction_finish_connection = document->connectReconstructionFinish(sigc::bind(sigc::ptr_fun(_reconstruction_finish), this)); _reconstruction_old_layer_id = NULL; - - _commit_connection = document->connectCommit(sigc::mem_fun(*this, &SPDesktop::updateNow)); - + // ? // sp_active_desktop_set (desktop); _inkscape = INKSCAPE; @@ -295,11 +322,27 @@ SPDesktop::init (SPNamedView *nv, SPCanvas *aCanvas) /* setup LayerManager */ // (Setting up after the connections are all in place, as it may use some of them) layer_manager = new Inkscape::LayerManager( this ); + + showGrids(namedview->grids_visible, false); + + temporary_item_list = new Inkscape::Display::TemporaryItemList( this ); + snapindicator = new Inkscape::Display::SnapIndicator ( this ); } void SPDesktop::destroy() { + if (snapindicator) { + delete snapindicator; + snapindicator = NULL; + } + if (temporary_item_list) { + delete temporary_item_list; + temporary_item_list = NULL; + } + + namedview->hide(this); + _activate_connection.disconnect(); _deactivate_connection.disconnect(); _sel_modified_connection.disconnect(); @@ -322,6 +365,12 @@ void SPDesktop::destroy() if (_layer_hierarchy) { delete _layer_hierarchy; +// _layer_hierarchy = NULL; //this should be here, but commented to find other bug somewhere else. + } + + if (layer_manager) { + delete layer_manager; + layer_manager = NULL; } if (_inkscape) { @@ -345,30 +394,58 @@ SPDesktop::~SPDesktop() {} //-------------------------------------------------------------------- /* Public methods */ -void SPDesktop::setDisplayModeNormal() + +/* These methods help for temporarily showing things on-canvas. + * The *only* valid use of the TemporaryItem* that you get from add_temporary_canvasitem + * is when you want to prematurely remove the item from the canvas, by calling + * desktop->remove_temporary_canvasitem(tempitem). + */ +/** Note that lifetime is measured in milliseconds + * One should *not* keep a reference to the SPCanvasItem, the temporary item code will + * delete the object for you and the reference will become invalid without you knowing it. + * It is perfectly safe to ignore the returned pointer: the object is deleted by itself, so don't delete it elsewhere! + * The *only* valid use of the returned TemporaryItem* is as argument for SPDesktop::remove_temporary_canvasitem, + * because the object might be deleted already without you knowing it. + * move_to_bottom = true by default so the item does not interfere with handling of other items on the canvas like nodes. + */ +Inkscape::Display::TemporaryItem * +SPDesktop::add_temporary_canvasitem (SPCanvasItem *item, guint lifetime, bool move_to_bottom) { - SP_CANVAS_ARENA (drawing)->arena->rendermode = RENDERMODE_NORMAL; - canvas->rendermode = RENDERMODE_NORMAL; // canvas needs that for choosing the best buffer size - displayMode = RENDERMODE_NORMAL; - sp_canvas_item_affine_absolute (SP_CANVAS_ITEM (main), _d2w); // redraw - _widget->setTitle(SP_DOCUMENT_NAME(sp_desktop_document(this))); + if (move_to_bottom) { + sp_canvas_item_move_to_z(item, 0); + } + + return temporary_item_list->add_item(item, lifetime); } -void SPDesktop::setDisplayModeOutline() +/** It is perfectly safe to call this function while the object has already been deleted due to a timeout. +*/ +void +SPDesktop::remove_temporary_canvasitem (Inkscape::Display::TemporaryItem * tempitem) { - SP_CANVAS_ARENA (drawing)->arena->rendermode = RENDERMODE_OUTLINE; - canvas->rendermode = RENDERMODE_OUTLINE; // canvas needs that for choosing the best buffer size - displayMode = RENDERMODE_OUTLINE; + // check for non-null temporary_item_list, because during destruction of desktop, some destructor might try to access this list! + if (tempitem && temporary_item_list) { + temporary_item_list->delete_item(tempitem); + } +} + +void SPDesktop::_setDisplayMode(Inkscape::RenderMode mode) { + SP_CANVAS_ARENA (drawing)->arena->rendermode = mode; + canvas->rendermode = mode; + _display_mode = mode; + if (mode != Inkscape::RENDERMODE_OUTLINE) { + _saved_display_mode = _display_mode; + } sp_canvas_item_affine_absolute (SP_CANVAS_ITEM (main), _d2w); // redraw _widget->setTitle(SP_DOCUMENT_NAME(sp_desktop_document(this))); } -void SPDesktop::displayModeToggle() -{ - if (displayMode == RENDERMODE_OUTLINE) - setDisplayModeNormal(); - else - setDisplayModeOutline(); +void SPDesktop::displayModeToggle() { + if (_display_mode == Inkscape::RENDERMODE_OUTLINE) { + _setDisplayMode(_saved_display_mode); + } else { + _setDisplayMode(Inkscape::RENDERMODE_OUTLINE); + } } /** @@ -389,7 +466,7 @@ SPObject *SPDesktop::currentLayer() const /** * Sets the current layer of the desktop. - * + * * Make \a object the top layer. */ void SPDesktop::setCurrentLayer(SPObject *object) { @@ -399,6 +476,31 @@ void SPDesktop::setCurrentLayer(SPObject *object) { _layer_hierarchy->setBottom(object); } +void SPDesktop::toggleLayerSolo(SPObject *object) { + g_return_if_fail(SP_IS_GROUP(object)); + g_return_if_fail( currentRoot() == object || (currentRoot() && currentRoot()->isAncestorOf(object)) ); + + bool othersShowing = false; + std::vector layers; + for ( SPObject* obj = Inkscape::next_layer(currentRoot(), object); obj; obj = Inkscape::next_layer(currentRoot(), obj) ) { + layers.push_back(obj); + othersShowing |= !SP_ITEM(obj)->isHidden(); + } + for ( SPObject* obj = Inkscape::previous_layer(currentRoot(), object); obj; obj = Inkscape::previous_layer(currentRoot(), obj) ) { + layers.push_back(obj); + othersShowing |= !SP_ITEM(obj)->isHidden(); + } + + + if ( SP_ITEM(object)->isHidden() ) { + SP_ITEM(object)->setHidden(false); + } + + for ( std::vector::iterator it = layers.begin(); it != layers.end(); ++it ) { + SP_ITEM(*it)->setHidden(othersShowing); + } +} + /** * Return layer that contains \a object. */ @@ -479,6 +581,15 @@ SPDesktop::change_document (SPDocument *theDocument) selection->clear(); setDocument (theDocument); + + /* update the rulers, connect the desktop widget's signal to the new namedview etc. + (this can probably be done in a better way) */ + Gtk::Window *parent = this->getToplevel(); + g_assert(parent != NULL); + SPDesktopWidget *dtw = (SPDesktopWidget *) parent->get_data("desktopwidget"); + if (dtw) dtw->desktop = this; + sp_desktop_widget_update_namedview(dtw); + _namedview_modified (namedview, SP_OBJECT_MODIFIED_FLAG, this); _document_replaced_signal.emit (this, theDocument); } @@ -623,7 +734,7 @@ SPDesktop::push_current_zoom (GList **history) } /** - * Set viewbox. + * Set viewbox (x0, x1, y0 and y1 are in document pixels. Border is in screen pixels). */ void SPDesktop::set_display_area (double x0, double y0, double x1, double y1, double border, bool log) @@ -651,7 +762,7 @@ SPDesktop::set_display_area (double x0, double y0, double x1, double y1, double newscale = viewbox.dimensions()[NR::Y] / (y1 - y0); } - newscale = CLAMP(newscale, SP_DESKTOP_ZOOM_MIN, SP_DESKTOP_ZOOM_MAX); + newscale = CLAMP(newscale, SP_DESKTOP_ZOOM_MIN, SP_DESKTOP_ZOOM_MAX); // unit: 'screen pixels' per 'document pixels' int clear = FALSE; if (!NR_DF_TEST_CLOSE (newscale, scale, 1e-4 * scale)) { @@ -662,13 +773,16 @@ SPDesktop::set_display_area (double x0, double y0, double x1, double y1, double clear = TRUE; } - /* Calculate top left corner */ + /* Calculate top left corner (in document pixels) */ x0 = cx - 0.5 * viewbox.dimensions()[NR::X] / newscale; y1 = cy + 0.5 * viewbox.dimensions()[NR::Y] / newscale; /* Scroll */ sp_canvas_scroll_to (canvas, x0 * newscale - border, y1 * -newscale - border, clear); + /* update perspective lines if we are in the 3D box tool (so that infinite ones are shown correctly) */ + sp_box3d_context_update_lines(event_context); + _widget->updateRulers(); _widget->updateScrollbars(expansion(_d2w)); _widget->updateZoom(); @@ -824,7 +938,7 @@ SPDesktop::zoom_page() NR::Rect d(NR::Point(0, 0), NR::Point(sp_document_width(doc()), sp_document_height(doc()))); - if (d.dimensions()[NR::X] < 1.0 || d.dimensions()[NR::Y] < 1.0) { + if (d.isEmpty(1.0)) { return; } @@ -855,13 +969,13 @@ SPDesktop::zoom_page_width() void SPDesktop::zoom_selection() { - NR::Rect const d = selection->bounds(); + NR::Maybe const d = selection->bounds(); - if (d.dimensions()[NR::X] < 0.1 || d.dimensions()[NR::Y] < 0.1) { + if ( !d || d->isEmpty(0.1) ) { return; } - set_display_area(d, 10); + set_display_area(*d, 10); } /** @@ -888,13 +1002,23 @@ SPDesktop::zoom_drawing() /* Note that the second condition here indicates that ** there are no items in the drawing. */ - if ( !d || d->dimensions()[NR::X] < 1.0 || d->dimensions()[NR::Y] < 1.0 ) { + if ( !d || d->isEmpty(1.0) ) { return; } set_display_area(*d, 10); } +/** + * Scroll canvas by specific coordinate amount in svg coordinates. + */ +void +SPDesktop::scroll_world_in_svg_coords (double dx, double dy, bool is_scrolling) +{ + double scale = expansion(_d2w); + scroll_world(dx*scale, dy*scale, is_scrolling); +} + /** * Scroll canvas by specific coordinate amount. */ @@ -907,6 +1031,9 @@ SPDesktop::scroll_world (double dx, double dy, bool is_scrolling) sp_canvas_scroll_to(canvas, viewbox.min()[NR::X] - dx, viewbox.min()[NR::Y] - dy, FALSE, is_scrolling); + /* update perspective lines if we are in the 3D box tool (so that infinite ones are shown correctly) */ + sp_box3d_context_update_lines(event_context); + _widget->updateRulers(); _widget->updateScrollbars(expansion(_d2w)); } @@ -956,6 +1083,36 @@ SPDesktop::scroll_to_point (NR::Point const *p, gdouble autoscrollspeed) return false; } +bool +SPDesktop::is_iconified() +{ + return 0!=(window_state & GDK_WINDOW_STATE_ICONIFIED); +} + +void +SPDesktop::iconify() +{ + _widget->setIconified(); +} + +bool +SPDesktop::is_maximized() +{ + return 0!=(window_state & GDK_WINDOW_STATE_MAXIMIZED); +} + +void +SPDesktop::maximize() +{ + _widget->setMaximized(); +} + +bool +SPDesktop::is_fullscreen() +{ + return 0!=(window_state & GDK_WINDOW_STATE_FULLSCREEN); +} + void SPDesktop::fullscreen() { @@ -986,6 +1143,12 @@ SPDesktop::setWindowTransient (void *p, int transient_policy) _widget->setTransient (p, transient_policy); } +Gtk::Window* +SPDesktop::getToplevel( ) +{ + return _widget->getWindow(); +} + void SPDesktop::presentWindow() { @@ -1028,6 +1191,37 @@ SPDesktop::shutdown() return _widget->shutdown(); } +bool SPDesktop::onDeleteUI (GdkEventAny*) +{ + if(shutdown()) + return true; + + destroyWidget(); + return false; +} + +/** + * onWindowStateEvent + * + * Called when the window changes its maximize/fullscreen/iconify/pinned state. + * Since GTK doesn't have a way to query this state information directly, we + * record it for the desktop here, and also possibly trigger a layout. + */ +bool +SPDesktop::onWindowStateEvent (GdkEventWindowState* event) +{ + // Record the desktop window's state + window_state = event->new_window_state; + + // Layout may differ depending on full-screen mode or not + GdkWindowState changed = event->changed_mask; + if (changed & (GDK_WINDOW_STATE_FULLSCREEN|GDK_WINDOW_STATE_MAXIMIZED)) { + layoutWidget(); + } + + return false; +} + void SPDesktop::setToolboxFocusTo (gchar const *label) { @@ -1040,6 +1234,12 @@ SPDesktop::setToolboxAdjustmentValue (gchar const* id, double val) _widget->setToolboxAdjustmentValue (id, val); } +void +SPDesktop::setToolboxSelectOneValue (gchar const* id, gint val) +{ + _widget->setToolboxSelectOneValue (id, val); +} + bool SPDesktop::isToolboxButtonActive (gchar const *id) { @@ -1070,6 +1270,64 @@ void SPDesktop::disableInteraction() _widget->disableInteraction(); } +void SPDesktop::setWaitingCursor() +{ + GdkCursor *waiting = gdk_cursor_new(GDK_WATCH); + gdk_window_set_cursor(GTK_WIDGET(sp_desktop_canvas(this))->window, waiting); + gdk_cursor_unref(waiting); + waiting_cursor = true; + + // Stupidly broken GDK cannot just set the new cursor right now - it needs some main loop iterations for that + // Since setting waiting_cursor is usually immediately followed by some Real Work, we must run the iterations here + // CAUTION: iterations may redraw, and redraw may be interrupted, so you cannot assume that anything is the same + // after the call to setWaitingCursor as it was before + while( Gtk::Main::events_pending() ) + Gtk::Main::iteration(); +} + +void SPDesktop::clearWaitingCursor() +{ + if (waiting_cursor) + sp_event_context_update_cursor(sp_desktop_event_context(this)); +} + +void SPDesktop::toggleColorProfAdjust() +{ + _widget->toggleColorProfAdjust(); +} + +void SPDesktop::toggleGrids() +{ + if (namedview->grids) { + if(gridgroup) { + showGrids(!grids_visible); + } + } else { + //there is no grid present at the moment. add a rectangular grid and make it visible + Inkscape::XML::Node *repr = SP_OBJECT_REPR(namedview); + Inkscape::CanvasGrid::writeNewGridToRepr(repr, sp_desktop_document(this), Inkscape::GRID_RECTANGULAR); + showGrids(true); + } +} + +void SPDesktop::showGrids(bool show, bool dirty_document) +{ + grids_visible = show; + sp_namedview_show_grids(namedview, grids_visible, dirty_document); + if (show) { + sp_canvas_item_show(SP_CANVAS_ITEM(gridgroup)); + } else { + sp_canvas_item_hide(SP_CANVAS_ITEM(gridgroup)); + } +} + +void SPDesktop::toggleSnapping() +{ + bool v = namedview->snap_manager.getSnapEnabledGlobally(); + Inkscape::XML::Node *repr = SP_OBJECT_REPR(namedview); + sp_repr_set_boolean(repr, "inkscape:snap-global", !v); +} + //---------------------------------------------------------------------- // Callback implementations. The virtual ones are connected by the view. @@ -1080,7 +1338,7 @@ SPDesktop::onPositionSet (double x, double y) } void -SPDesktop::onResized (double x, double y) +SPDesktop::onResized (double /*x*/, double /*y*/) { // Nothing called here } @@ -1105,7 +1363,6 @@ SPDesktop::updateCanvasNow() /** * Associate document with desktop. */ -/// \todo fixme: refactor SPDesktop::init to use setDocument void SPDesktop::setDocument (SPDocument *doc) { @@ -1132,10 +1389,11 @@ SPDesktop::setDocument (SPDocument *doc) _commit_connection = doc->connectCommit(sigc::mem_fun(*this, &SPDesktop::updateNow)); /// \todo fixme: This condition exists to make sure the code - /// inside is called only once on initialization. But there + /// inside is NOT called on initialization, only on replacement. But there /// are surely more safe methods to accomplish this. + // TODO since the comment had reversed logic, check the intent of this block of code: if (drawing) { - NRArenaItem *ai; + NRArenaItem *ai = 0; namedview = sp_document_namedview (doc, NULL); _modified_connection = namedview->connectModified(sigc::bind<2>(sigc::ptr_fun(&_namedview_modified), this)); @@ -1206,7 +1464,7 @@ SPDesktop::_onDeactivate (SPDesktop* dt) void SPDesktop::_onSelectionModified -(Inkscape::Selection *selection, guint flags, SPDesktop *dt) +(Inkscape::Selection */*selection*/, guint /*flags*/, SPDesktop *dt) { if (!dt->_widget) return; dt->_widget->updateScrollbars (expansion(dt->_d2w)); @@ -1236,7 +1494,7 @@ _onSelectionChanged * \todo fixme */ static gint -_arena_handler (SPCanvasArena *arena, NRArenaItem *ai, GdkEvent *event, SPDesktop *desktop) +_arena_handler (SPCanvasArena */*arena*/, NRArenaItem *ai, GdkEvent *event, SPDesktop *desktop) { if (ai) { SPItem *spi = (SPItem*)NR_ARENA_ITEM_GET_DATA (ai); @@ -1261,7 +1519,7 @@ _layer_deactivated(SPObject *layer, SPDesktop *desktop) { /// Callback static void -_layer_hierarchy_changed(SPObject *top, SPObject *bottom, +_layer_hierarchy_changed(SPObject */*top*/, SPObject *bottom, SPDesktop *desktop) { desktop->_layer_changed_signal.emit (bottom); @@ -1353,7 +1611,7 @@ _namedview_modified (SPObject *obj, guint flags, SPDesktop *desktop) ((CtrlRect *) desktop->page)->setShadow(0, 0x00000000); } } - + /* Show/hide page shadow */ if (nv->showpageshadow && nv->pageshadow) { ((CtrlRect *) desktop->page_border)->setShadow(nv->pageshadow, nv->bordercolor); @@ -1383,16 +1641,18 @@ _update_snap_distances (SPDesktop *desktop) SPNamedView &nv = *desktop->namedview; - nv.snap_manager.grid.setDistance(sp_convert_distance_full(nv.gridtolerance, + //tell all grid snappers + for ( GSList const *l = nv.grids; l != NULL; l = l->next) { + Inkscape::CanvasGrid *grid = (Inkscape::CanvasGrid*) l->data; + grid->snapper->setSnapperTolerance(sp_convert_distance_full(nv.gridtolerance, *nv.gridtoleranceunit, px)); - nv.snap_manager.axonomgrid.setDistance(sp_convert_distance_full(nv.gridtolerance, - *nv.gridtoleranceunit, - px)); - nv.snap_manager.guide.setDistance(sp_convert_distance_full(nv.guidetolerance, + } + + nv.snap_manager.guide.setSnapperTolerance(sp_convert_distance_full(nv.guidetolerance, *nv.guidetoleranceunit, px)); - nv.snap_manager.object.setDistance(sp_convert_distance_full(nv.objecttolerance, + nv.snap_manager.object.setSnapperTolerance(sp_convert_distance_full(nv.objecttolerance, *nv.objecttoleranceunit, px)); }