Add colored shape to the UI (#258)

* Fixup colored shape backend code

* More colored shape stuff

* Start adding shape change to drawing

* Mostly works!

* Add powercell image for shape test mode

* Make super-duper-sure to release stuff

Fixes colored shape leak

* Move approx poly dp into Contour

* Adjust epsilon threshold

* Add dialog to change pipeline type

* Run spotless

* Make yes red :>

* Move "no" button

* Fix duplication/deletion name logic and switching

* Fix compilation errors from rebase

* Update VisionSourceManager.java

* Update type dialog, remove duplicate popup

The dropdown still switches even if the user says "no" tho

Co-authored-by: Banks Troutman <btrout.dhrs@gmail.com>
This commit is contained in:
Matt
2021-09-03 19:20:55 -07:00
committed by GitHub
parent 798b8e398a
commit 00b8e7d1c5
38 changed files with 1252 additions and 785 deletions

View File

@@ -15,6 +15,7 @@
:value="localValue"
:max="max"
:min="min"
:disabled="disabled"
hide-details
class="align-center"
dark
@@ -34,7 +35,7 @@
hide-details
single-line
type="number"
style="width: 50px"
style="width: 60px"
:step="step"
@input="handleChange"
@focus="prependFocused = true"
@@ -53,7 +54,7 @@
hide-details
single-line
type="number"
style="width: 50px"
style="width: 60px"
:step="step"
@input="handleChange"
@focus="appendFocused = true"
@@ -75,7 +76,7 @@ export default {
TooltippedLabel,
},
// eslint-disable-next-line vue/require-prop-types
props: ["name", "min", "max", "value", "step", "tooltip"],
props: ["name", "min", "max", "value", "step", "tooltip", "disabled"],
data() {
return {
prependFocused: false,

View File

@@ -88,7 +88,11 @@
menu
</v-icon>
</template>
<v-list dense>
<v-list
dark
dense
color="primary"
>
<v-list-item @click="toPipelineNameChange">
<v-list-item-title>
<CVicon
@@ -119,7 +123,7 @@
/>
</v-list-item-title>
</v-list-item>
<v-list-item @click="openDuplicateDialog">
<v-list-item @click="duplicatePipeline">
<v-list-item-title>
<CVicon
color="#c5c5c5"
@@ -132,66 +136,51 @@
</v-list>
</v-menu>
</v-col>
<v-col
v-if="currentPipelineType >= 0"
cols="10"
md="5"
lg="10"
class="pt-0 pb-0 pl-6 ml-16"
>
<CVselect
v-model="currentPipelineType"
name="Type"
:list="['Reflective', 'Shape']"
@input="e => showTypeDialog(e)"
/>
</v-col>
</v-row>
<!--pipeline duplicate dialog-->
<v-dialog
v-model="duplicateDialog"
dark
width="500"
height="357"
>
<v-card dark>
<v-card-title
class="headline"
primary-title
>
Duplicate Pipeline
</v-card-title>
<v-card-text>
<CVselect
v-model="pipeIndexToDuplicate"
name="Pipeline"
:list="$store.getters.pipelineList"
/>
</v-card-text>
<v-divider />
<v-card-actions>
<v-spacer />
<v-btn
color="#ffd843"
@click="duplicatePipeline"
>
Duplicate
</v-btn>
<v-btn
color="error"
@click="closeDuplicateDialog"
>
Cancel
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
<!--pipeline naming dialog-->
<v-dialog
v-model="namingDialog"
dark
persistent
width="500"
height="357"
>
<v-card dark>
<v-card
dark
color="primary"
>
<v-card-title
class="headline"
primary-title
>
Pipeline Name
{{ isPipelineNameEdit ? "Edit Pipeline Name" : "Create Pipeline" }}
</v-card-title>
<v-card-text>
<CVinput
v-model="newPipelineName"
name="Pipeline"
:error-message="checkPipelineName"
@Enter="savePipelineNameChange"
/>
<CVselect
v-model="newPipelineType"
name="Pipeline Type"
:list="['Reflective', 'Shape']"
:disabled="isPipelineNameEdit"
/>
</v-card-text>
<v-divider />
@@ -213,161 +202,205 @@
</v-card-actions>
</v-card>
</v-dialog>
<v-dialog
v-model="showPipeTypeDialog"
width="600"
>
<v-card
color="primary"
dark
>
<v-card-title>Change Pipeline Type</v-card-title>
<v-card-text>
Changing the type of this pipeline will erase the current pipeline's settings and replace it with a new {{ ['Reflective', 'Shape'][proposedPipelineType] }} pipeline. <b class="red--text format_bold">You will lose all settings for the pipeline
"{{ ($store.getters.isDriverMode ? ['Driver Mode'] : []).concat($store.getters.pipelineList)[currentPipelineIndex] }}."</b> Are you sure you want to do this?
<v-row
class="mt-6"
style="display: flex; align-items: center; justify-content: center"
align="center"
>
<v-btn
class="mr-3"
color="red"
width="250"
@click="e => changePipeType(true)"
>
Yes, replace this pipeline
</v-btn>
<v-btn
class="ml-10"
color="secondary"
width="250"
@click="e => changePipeType(false)"
>
No, take me back
</v-btn>
</v-row>
</v-card-text>
</v-card>
</v-dialog>
</div>
</template>
<script>
import CVicon from '../common/cv-icon'
import CVselect from '../common/cv-select'
import CVinput from '../common/cv-input'
export default {
name: "CameraAndPipelineSelect",
components: {
CVicon,
CVselect,
CVinput
},
data: () => {
return {
re: RegExp("^[A-Za-z0-9 \\-)(]*[A-Za-z0-9][A-Za-z0-9 \\-)(.]*$"),
isCameraNameEdit: false,
newCameraName: "",
cameraNameError: "",
isPipelineNameEdit: false,
namingDialog: false,
newPipelineName: "",
duplicateDialog: false,
pipeIndexToDuplicate: undefined
}
},
computed: {
checkCameraName() {
if (this.newCameraName !== this.$store.getters.cameraList[this.currentCameraIndex]) {
if (this.re.test(this.newCameraName)) {
for (let cam in this.cameraList) {
if (this.cameraList.hasOwnProperty(cam)) {
if (this.newCameraName === this.cameraList[cam]) {
return "A camera by that name already Exists"
}
}
}
} else {
return "A camera name can only contain letters, numbers and spaces"
}
}
return "";
},
checkPipelineName() {
if (this.newPipelineName !== this.$store.getters.pipelineList[this.currentPipelineIndex - 1] || this.isPipelineNameEdit === false) {
if (this.re.test(this.newPipelineName)) {
for (let pipe in this.$store.getters.pipelineList) {
if (this.$store.getters.pipelineList.hasOwnProperty(pipe)) {
if (this.newPipelineName === this.$store.getters.pipelineList[pipe]) {
return "A pipeline with this name already exists"
}
}
}
} else {
return "A pipeline name can only contain letters, numbers, and spaces"
}
}
return ""
},
currentCameraIndex: {
get() {
return this.$store.getters.currentCameraIndex;
},
set(value) {
this.$store.commit('currentCameraIndex', value);
}
},
currentPipelineIndex: {
get() {
return this.$store.getters.currentPipelineIndex + (this.$store.getters.isDriverMode ? 1 : 0);
},
set(value) {
this.$store.commit('currentPipelineIndex', value - (this.$store.getters.isDriverMode ? 1 : 0));
}
}
},
methods: {
changeCameraName() {
this.newCameraName = this.$store.getters.cameraList[this.currentCameraIndex];
this.isCameraNameEdit = true;
},
saveCameraNameChange() {
if (this.checkCameraName === "") {
// this.handleInputWithIndex("changeCameraName", this.newCameraName);
this.axios.post('http://' + this.$address + '/api/setCameraNickname',
{name: this.newCameraName, cameraIndex: this.$store.getters.currentCameraIndex})
// eslint-disable-next-line
.then(r => {
this.$emit('camera-name-changed')
})
.catch(e => {
console.log("HTTP error while changing camera name " + e);
this.$emit('camera-name-changed')
})
this.discardCameraNameChange();
}
},
discardCameraNameChange() {
this.isCameraNameEdit = false;
this.newCameraName = "";
},
toPipelineNameChange() {
this.newPipelineName = this.$store.getters.pipelineList[this.currentPipelineIndex - 1];
this.isPipelineNameEdit = true;
this.namingDialog = true;
},
toCreatePipeline() {
this.newPipelineName = "New Pipeline";
this.isPipelineNameEdit = false;
this.namingDialog = true;
},
openDuplicateDialog() {
this.pipeIndexToDuplicate = this.currentPipelineIndex - 1;
this.duplicateDialog = true;
},
deleteCurrentPipeline() {
if (this.$store.getters.pipelineList.length > 1) {
this.handleInputWithIndex('deleteCurrentPipeline', {});
} else {
this.snackbar = true;
}
},
savePipelineNameChange() {
if (this.checkPipelineName === "") {
if (this.isPipelineNameEdit) {
this.handleInputWithIndex("changePipelineName", this.newPipelineName);
} else {
this.handleInputWithIndex("addNewPipeline", this.newPipelineName);
}
this.discardPipelineNameChange();
}
},
duplicatePipeline() {
// if (!this.anotherCamera) {
// this.pipelineDuplicate.camera = -1
// }
this.handleInputWithIndex("duplicatePipeline", this.pipeIndexToDuplicate);
// this.axios.post("http://" + this.$address + "/api/vision/duplicate", this.pipeIndexToDuplicate);
this.closeDuplicateDialog();
},
closeDuplicateDialog() {
this.duplicateDialog = false;
this.pipeIndexToDuplicate = undefined;
},
discardPipelineNameChange() {
this.namingDialog = false;
this.isPipelineNameEdit = false;
this.newPipelineName = "";
},
}
import CVicon from '../common/cv-icon'
import CVselect from '../common/cv-select'
import CVinput from '../common/cv-input'
export default {
name: "CameraAndPipelineSelect",
components: {
CVicon,
CVselect,
CVinput
},
data: () => {
return {
re: RegExp("^[A-Za-z0-9 \\-)(]*[A-Za-z0-9][A-Za-z0-9 \\-)(.]*$"),
isCameraNameEdit: false,
newCameraName: "",
cameraNameError: "",
isPipelineNameEdit: false,
namingDialog: false,
newPipelineName: "",
newPipelineType: 0,
duplicateDialog: false,
showPipeTypeDialog: false,
proposedPipelineType : 0,
pipeIndexToDuplicate: undefined
}
},
computed: {
checkCameraName() {
if (this.newCameraName !== this.$store.getters.cameraList[this.currentCameraIndex]) {
if (this.re.test(this.newCameraName)) {
for (let cam in this.cameraList) {
if (this.cameraList.hasOwnProperty(cam)) {
if (this.newCameraName === this.cameraList[cam]) {
return "A camera by that name already Exists"
}
}
}
} else {
return "A camera name can only contain letters, numbers and spaces"
}
}
return "";
},
checkPipelineName() {
if (this.newPipelineName !== this.$store.getters.pipelineList[this.currentPipelineIndex - 1] || this.isPipelineNameEdit === false) {
if (this.re.test(this.newPipelineName)) {
for (let pipe in this.$store.getters.pipelineList) {
if (this.$store.getters.pipelineList.hasOwnProperty(pipe)) {
if (this.newPipelineName === this.$store.getters.pipelineList[pipe]) {
return "A pipeline with this name already exists"
}
}
}
} else {
return "A pipeline name can only contain letters, numbers, and spaces"
}
}
return ""
},
currentCameraIndex: {
get() {
return this.$store.getters.currentCameraIndex;
},
set(value) {
this.$store.commit('currentCameraIndex', value);
}
},
currentPipelineIndex: {
get() {
return this.$store.getters.currentPipelineIndex + (this.$store.getters.isDriverMode ? 1 : 0);
},
set(value) {
this.$store.commit('currentPipelineIndex', value - (this.$store.getters.isDriverMode ? 1 : 0));
}
},
currentPipelineType: {
get() {
return this.$store.getters.currentPipelineSettings.pipelineType - 2;
},
set(value) {
value; // nop, since we have the dialog for this
}
}
},
methods: {
showTypeDialog(idx) {
// Only show the dialog if it's a new type
this.showPipeTypeDialog = idx !== this.currentPipelineType;
this.proposedPipelineType = idx;
},
changePipeType(actuallyChange) {
const newIdx = actuallyChange ? this.proposedPipelineType : this.currentPipelineType
this.handleInputWithIndex('pipelineType', newIdx);
this.showPipeTypeDialog = false;
},
changeCameraName() {
this.newCameraName = this.$store.getters.cameraList[this.currentCameraIndex];
this.isCameraNameEdit = true;
},
saveCameraNameChange() {
if (this.checkCameraName === "") {
// this.handleInputWithIndex("changeCameraName", this.newCameraName);
this.axios.post('http://' + this.$address + '/api/setCameraNickname',
{name: this.newCameraName, cameraIndex: this.$store.getters.currentCameraIndex})
// eslint-disable-next-line
.then(r => {
this.$emit('camera-name-changed')
})
.catch(e => {
console.log("HTTP error while changing camera name " + e);
this.$emit('camera-name-changed')
})
this.discardCameraNameChange();
}
},
discardCameraNameChange() {
this.isCameraNameEdit = false;
this.newCameraName = "";
},
toPipelineNameChange() {
this.newPipelineName = this.$store.getters.pipelineList[this.currentPipelineIndex - 1];
this.isPipelineNameEdit = true;
this.namingDialog = true;
},
toCreatePipeline() {
this.newPipelineName = "New Pipeline";
this.isPipelineNameEdit = false;
this.namingDialog = true;
},
deleteCurrentPipeline() {
if (this.$store.getters.pipelineList.length > 1) {
this.handleInputWithIndex('deleteCurrentPipeline', {});
} else {
this.snackbar = true;
}
},
savePipelineNameChange() {
if (this.checkPipelineName === "") {
if (this.isPipelineNameEdit) {
this.handleInputWithIndex("changePipelineName", this.newPipelineName);
} else {
this.handleInputWithIndex("addNewPipeline", [this.newPipelineName, this.newPipelineType]); // 0 for reflective, 1 for colored shpae
}
this.discardPipelineNameChange();
}
},
duplicatePipeline() {
this.handleInputWithIndex("duplicatePipeline", this.currentPipelineIndex);
},
discardPipelineNameChange() {
this.namingDialog = false;
this.isPipelineNameEdit = false;
this.newPipelineName = "";
},
}
}
</script>
<style scoped>