diff --git a/octoprint/server.py b/octoprint/server.py index 4db9ba5..6d552d9 100644 --- a/octoprint/server.py +++ b/octoprint/server.py @@ -442,7 +442,9 @@ def getSettings(): "snapshotUrl": s.get(["webcam", "snapshot"]), "ffmpegPath": s.get(["webcam", "ffmpeg"]), "bitrate": s.get(["webcam", "bitrate"]), - "watermark": s.getBoolean(["webcam", "watermark"]) + "watermark": s.getBoolean(["webcam", "watermark"]), + "flipH": s.getBoolean(["webcam", "flipH"]), + "flipV": s.getBoolean(["webcam", "flipV"]) }, "feature": { "gcodeViewer": s.getBoolean(["feature", "gCodeVisualizer"]), @@ -490,6 +492,8 @@ def setSettings(): if "ffmpegPath" in data["webcam"].keys(): s.set(["webcam", "ffmpeg"], data["webcam"]["ffmpegPath"]) if "bitrate" in data["webcam"].keys(): s.set(["webcam", "bitrate"], data["webcam"]["bitrate"]) if "watermark" in data["webcam"].keys(): s.setBoolean(["webcam", "watermark"], data["webcam"]["watermark"]) + if "flipH" in data["webcam"].keys(): s.setBoolean(["webcam", "flipH"], data["webcam"]["flipH"]) + if "flipV" in data["webcam"].keys(): s.setBoolean(["webcam", "flipV"], data["webcam"]["flipV"]) if "feature" in data.keys(): if "gcodeViewer" in data["feature"].keys(): s.setBoolean(["feature", "gCodeVisualizer"], data["feature"]["gcodeViewer"]) diff --git a/octoprint/settings.py b/octoprint/settings.py index f6fed77..4efd483 100644 --- a/octoprint/settings.py +++ b/octoprint/settings.py @@ -35,7 +35,9 @@ default_settings = { "snapshot": None, "ffmpeg": None, "bitrate": "5000k", - "watermark": True + "watermark": True, + "flipH": False, + "flipV": False }, "feature": { "gCodeVisualizer": True, diff --git a/octoprint/static/css/octoprint.less b/octoprint/static/css/octoprint.less index 41f4367..d2de9d8 100644 --- a/octoprint/static/css/octoprint.less +++ b/octoprint/static/css/octoprint.less @@ -358,6 +358,21 @@ ul.dropdown-menu li a { #webcam_container { width: 100%; + + .flipH { + -webkit-transform: scaleX(-1); + -moz-transform: scaleX(-1); + } + + .flipV { + -webkit-transform: scaleY(-1); + -moz-transform: scaleY(-1); + } + + .flipH.flipV { + -webkit-transform: scaleX(-1) scaleY(-1); + -moz-transform: scaleX(-1) scaleY(-1); + } } /** GCODE file manager */ @@ -577,4 +592,4 @@ ul.dropdown-menu li a { background: url("../img/icon-sd-black-14.png") 0 3px no-repeat; width: 11px; height: 17px; -} \ No newline at end of file +} diff --git a/octoprint/static/js/ui.js b/octoprint/static/js/ui.js index 9d2c27c..9d0c11b 100644 --- a/octoprint/static/js/ui.js +++ b/octoprint/static/js/ui.js @@ -509,10 +509,11 @@ function TemperatureViewModel(loginStateViewModel, settingsViewModel) { } } -function ControlViewModel(loginStateViewModel) { +function ControlViewModel(loginStateViewModel, settingsViewModel) { var self = this; self.loginState = loginStateViewModel; + self.settings = settingsViewModel; self.isErrorOrClosed = ko.observable(undefined); self.isOperational = ko.observable(undefined); @@ -1325,6 +1326,8 @@ function SettingsViewModel(loginStateViewModel, usersViewModel) { self.webcam_ffmpegPath = ko.observable(undefined); self.webcam_bitrate = ko.observable(undefined); self.webcam_watermark = ko.observable(undefined); + self.webcam_flipH = ko.observable(undefined); + self.webcam_flipV = ko.observable(undefined); self.feature_gcodeViewer = ko.observable(undefined); self.feature_waitForStart = ko.observable(undefined); @@ -1372,6 +1375,8 @@ function SettingsViewModel(loginStateViewModel, usersViewModel) { self.webcam_ffmpegPath(response.webcam.ffmpegPath); self.webcam_bitrate(response.webcam.bitrate); self.webcam_watermark(response.webcam.watermark); + self.webcam_flipH(response.webcam.flipH); + self.webcam_flipV(response.webcam.flipV); self.feature_gcodeViewer(response.feature.gcodeViewer); self.feature_waitForStart(response.feature.waitForStart); @@ -1406,14 +1411,15 @@ function SettingsViewModel(loginStateViewModel, usersViewModel) { "snapshotUrl": self.webcam_snapshotUrl(), "ffmpegPath": self.webcam_ffmpegPath(), "bitrate": self.webcam_bitrate(), - "watermark": self.webcam_watermark() + "watermark": self.webcam_watermark(), + "flipH": self.webcam_flipH(), + "flipV": self.webcam_flipV() }, "feature": { "gcodeViewer": self.feature_gcodeViewer(), "waitForStart": self.feature_waitForStart(), "alwaysSendChecksum": self.feature_alwaysSendChecksum(), "resetLineNumbersWithPrefixedN": self.feature_resetLineNumbersWithPrefixedN(), - "waitForStart": self.feature_waitForStart(), "sdSupport": self.feature_sdSupport() }, "folder": { @@ -1833,7 +1839,7 @@ $(function() { var settingsViewModel = new SettingsViewModel(loginStateViewModel, usersViewModel); var appearanceViewModel = new AppearanceViewModel(settingsViewModel); var temperatureViewModel = new TemperatureViewModel(loginStateViewModel, settingsViewModel); - var controlViewModel = new ControlViewModel(loginStateViewModel); + var controlViewModel = new ControlViewModel(loginStateViewModel, settingsViewModel); var terminalViewModel = new TerminalViewModel(loginStateViewModel); var gcodeFilesViewModel = new GcodeFilesViewModel(loginStateViewModel); var timelapseViewModel = new TimelapseViewModel(loginStateViewModel); diff --git a/octoprint/templates/index.jinja2 b/octoprint/templates/index.jinja2 index 5fa53f3..d1bcbb6 100644 --- a/octoprint/templates/index.jinja2 +++ b/octoprint/templates/index.jinja2 @@ -311,7 +311,7 @@