From c552e9e9bea7f3c7bf3024e496d5e8de20fbb8a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gina=20H=C3=A4u=C3=9Fge?= Date: Fri, 8 Aug 2014 16:22:48 +0200 Subject: [PATCH] Fixed a couple of issue with the gcode viewer Most notably the interfering options tracked in #398, but also made "Center viewport on model" and "Zoom in on model" automatically deselect and de-apply if viewport gets manipulated by user, therefore properly allowing the re-select by the user to work to. Closes #398 (cherry picked from commit f195af0) --- .../static/gcodeviewer/js/renderer.js | 117 ++++++++++++++---- .../static/js/app/viewmodels/gcode.js | 20 ++- 2 files changed, 112 insertions(+), 25 deletions(-) diff --git a/src/octoprint/static/gcodeviewer/js/renderer.js b/src/octoprint/static/gcodeviewer/js/renderer.js index c0f28688..3c7d2ee7 100644 --- a/src/octoprint/static/gcodeviewer/js/renderer.js +++ b/src/octoprint/static/gcodeviewer/js/renderer.js @@ -46,7 +46,9 @@ GCODE.renderer = (function(){ centerViewport: false, bed: {x: 200, y: 200}, - container: undefined + container: undefined, + + onInternalOptionChange: undefined }; var offsetModelX = 0, offsetModelY = 0; @@ -140,45 +142,107 @@ GCODE.renderer = (function(){ ctx.lineCap = 'round'; trackTransforms(ctx); - canvas.addEventListener('mousedown',function(evt){ + // dragging => translating + canvas.addEventListener('mousedown', function(event){ document.body.style.mozUserSelect = document.body.style.webkitUserSelect = document.body.style.userSelect = 'none'; - lastX = evt.offsetX || (evt.pageX - canvas.offsetLeft); - lastY = evt.offsetY || (evt.pageY - canvas.offsetTop); - dragStart = ctx.transformedPoint(lastX,lastY); + + // remember starting point of dragging gesture + lastX = event.offsetX || (event.pageX - canvas.offsetLeft); + lastY = event.offsetY || (event.pageY - canvas.offsetTop); + dragStart = ctx.transformedPoint(lastX, lastY); + + // not yet dragged anything dragged = false; - },false); - canvas.addEventListener('mousemove',function(evt){ - lastX = evt.offsetX || (evt.pageX - canvas.offsetLeft); - lastY = evt.offsetY || (evt.pageY - canvas.offsetTop); + }, false); + + canvas.addEventListener('mousemove', function(event){ + // save current mouse coordinates + lastX = event.offsetX || (event.pageX - canvas.offsetLeft); + lastY = event.offsetY || (event.pageY - canvas.offsetTop); + + // mouse movement => dragged dragged = true; - if (dragStart){ + + if (dragStart !== undefined){ + // translate var pt = ctx.transformedPoint(lastX,lastY); - ctx.translate(pt.x-dragStart.x,pt.y-dragStart.y); + ctx.translate(pt.x - dragStart.x, pt.y - dragStart.y); reRender(); + + renderOptions["centerViewport"] = false; + renderOptions["zoomInOnModel"] = false; + renderOptions["zoomInOnBed"] = false; + offsetModelX = 0; + offsetModelY = 0; + offsetBedX = 0; + offsetBedY = 0; + scaleX = 1; + scaleY = 1; + + if (renderOptions["onInternalOptionChange"] !== undefined) { + renderOptions["onInternalOptionChange"]({ + centerViewport: false, + moveModel: false, + zoomInOnModel: false, + zoomInOnBed: false + }); + } } - },false); - canvas.addEventListener('mouseup',function(evt){ - dragStart = null; - if (!dragged) zoom(evt.shiftKey ? -1 : 1 ); - },false); + }, false); + + canvas.addEventListener('mouseup', function(event){ + // reset dragStart + dragStart = undefined; + }, false); + + // mouse wheel => zooming var zoom = function(clicks){ - var pt = ctx.transformedPoint(lastX,lastY); + // focus on last mouse position prior to zoom + var pt = ctx.transformedPoint(lastX, lastY); ctx.translate(pt.x,pt.y); + + // determine zooming factor and perform zoom var factor = Math.pow(scaleFactor,clicks); ctx.scale(factor,factor); + + // return to old position ctx.translate(-pt.x,-pt.y); + + // render reRender(); + + // disable conflicting options + renderOptions["zoomInOnModel"] = false; + renderOptions["zoomInOnBed"] = false; + offsetModelX = 0; + offsetModelY = 0; + offsetBedX = 0; + offsetBedY = 0; + scaleX = 1; + scaleY = 1; + + if (renderOptions["onInternalOptionChange"] !== undefined) { + renderOptions["onInternalOptionChange"]({ + zoomInOnModel: false, + zoomInOnBed: false + }); + } }; - var handleScroll = function(evt){ + var handleScroll = function(event){ var delta; - if(evt.detail<0 || evt.wheelDelta>0)delta=zoomFactorDelta; - else delta=-1*zoomFactorDelta; + + // determine zoom direction & delta + if (event.detail < 0 || event.wheelDelta > 0) { + delta = zoomFactorDelta; + } else { + delta = -1 * zoomFactorDelta; + } if (delta) zoom(delta); - return evt.preventDefault() && false; + + return event.preventDefault() && false; }; canvas.addEventListener('DOMMouseScroll',handleScroll,false); canvas.addEventListener('mousewheel',handleScroll,false); - }; var drawGrid = function() { @@ -368,8 +432,13 @@ GCODE.renderer = (function(){ }; var applyZoom = function(mdlInfo) { + // get middle of canvas var pt = ctx.transformedPoint(canvas.width/2,canvas.height/2); + + // get current transform var transform = ctx.getTransform(); + + // move to middle of canvas, reset scale, move back if (scaleX && scaleY && transform.a && transform.d) { ctx.translate(pt.x, pt.y); ctx.scale(1 / scaleX, 1 / scaleY); @@ -378,6 +447,7 @@ GCODE.renderer = (function(){ } if (mdlInfo && renderOptions["zoomInOnModel"]) { + // if we need to zoom in on model, scale factor is calculated by longer side of object in relation to that axis of canvas var scaleF = mdlInfo.modelSize.x > mdlInfo.modelSize.y ? (canvas.width - 10) / mdlInfo.modelSize.x : (canvas.height - 10) / mdlInfo.modelSize.y; scaleF /= zoomFactor; if (transform.a && transform.d) { @@ -388,6 +458,7 @@ GCODE.renderer = (function(){ ctx.translate(-pt.x, -pt.y); } } else { + // reset scale to 1 scaleX = 1; scaleY = 1; } @@ -416,7 +487,7 @@ GCODE.renderer = (function(){ dirty = true; renderOptions[opt] = options[opt]; - if ($.inArray(opt, ["moveModel", "centerViewport", "zoomInOnModel", "bed"])) { + if ($.inArray(opt, ["moveModel", "centerViewport", "zoomInOnModel", "bed"]) > -1) { mustRefresh = true; } } diff --git a/src/octoprint/static/js/app/viewmodels/gcode.js b/src/octoprint/static/js/app/viewmodels/gcode.js index efba29c0..5b5f9b33 100644 --- a/src/octoprint/static/js/app/viewmodels/gcode.js +++ b/src/octoprint/static/js/app/viewmodels/gcode.js @@ -60,7 +60,8 @@ function GcodeViewModel(loginStateViewModel, settingsViewModel) { extrusionWidth: self.renderer_extrusionWidthEnabled() ? self.renderer_extrusionWidth() : 1, showNextLayer: self.renderer_showNext(), showPreviousLayer: self.renderer_showPrevious(), - zoomInOnModel: self.renderer_zoomOnModel() + zoomInOnModel: self.renderer_zoomOnModel(), + onInternalOptionChange: self._onInternalRendererOptionChange }; if (additionalRendererOptions) { _.extend(renderer, additionalRendererOptions); @@ -155,7 +156,7 @@ function GcodeViewModel(loginStateViewModel, settingsViewModel) { self.clear = function() { GCODE.ui.clear(); - } + }; self._configureLayerSlider = function() { self.layerSlider = $("#gcode_slider_layers").slider({ @@ -353,6 +354,20 @@ function GcodeViewModel(loginStateViewModel, settingsViewModel) { } }; + self._onInternalRendererOptionChange = function(options) { + if (!options) return; + + for (var opt in options) { + if (opt == "zoomInOnModel" && options[opt] != self.renderer_zoomOnModel()) { + self.renderer_zoomOnModel(false); + } else if (opt == "centerViewport" && options[opt] != self.renderer_centerViewport()) { + self.renderer_centerViewport(false); + } else if (opt == "moveModel" && options[opt] != self.renderer_centerModel()) { + self.renderer_centerModel(false); + } + } + }; + self.changeLayer = function(event) { if (self.currentlyPrinting && self.renderer_syncProgress()) self.renderer_syncProgress(false); @@ -372,4 +387,5 @@ function GcodeViewModel(loginStateViewModel, settingsViewModel) { GCODE.ui.changeSelectedCommands(self.layerSlider.slider("getValue"), tuple[0], tuple[1]); }; + }