Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(Webcam): add a optional overlay for IDEX calibration #2053

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 100 additions & 0 deletions src/components/settings/Webcams/WebcamForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,58 @@
:label="$t('Settings.WebcamsTab.Vertically')" />
</v-col>
</v-row>
<template v-if="nozzleCrosshairAvialable">
<v-row>
<v-col class="pt-3 pb-3">
<div class="v-label v-label--active theme--dark text-subtitle-1">
{{ $t('Settings.WebcamsTab.NozzleCrosshair') }}:
</div>
</v-col>
</v-row>
<v-row class="mt-0">
<v-col class="py-0">
<v-checkbox
v-model="nozzleCrosshair"
class="mt-1"
hide-details
:label="$t('Settings.WebcamsTab.Enable')" />
</v-col>
<v-col v-if="nozzleCrosshair" class="py-0">
<v-menu bottom left offset-y :close-on-content-click="false">
<template #activator="{ on, attrs }">
<v-btn
v-bind="attrs"
:color="nozzleCrosshairColor"
class="minwidth-0 px-5"
small
v-on="on" />
</template>
<v-color-picker
:value="nozzleCrosshairColor"
hide-mode-switch
mode="rgba"
@update:color="updateLogoColor" />
</v-menu>
<div
class="v-label v-label--active theme--dark text-subtitle-1 d-inline-block ml-2 mt-2">
{{ $t('Settings.WebcamsTab.Color') }}
</div>
</v-col>
</v-row>
<v-row v-if="nozzleCrosshair">
<v-col>
<v-slider
v-model="nozzleCrosshairSize"
:max="1"
:min="0.01"
:step="0.01"
thumb-label
thumb-size="24"
hide-details
:label="$t('Settings.WebcamsTab.Size')" />
</v-col>
</v-row>
</template>
</v-col>
<v-col class="col-12 col-sm-6 text-center" align-self="center">
<webcam-wrapper :webcam="webcam" page="settings" />
Expand Down Expand Up @@ -311,6 +363,54 @@ export default class WebcamForm extends Mixins(BaseMixin, WebcamMixin) {
this.webcam.extra_data.enableAudio = newVal
}

get nozzleCrosshairAvialable() {
return ['mjpegstreamer', 'mjpegstreamer-adaptive', 'webrtc-camerastreamer'].includes(this.webcam.service)
}

get nozzleCrosshair() {
window.console.log(this.webcam.extra_data)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove debug output


return this.webcam.extra_data?.nozzleCrosshair ?? false
}

set nozzleCrosshair(newVal) {
const extraData = { ...(this.webcam.extra_data ?? {}) }
extraData.nozzleCrosshair = newVal

this.webcam.extra_data = extraData
}

get nozzleCrosshairColor() {
return this.webcam.extra_data?.nozzleCrosshairColor ?? '#ff0000'
}

set nozzleCrosshairColor(newVal: string) {
const extraData = { ...(this.webcam.extra_data ?? {}) }
extraData.nozzleCrosshairColor = newVal

this.webcam.extra_data = extraData
}

updateLogoColor(color: string | { hex: string }) {
if (typeof color === 'object') {
this.nozzleCrosshairColor = color.hex
return
}

this.nozzleCrosshairColor = color
}

get nozzleCrosshairSize() {
return this.webcam.extra_data?.nozzleCrosshairSize ?? 0.1
}

set nozzleCrosshairSize(newVal: number) {
const extraData = { ...(this.webcam.extra_data ?? {}) }
extraData.nozzleCrosshairSize = newVal

this.webcam.extra_data = extraData
}

mounted() {
this.oldWebcamName = this.webcam.name
}
Expand Down
94 changes: 94 additions & 0 deletions src/components/webcams/WebcamNozzleCrosshair.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
<template>
<div ref="container" class="crosshair-container">
<div class="line horizontal" :style="styleLines" />
<div class="line vertical" :style="styleLines" />
<div class="circle" :style="styleCircle" />
<resize-observer @notify="handleResize" />
</div>
</template>

