UI bug fixes and feature refinements (#59)

* Rework settings page; touch up contour, output, and 3D tabs; font sizing

No stream placeholder; driver mode refined; cameras page

Make settings snackbar work

Lint fix

Fix settings page padding

Actually hide settings fields if unsupported

* Make toggle buttons less confusing; fix driver toggle; form validation

* Make eyedropper work and make input/select styling more consistent

* Fix color picker and tabbing bugs

* Set up camera and settings pages to talk to the backend

* Add auto reconnect

* Add lots of tooltips and improve related thematic consistency

* Only show output stream while color picking

* Unbreak robot offset

* Increase tooltip delay and refactor tooltip label into a component

* Remove toggle button switching behavior

* Fix PnP tab and add a flag to disable FOV configuration

* Move FPS indicator

* Make GPU acceleration status use one value in the store

* Only allow IPv4 static IPs and remove accidentally committed index
This commit is contained in:
Declan Freeman-Gleason
2020-07-31 13:50:50 -07:00
committed by GitHub
parent 0b98dc3c9f
commit 19b57235fe
34 changed files with 1099 additions and 566 deletions

View File

@@ -1,8 +1,9 @@
<template>
<img
id="CameraStream"
:id="id"
crossOrigin="anonymous"
:style="styleObject"
:src="address"
:src="src"
alt=""
@click="e => $emit('click', e)"
>
@@ -11,20 +12,24 @@
<script>
export default {
name: "CvImage",
// eslint-disable-next-line vue/require-prop-types
props: ['address', 'scale', 'maxHeight', 'maxHeightMd', 'maxHeightXl'],
data: () => {
return {}
},
// eslint-disable-next-line vue/require-prop-types
props: ['address', 'scale', 'maxHeight', 'maxHeightMd', 'maxHeightXl', 'colorPicking', 'id', 'disconnected'],
computed: {
styleObject: {
get() {
let ret = {
"border-radius": "3px",
"display": "block",
"object-fit": "contain",
"object-position": "50% 50%",
"max-width": "100%",
"margin-left": "auto",
"margin-right": "auto",
"max-height": this.maxHeight,
width: `${this.scale}%`,
height: `${this.scale}%`,
cursor: (this.colorPicking ? `url(${require("../../assets/eyedropper.svg")}),` : "") + "default",
};
console.log(ret);
if (this.$vuetify.breakpoint.xl) {
ret["max-height"] = this.maxHeightXl;
@@ -34,8 +39,12 @@
return ret;
}
}
}
},
src: {
get() {
return this.disconnected ? require("../../assets/noStream.jpg") : this.address;
},
},
},
}
</script>

View File

@@ -4,16 +4,22 @@
dense
align="center"
>
<v-col cols="4">
<span class="ml-2">{{ name }}</span>
<v-col :cols="12 - (inputCols || 8)">
<tooltipped-label
:tooltip="tooltip"
:text="name"
/>
</v-col>
<v-col cols="8">
<v-col :cols="inputCols || 8">
<v-text-field
v-model="localValue"
dark
dense
color="accent"
:disabled="disabled"
:error-messages="errorMessage"
:rules="rules"
class="mt-1 pt-2"
@keydown="handleKeyboard"
/>
</v-col>
@@ -22,10 +28,15 @@
</template>
s
<script>
import TooltippedLabel from "./cv-tooltipped-label";
export default {
name: 'Input',
// eslint-disable-next-line vue/require-prop-types
props: ['name', 'value', 'disabled', 'errorMessage'],
components: {
TooltippedLabel
},
// eslint-disable-next-line vue/require-prop-types
props: ['name', 'value', 'disabled', 'errorMessage', 'inputCols', 'rules', 'tooltip'],
data() {
return {}
},
@@ -49,6 +60,5 @@ s
}
</script>
<style lang="" scoped>
<style lang="css" scoped>
</style>

View File

