From 848d881976529dbf374d391fcf71a9660515d862 Mon Sep 17 00:00:00 2001
From: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com>
Date: Wed, 17 Apr 2024 15:59:55 -0500
Subject: [PATCH] object masks and deletion of all types
---
web/src/components/settings/MasksAndZones.tsx | 169 +++++++++------
.../settings/MotionMaskEditPane.tsx | 41 ++--
.../settings/ObjectMaskEditPane.tsx | 205 ++++++++++++++++--
web/src/components/settings/PolygonDrawer.tsx | 1 +
.../settings/PolygonEditControls.tsx | 6 +
web/src/components/settings/PolygonItem.tsx | 110 ++++++++--
web/src/components/settings/ZoneEditPane.tsx | 35 ++-
web/src/pages/Settings.tsx | 7 +-
web/src/types/canvas.ts | 10 +-
web/src/utils/canvasUtil.ts | 16 +-
10 files changed, 461 insertions(+), 139 deletions(-)
diff --git a/web/src/components/settings/MasksAndZones.tsx b/web/src/components/settings/MasksAndZones.tsx
index 035a16927..2ab042bc4 100644
--- a/web/src/components/settings/MasksAndZones.tsx
+++ b/web/src/components/settings/MasksAndZones.tsx
@@ -7,7 +7,7 @@ import { Polygon, PolygonType } from "@/types/canvas";
import { interpolatePoints, parseCoordinates } from "@/utils/canvasUtil";
import { Skeleton } from "../ui/skeleton";
import { useResizeObserver } from "@/hooks/resize-observer";
-import { LuExternalLink, LuInfo, LuPlus } from "react-icons/lu";
+import { LuExternalLink, LuPlus } from "react-icons/lu";
import {
HoverCard,
HoverCardContent,
@@ -25,12 +25,6 @@ import ObjectMaskEditPane from "./ObjectMaskEditPane";
import PolygonItem from "./PolygonItem";
import { Link } from "react-router-dom";
-// export type ZoneObjects = {
-// camera: string;
-// zoneName: string;
-// objects: string[];
-// };
-
type MasksAndZoneProps = {
selectedCamera: string;
selectedZoneMask?: PolygonType[];
@@ -209,12 +203,12 @@ export default function MasksAndZones({
setActivePolygonIndex(allPolygons.length);
let polygonColor = [128, 128, 0];
+
if (type == "motion_mask") {
polygonColor = [0, 0, 220];
}
if (type == "object_mask") {
polygonColor = [128, 128, 128];
- // TODO - get this from config object after mutation so label can be set
}
setEditingPolygons([
@@ -224,6 +218,7 @@ export default function MasksAndZones({
isFinished: false,
// isUnsaved: true,
type,
+ typeIndex: 9999,
name: "",
objects: [],
camera: selectedCamera,
@@ -305,30 +300,49 @@ export default function MasksAndZones({
}),
);
- // this can be an array or a string
- const motionMasks = Object.entries(
- Array.isArray(cameraConfig.motion.mask)
- ? cameraConfig.motion.mask
- : [cameraConfig.motion.mask],
- ).map(([, maskData], index) => ({
- type: "motion_mask" as PolygonType,
- typeIndex: index,
- camera: cameraConfig.name,
- name: `Motion Mask ${index + 1}`,
- objects: [],
- points: interpolatePoints(
- parseCoordinates(maskData),
- 1,
- 1,
- scaledWidth,
- scaledHeight,
- ),
- isFinished: true,
- color: [0, 0, 255],
- }));
+ let motionMasks: Polygon[] = [];
+ let globalObjectMasks: Polygon[] = [];
+ let objectMasks: Polygon[] = [];
- const globalObjectMasks = Object.entries(cameraConfig.objects.mask).map(
- ([, maskData], index) => ({
+ if (
+ cameraConfig.motion.mask !== null &&
+ cameraConfig.motion.mask !== undefined
+ ) {
+ // this can be an array or a string
+ motionMasks = (
+ Array.isArray(cameraConfig.motion.mask)
+ ? cameraConfig.motion.mask
+ : cameraConfig.motion.mask
+ ? [cameraConfig.motion.mask]
+ : []
+ ).map((maskData, index) => ({
+ type: "motion_mask" as PolygonType,
+ typeIndex: index,
+ camera: cameraConfig.name,
+ name: `Motion Mask ${index + 1}`,
+ objects: [],
+ points: interpolatePoints(
+ parseCoordinates(maskData),
+ 1,
+ 1,
+ scaledWidth,
+ scaledHeight,
+ ),
+ isFinished: true,
+ color: [0, 0, 255],
+ }));
+ }
+
+ const globalObjectMasksArray = Array.isArray(cameraConfig.objects.mask)
+ ? cameraConfig.objects.mask
+ : cameraConfig.objects.mask
+ ? [cameraConfig.objects.mask]
+ : [];
+ if (
+ cameraConfig.objects.mask !== null &&
+ cameraConfig.objects.mask !== undefined
+ ) {
+ globalObjectMasks = globalObjectMasksArray.map((maskData, index) => ({
type: "object_mask" as PolygonType,
typeIndex: index,
camera: cameraConfig.name,
@@ -342,41 +356,66 @@ export default function MasksAndZones({
scaledHeight,
),
isFinished: true,
- // isUnsaved: false,
- color: [0, 0, 255],
- }),
- );
+ color: [128, 128, 128],
+ }));
+ }
+
+ // if (globalObjectMasks && !Array.isArray(globalObjectMasks)) {
+ // globalObjectMasks = [globalObjectMasks];
+ // }
+
+ console.log("global", globalObjectMasks);
const globalObjectMasksCount = globalObjectMasks.length;
- const objectMasks = Object.entries(cameraConfig.objects.filters).flatMap(
- ([objectName, { mask }]): Polygon[] =>
- mask !== null && mask !== undefined
- ? mask.flatMap((maskItem, subIndex) =>
- maskItem !== null && maskItem !== undefined
- ? [
- {
- type: "object_mask" as PolygonType,
- typeIndex: subIndex,
- camera: cameraConfig.name,
- name: `Object Mask ${globalObjectMasksCount + subIndex + 1} (${objectName})`,
- objects: [objectName],
- points: interpolatePoints(
- parseCoordinates(maskItem),
- 1,
- 1,
- scaledWidth,
- scaledHeight,
- ),
- isFinished: true,
- // isUnsaved: false,
- color: [128, 128, 128],
- },
- ]
- : [],
+ console.log("filters", cameraConfig.objects.filters);
+
+ let index = 0;
+ objectMasks = Object.entries(cameraConfig.objects.filters)
+ .filter(([_, { mask }]) => mask || Array.isArray(mask))
+ .flatMap(([objectName, { mask }]): Polygon[] => {
+ console.log("index", index);
+ console.log("outer", objectName, mask);
+
+ const maskArray = Array.isArray(mask) ? mask : mask ? [mask] : [];
+
+ return maskArray.flatMap((maskItem, subIndex) => {
+ const maskItemString = maskItem;
+
+ const newMask = {
+ type: "object_mask" as PolygonType,
+ typeIndex: subIndex,
+ camera: cameraConfig.name,
+ name: `Object Mask ${globalObjectMasksCount + index + 1} (${objectName})`,
+ objects: [objectName],
+ points: interpolatePoints(
+ parseCoordinates(maskItem),
+ 1,
+ 1,
+ scaledWidth,
+ scaledHeight,
+ ),
+ isFinished: true,
+ color: [128, 128, 128],
+ };
+ index++;
+
+ if (
+ globalObjectMasksArray.some(
+ (globalMask) => globalMask === maskItemString,
)
- : [],
- );
+ ) {
+ index--;
+ return [];
+ } else {
+ return [newMask];
+ }
+ });
+ });
+
+ console.log(Object.entries(cameraConfig.objects.filters));
+
+ console.log("final object masks", objectMasks);
// console.log("setting all and editing");
setAllPolygons([
@@ -404,9 +443,9 @@ export default function MasksAndZones({
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [cameraConfig, containerRef, scaledHeight, scaledWidth]);
- useEffect(() => {
- console.log("editing polygons changed:", editingPolygons);
- }, [editingPolygons]);
+ // useEffect(() => {
+ // console.log("editing polygons changed:", editingPolygons);
+ // }, [editingPolygons]);
useEffect(() => {
if (editPane === undefined) {
diff --git a/web/src/components/settings/MotionMaskEditPane.tsx b/web/src/components/settings/MotionMaskEditPane.tsx
index a921af8ed..ff7a32a7e 100644
--- a/web/src/components/settings/MotionMaskEditPane.tsx
+++ b/web/src/components/settings/MotionMaskEditPane.tsx
@@ -19,6 +19,7 @@ import {
import axios from "axios";
import { toast } from "sonner";
import { Toaster } from "../ui/sonner";
+import ActivityIndicator from "../indicators/activity-indicator";
type MotionMaskEditPaneProps = {
polygons?: Polygon[];
@@ -105,7 +106,9 @@ export default function MotionMaskEditPane({
let index = Array.isArray(cameraConfig.motion.mask)
? cameraConfig.motion.mask.length
- : 1;
+ : cameraConfig.motion.mask
+ ? 1
+ : 0;
console.log("are we an array?", Array.isArray(cameraConfig.motion.mask));
console.log("index", index);
@@ -114,20 +117,14 @@ export default function MotionMaskEditPane({
// editing existing mask, not creating a new one
if (editingMask) {
index = polygon.typeIndex;
- if (polygon.name) {
- const match = polygon.name.match(/\d+/);
- if (match) {
- // index = parseInt(match[0]) - 1;
- console.log("editing, index", index);
- }
- }
+ console.log("editing, index", index);
}
- const filteredMask = Array.isArray(cameraConfig.motion.mask)
- ? cameraConfig.motion.mask
- : [cameraConfig.motion.mask].filter(
- (_, currentIndex) => currentIndex !== index,
- );
+ const filteredMask = (
+ Array.isArray(cameraConfig.motion.mask)
+ ? cameraConfig.motion.mask
+ : [cameraConfig.motion.mask]
+ ).filter((_, currentIndex) => currentIndex !== index);
console.log("filtered", filteredMask);
// if (editingMask) {
@@ -163,7 +160,7 @@ export default function MotionMaskEditPane({
})
.then((res) => {
if (res.status === 200) {
- toast.success(`Zone ${name} saved.`, {
+ toast.success(`${polygon.name || "Motion Mask"} has been saved.`, {
position: "top-center",
});
// setChangedValue(false);
@@ -274,8 +271,20 @@ export default function MotionMaskEditPane({
-