<script lang="ts">
import Component from 'vue-class-component'
import { Mixins, Prop, Ref } from 'vue-property-decorator'
import BaseMixin from '@/components/mixins/base'
import { GuiWebcamStateWebcam } from '@/store/gui/webcams/types'

@Component
export default class WebcamWrapper extends Mixins(BaseMixin) {
@Prop({ type: Object, required: true }) webcam!: GuiWebcamStateWebcam
@Ref() container!: HTMLDivElement

clientHeight = 0

get color() {
return this.webcam.extra_data?.nozzleCrosshairColor ?? '#ff0000'
}

get styleLines() {
return {
backgroundColor: this.color,
}
}

get styleCircle() {
const nozzleCrosshairSize = this.webcam.extra_data?.nozzleCrosshairSize ?? 0.1
const size = this.clientHeight * nozzleCrosshairSize

return {
borderColor: this.color,
width: `${size}px`,
height: `${size}px`,
marginLeft: `-${size / 2}px`,
marginTop: `-${size / 2}px`,
}
}

mounted() {
this.handleResize()
}

handleResize() {
this.$nextTick(() => {
this.clientHeight = this.container.clientHeight
})
}
}
</script>

<style scoped>
.crosshair-container {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
}

.line {
position: absolute;
background-color: #ff0000;
}

.horizontal {
height: 1px;
top: 50%;
left: 0;
right: 0;
}

.vertical {
left: 50%;
top: 0;
bottom: 0;
width: 1px;
}

.circle {
position: absolute;
border: 1px solid #ff0000;
border-radius: 50%;
box-sizing: border-box;
top: 50%;
left: 50%;
}
</style>
7 changes: 7 additions & 0 deletions src/components/webcams/streamers/Mjpegstreamer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
<span v-if="showFpsCounter && status === 'connected'" class="webcamFpsOutput">
{{ $t('Panels.WebcamPanel.FPS') }}: {{ fpsOutput }}
</span>
<webcam-nozzle-crosshair v-if="showNozzleCrosshair" :webcam="camSettings" />
<v-row v-if="status !== 'connected'">
<v-col class="_webcam_mjpegstreamer_output text-center d-flex flex-column justify-center align-center">
<v-progress-circular v-if="status === 'connecting'" indeterminate color="primary" class="mb-3" />
Expand Down Expand Up @@ -99,6 +100,12 @@ export default class Mjpegstreamer extends Mixins(BaseMixin, WebcamMixin) {
return this.$store.getters['gui/getPanelExpand']('webcam-panel', this.viewport) ?? false
}

get showNozzleCrosshair() {
const nozzleCrosshair = this.camSettings.extra_data?.nozzleCrosshair ?? false

return nozzleCrosshair && this.status === 'connected'
}