@@ -4,8 +4,11 @@
dense
align="center"
>
<v-col :cols="2">
<span>{{ name }}</span>
<v-col :cols="labelCols || 2">
<tooltipped-label
:tooltip="tooltip"
:text="name"
/>
</v-col>
<v-col>
<v-text-field
@@ -14,9 +17,11 @@
class="mt-0 pt-0"
hide-details
single-line
color="accent"
type="number"
style="width: 70px"
:step="step"
:rules="rules"
/>
</v-col>
</v-row>
@@ -24,13 +29,15 @@
</template>
<script>
import TooltippedLabel from "./cv-tooltipped-label";
export default {
name: 'NumberInput',
// eslint-disable-next-line vue/require-prop-types
props: ['name', 'value', 'step'],
data() {
return {}
components: {
TooltippedLabel,
},
// eslint-disable-next-line vue/require-prop-types
props: ['name', 'value', 'step', 'labelCols', 'rules', 'tooltip'],
computed: {
localValue: {
get() {

View File

@@ -1,10 +1,16 @@
<template>
<div>
<v-row dense align="center">
<v-col :cols="2">
<span>{{ name }}</span>
<v-row
dense
align="center"
>
<v-col cols="2">
<tooltipped-label
:tooltip="tooltip"
:text="name"
/>
</v-col>
<v-col :cols="10">
<v-col cols="10">
<v-range-slider
:value="localValue"
:max="max"
@@ -12,7 +18,7 @@
hide-details
class="align-center"
dark
color="#ffd843"
color="accent"
:step="step"
@input="handleInput"
@mousedown="$emit('rollback', localValue)"
@@ -20,6 +26,7 @@
<template v-slot:prepend>
<v-text-field
dark
color="accent"
:value="localValue[0]"
:max="max"
:min="min"
@@ -38,6 +45,7 @@
<template v-slot:append>
<v-text-field
dark
color="accent"
:value="localValue[1]"
:max="max"
:min="min"
@@ -59,10 +67,15 @@
</template>
<script>
import TooltippedLabel from "./cv-tooltipped-label";
export default {
name: "RangeSlider",
components: {
TooltippedLabel,
},
// eslint-disable-next-line vue/require-prop-types
props: ["name", "min", "max", "value", "step"],
props: ["name", "min", "max", "value", "step", "tooltip"],
data() {
return {
prependFocused: false,

View File

@@ -5,7 +5,10 @@
align="center"
>
<v-col :cols="12 - (selectCols || 9)">
<span>{{ name }}</span>
<tooltipped-label
:tooltip="tooltip"
:text="name"
/>
</v-col>
<v-col :cols="selectCols || 9">
<v-select
@@ -17,6 +20,7 @@
color="accent"
item-color="secondary"
:disabled="disabled"
:rules="rules"
@change="$emit('rollback', localValue)"
/>
</v-col>
@@ -25,13 +29,15 @@
</template>
<script>
import TooltippedLabel from "./cv-tooltipped-label";
export default {
name: 'Select',
// eslint-disable-next-line vue/require-prop-types
props: ['list', 'name', 'value', 'disabled', 'selectCols'],
data() {
return {}
components: {
TooltippedLabel,
},
// eslint-disable-next-line vue/require-prop-types
props: ['list', 'name', 'value', 'disabled', 'selectCols', 'rules', 'tooltip'],
computed: {
localValue: {
get() {

View File

@@ -5,7 +5,10 @@
align="center"
>
<v-col :cols="12 - (sliderCols || 8)">
<span>{{ name }}</span>
<tooltipped-label
:tooltip="tooltip"
:text="name"
/>
</v-col>
<v-col :cols="sliderCols || 8">
<v-slider
@@ -27,6 +30,7 @@
<template v-slot:append>
<v-text-field
dark
color="accent"
:max="max"
:min="min"
:disabled="disabled"
@@ -49,10 +53,15 @@
</template>
<script>
import TooltippedLabel from "./cv-tooltipped-label";
export default {
name: "Slider",
components: {
TooltippedLabel,
},
// eslint-disable-next-line vue/require-prop-types
props: ["min", "max", "name", "value", "step", "sliderCols", "disabled"],
props: ["min", "max", "name", "value", "step", "sliderCols", "disabled", "tooltip"],
data() {
return {
isFocused: false,

View File

@@ -4,10 +4,13 @@
dense
align="center"
>
<v-col :cols="2">
<span>{{ name }}</span>
<v-col :cols="textCols || 2">
<tooltipped-label
:tooltip="tooltip"
:text="name"
/>
</v-col>
<v-col>
<v-col :cols="12 - (textCols || 2)">
<v-switch
v-model="localValue"
dark
@@ -21,24 +24,26 @@
</template>
<script>
export default {
name: 'CVSwitch',
// eslint-disable-next-line vue/require-prop-types
props: ['name', 'value', 'disabled'],
data() {
return {}
},
computed: {
localValue: {
get() {
return this.value;
},
set(value) {
this.$emit('input', value)
}
import TooltippedLabel from "./cv-tooltipped-label";
export default {
name: 'CVSwitch',
components: {
TooltippedLabel,
},
// eslint-disable-next-line vue/require-prop-types
props: ['name', 'value', 'disabled', 'textCols', 'tooltip'],
computed: {
localValue: {
get() {
return this.value;
},
set(value) {
this.$emit('input', value)
}
}
}
}
</script>
<style lang="" scoped>

View File

@@ -0,0 +1,26 @@
<template>
<div>
<v-tooltip
:disabled="tooltip === undefined"
right
open-delay="600"
>
<template v-slot:activator="{ on, attrs }">
<span
style="cursor: text !important;"
v-bind="attrs"
v-on="on"
>{{ text }}</span>
</template>
<span>{{ tooltip }}</span>
</v-tooltip>
</div>
</template>
<script>
export default {
name: 'TooltippedLabel',
// eslint-disable-next-line vue/require-prop-types
props: ['text', 'tooltip'],
}
</script>

View File

@@ -24,9 +24,9 @@
name: "MiniMap",
props: {
// eslint-disable-next-line vue/require-default-prop
targets: Array,
targets: Array,
// eslint-disable-next-line vue/require-default-prop
horizontalFOV: Number
horizontalFOV: Number
},
data() {
return {
@@ -75,7 +75,6 @@
this.$nextTick(function () {
this.drawPlayer();
});
},
methods: {
@@ -88,8 +87,8 @@
},
drawTarget(index, target) {
// first save the untranslated/unrotated context
let x = 800 - (160 * target.translation.x); // getting meters as pixels
let y = 400 - (160 * target.translation.y);
let x = 800 - (160 * target.x); // getting meters as pixels
let y = 400 - (160 * target.y);
this.ctx.save();
this.ctx.beginPath();
// move the rotation point to the center of the rect

View File

@@ -18,6 +18,7 @@
v-else
v-model="newCameraName"
name="Camera"
input-cols="9"
:error-message="checkCameraName"
@Enter="saveCameraNameChange"
/>
@@ -63,8 +64,10 @@
<CVselect
v-model="currentPipelineIndex"
name="Pipeline"
:list="['Driver Mode'].concat($store.getters.pipelineList)"
@input="handleInputWithIndex('currentPipeline',currentPipelineIndex - 1)"
tooltip="Each pipeline runs on a camera output and stores a unique set of processing settings"
:disabled="$store.getters.isDriverMode"
:list="($store.getters.isDriverMode ? ['Driver Mode'] : []).concat($store.getters.pipelineList)"
@input="handleInputWithIndex('currentPipeline', currentPipelineIndex)"
/>
</v-col>
<v-col
@@ -128,15 +131,6 @@
</v-list>
</v-menu>
</v-col>
<!-- <v-btn-->
<!-- outlined-->
<!-- color="accent"-->
<!-- @click="handleInput('command','save')"-->
<!-- >-->
<!-- <v-icon>save</v-icon>-->
<!-- Save-->
<!-- </v-btn>-->
</v-row>
<!--pipeline duplicate dialog-->
<v-dialog
@@ -305,10 +299,10 @@
},
currentPipelineIndex: {
get() {
return this.$store.getters.currentPipelineIndex + 1;
return this.$store.getters.currentPipelineIndex + this.$store.getters.isDriverMode ? 1 : 0;
},
set(value) {
this.$store.commit('currentPipelineIndex', value - 1);
this.$store.commit('currentPipelineIndex', value - this.$store.getters.isDriverMode ? 1 : 0);
}
}
},

View File

@@ -4,34 +4,33 @@
align="center"
justify="start"
>
<v-col
style="padding-right:0"
:cols="3"
>
<v-col cols="4">
<v-btn
small
color="#ffd843"
color="accent"
style="width: 100%;"
class="black--text"
@click="takePointA"
>
Take Point A
</v-btn>
</v-col>
<v-col
style="margin-left:0"
:cols="3"
>
<v-col cols="4">
<v-btn
small
color="#ffd843"
color="accent"
style="width: 100%;"
class="black--text"
@click="takePointB"
>
Take Point B
</v-btn>
</v-col>
<v-col>
<v-col cols="4">
<v-btn
small
color="yellow darken-3"
style="width: 100%;"
@click="clearSlope"
>
Clear All Points

View File

@@ -4,22 +4,22 @@
align="center"
justify="start"
>
<v-col
style="padding-right:0"
:cols="3"
>
<v-col cols="6">
<v-btn
small
color="#ffd843"
color="accent"
class="black--text"
style="width: 100%;"
@click="takePoint"
>
Take Point
</v-btn>
</v-col>
<v-col>
<v-col cols="6">
<v-btn
small
color="yellow darken-3"
style="width: 100%;"
@click="clearPoint"
>
Clear Point