// start or stop the video when the expanded state changes
@Watch('expanded', { immediate: true })
expandChanged(newExpanded: boolean): void {
Expand Down
7 changes: 7 additions & 0 deletions src/components/webcams/streamers/MjpegstreamerAdaptive.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
<span v-if="status === 'connected' && showFpsCounter" class="webcamFpsOutput">
{{ $t('Panels.WebcamPanel.FPS') }}: {{ fpsOutput }}
</span>
<webcam-nozzle-crosshair v-if="showNozzleCrosshair" :webcam="camSettings" />
<v-row v-if="status !== 'connected'">
<v-col class="_webcam_mjpegstreamer_output text-center d-flex flex-column justify-center align-center">
<v-progress-circular v-if="status === 'connecting'" indeterminate color="primary" class="mb-3" />
Expand Down Expand Up @@ -100,6 +101,12 @@ export default class MjpegstreamerAdaptive extends Mixins(BaseMixin, WebcamMixin
return this.isVisibleDocument && this.isVisibleViewport
}

get showNozzleCrosshair() {
const nozzleCrosshair = this.camSettings.extra_data?.nozzleCrosshair ?? false

return nozzleCrosshair && this.status === 'connected'
}

mounted() {
document.addEventListener('visibilitychange', this.documentVisibilityChanged)
}
Expand Down
14 changes: 12 additions & 2 deletions src/components/webcams/streamers/WebrtcCameraStreamer.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<template>
<div>
<div class="position-relative d-flex">
<video
v-show="status === 'connected'"
ref="stream"
Expand All @@ -8,6 +8,7 @@
autoplay
muted
playsinline />
<webcam-nozzle-crosshair v-if="nozzleCrosshair" :webcam="camSettings" />
<v-row v-if="status !== 'connected'">
<v-col class="_webcam_webrtc_output text-center d-flex flex-column justify-center align-center">
<v-progress-circular v-if="status === 'connecting'" indeterminate color="primary" class="mb-3" />
Expand All @@ -23,14 +24,15 @@ import BaseMixin from '@/components/mixins/base'
import { GuiWebcamStateWebcam } from '@/store/gui/webcams/types'
import WebcamMixin from '@/components/mixins/webcam'
import { capitalize } from '@/plugins/helpers'
import WebcamNozzleCrosshair from '@/components/webcams/WebcamNozzleCrosshair.vue'

interface CameraStreamerResponse extends RTCSessionDescriptionInit {
id: string
iceServers?: RTCIceServer[]
}

@Component({
methods: { capitalize },
components: { WebcamNozzleCrosshair },
})
export default class WebrtcCameraStreamer extends Mixins(BaseMixin, WebcamMixin) {
capitalize = capitalize
Expand Down Expand Up @@ -65,6 +67,10 @@ export default class WebrtcCameraStreamer extends Mixins(BaseMixin, WebcamMixin)
return output
}

get nozzleCrosshair() {
return this.camSettings.extra_data?.nozzleCrosshair ?? false
}

get expanded(): boolean {
if (this.page !== 'dashboard') return true

Expand Down Expand Up @@ -243,6 +249,10 @@ export default class WebrtcCameraStreamer extends Mixins(BaseMixin, WebcamMixin)
</script>

<style scoped>
.position-relative {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there is an position relative p-rel css class in in the general page.css. so this would be a duplicate

position: relative;
}

.webcamStream {
width: 100%;
}
Expand Down
4 changes: 4 additions & 0 deletions src/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -1278,9 +1278,11 @@
"Update": "update",
"WebcamsTab": {
"AddWebcam": "add webcam",
"Color": "Color",
"CreateWebcam": "Create Webcam",
"EditCrowsnestConf": "Edit crowsnest.conf",
"EditWebcam": "Edit Webcam",
"Enable": "Enable",
"EnableAudio": "Enable audio",
"FlipWebcam": "Flip webcam image:",
"HideFps": "Hide FPS counter",
Expand All @@ -1300,10 +1302,12 @@
"MjpegstreamerAdaptive": "Adaptive MJPEG-Streamer (experimental)",
"Name": "Name",
"NameAlreadyExists": "Name already exists",
"NozzleCrosshair": "Nozzle Crosshair",
"Required": "required",
"Rotate": "Rotate",
"SaveWebcam": "Save Webcam",
"Service": "Service",
"Size": "Size",
"TargetFPS": "Target FPS",
"UpdateWebcam": "Update Webcam",
"UrlSnapshot": "URL Snapshot",
Expand Down
3 changes: 3 additions & 0 deletions src/store/gui/webcams/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ export interface GuiWebcamStateWebcam {
extra_data?: {
enableAudio?: boolean
hideFps?: boolean
nozzleCrosshair?: boolean
nozzleCrosshairColor?: string
nozzleCrosshairSize?: number
}
source?: 'config' | 'database'
}
Loading