mirror of
https://github.com/YuzuZensai/Pien-Studio.git
synced 2026-09-02 14:18:35 +00:00
♻️ refactor!: massive refactor
This commit is contained in:
@@ -1,5 +1,10 @@
|
||||
import React from "react";
|
||||
import type { FaceBlurMethod, Layer, LayerEffect } from "@pien-studio/types";
|
||||
import {
|
||||
getLayerRuntimeSource,
|
||||
type FaceBlurMethod,
|
||||
type Layer,
|
||||
type LayerEffect,
|
||||
} from "@pien-studio/types";
|
||||
import type { FaceDetectionOverlay } from "./use-face-detection";
|
||||
|
||||
type FaceBlurPreview = {
|
||||
@@ -21,15 +26,31 @@ type UseFaceBlurWorkflowOptions = {
|
||||
};
|
||||
|
||||
export function useFaceBlurWorkflow(options: UseFaceBlurWorkflowOptions) {
|
||||
const { selectedLayer, faceDetectionsLayerId, faceDetections, setLayerEffect, removeLayerEffect } = options;
|
||||
const [blurMethod, setBlurMethod] = React.useState<FaceBlurMethod>("gaussian");
|
||||
const {
|
||||
selectedLayer,
|
||||
faceDetectionsLayerId,
|
||||
faceDetections,
|
||||
setLayerEffect,
|
||||
removeLayerEffect,
|
||||
} = options;
|
||||
const [blurMethod, setBlurMethod] =
|
||||
React.useState<FaceBlurMethod>("gaussian");
|
||||
const [blurAmount, setBlurAmount] = React.useState(14);
|
||||
const [censorColor, setCensorColor] = React.useState("#111111");
|
||||
const [faceSelection, setFaceSelection] = React.useState<FaceSelectionState | null>(null);
|
||||
const hasDetectableSelection = Boolean(selectedLayer && selectedLayer.type === "raster" && faceDetectionsLayerId === selectedLayer.id);
|
||||
const [faceSelection, setFaceSelection] =
|
||||
React.useState<FaceSelectionState | null>(null);
|
||||
const hasDetectableSelection = Boolean(
|
||||
selectedLayer &&
|
||||
selectedLayer.type === "raster" &&
|
||||
faceDetectionsLayerId === selectedLayer.id,
|
||||
);
|
||||
|
||||
const faceBlurEffect = React.useMemo(
|
||||
() => selectedLayer?.effects.find((e): e is Extract<LayerEffect, { kind: "face-blur" }> => e.kind === "face-blur") ?? null,
|
||||
() =>
|
||||
selectedLayer?.effects.find(
|
||||
(e): e is Extract<LayerEffect, { kind: "face-blur" }> =>
|
||||
e.kind === "face-blur",
|
||||
) ?? null,
|
||||
[selectedLayer?.effects],
|
||||
);
|
||||
|
||||
@@ -40,18 +61,25 @@ export function useFaceBlurWorkflow(options: UseFaceBlurWorkflowOptions) {
|
||||
return faceDetections.map((_, index) => index);
|
||||
}, [faceDetections, faceBlurEffect, hasDetectableSelection]);
|
||||
|
||||
const selectedFaceIndices = faceSelection?.key === selectionKey ? faceSelection.indices : defaultSelectedFaceIndices;
|
||||
const selectedFaceIndices =
|
||||
faceSelection?.key === selectionKey
|
||||
? faceSelection.indices
|
||||
: defaultSelectedFaceIndices;
|
||||
|
||||
const buildBlurRegions = React.useCallback(
|
||||
(indices: number[]) => {
|
||||
if (!selectedLayer || selectedLayer.type !== "raster") return [];
|
||||
if (faceDetectionsLayerId !== selectedLayer.id || faceDetections.length === 0) return [];
|
||||
if (
|
||||
faceDetectionsLayerId !== selectedLayer.id ||
|
||||
faceDetections.length === 0
|
||||
)
|
||||
return [];
|
||||
const indexSet = new Set(indices);
|
||||
return faceDetections
|
||||
.filter((_, index) => indexSet.has(index))
|
||||
.map((face) => {
|
||||
const baseWidth = Math.max(1, selectedLayer.width ?? face.sourceWidth);
|
||||
const baseHeight = Math.max(1, selectedLayer.height ?? face.sourceHeight);
|
||||
const baseWidth = Math.max(1, selectedLayer.width);
|
||||
const baseHeight = Math.max(1, selectedLayer.height);
|
||||
const scaleX = face.sourceWidth / baseWidth;
|
||||
const scaleY = face.sourceHeight / baseHeight;
|
||||
return {
|
||||
@@ -68,13 +96,21 @@ export function useFaceBlurWorkflow(options: UseFaceBlurWorkflowOptions) {
|
||||
[censorColor, faceDetections, faceDetectionsLayerId, selectedLayer],
|
||||
);
|
||||
|
||||
const toggleFaceIndex = React.useCallback((index: number) => {
|
||||
setFaceSelection((prev) => {
|
||||
const current = prev?.key === selectionKey ? prev.indices : defaultSelectedFaceIndices;
|
||||
const indices = current.includes(index) ? current.filter((item) => item !== index) : [...current, index];
|
||||
return { key: selectionKey, indices };
|
||||
});
|
||||
}, [defaultSelectedFaceIndices, selectionKey]);
|
||||
const toggleFaceIndex = React.useCallback(
|
||||
(index: number) => {
|
||||
setFaceSelection((prev) => {
|
||||
const current =
|
||||
prev?.key === selectionKey
|
||||
? prev.indices
|
||||
: defaultSelectedFaceIndices;
|
||||
const indices = current.includes(index)
|
||||
? current.filter((item) => item !== index)
|
||||
: [...current, index];
|
||||
return { key: selectionKey, indices };
|
||||
});
|
||||
},
|
||||
[defaultSelectedFaceIndices, selectionKey],
|
||||
);
|
||||
|
||||
const clearBlur = React.useCallback(() => {
|
||||
if (!selectedLayer) return;
|
||||
@@ -84,8 +120,17 @@ export function useFaceBlurWorkflow(options: UseFaceBlurWorkflowOptions) {
|
||||
|
||||
const blurFaces = React.useCallback(
|
||||
(indices: number[]) => {
|
||||
if (!selectedLayer || selectedLayer.type !== "raster" || !selectedLayer.sourceUri) return;
|
||||
if (faceDetectionsLayerId !== selectedLayer.id || faceDetections.length === 0) return;
|
||||
if (
|
||||
!selectedLayer ||
|
||||
selectedLayer.type !== "raster" ||
|
||||
!getLayerRuntimeSource(selectedLayer)
|
||||
)
|
||||
return;
|
||||
if (
|
||||
faceDetectionsLayerId !== selectedLayer.id ||
|
||||
faceDetections.length === 0
|
||||
)
|
||||
return;
|
||||
const regions = buildBlurRegions(indices);
|
||||
setLayerEffect(selectedLayer.id, {
|
||||
kind: "face-blur",
|
||||
@@ -97,11 +142,25 @@ export function useFaceBlurWorkflow(options: UseFaceBlurWorkflowOptions) {
|
||||
});
|
||||
setFaceSelection({ key: selectionKey, indices: [] });
|
||||
},
|
||||
[blurAmount, blurMethod, buildBlurRegions, censorColor, faceDetections.length, faceDetectionsLayerId, selectedLayer, selectionKey, setLayerEffect],
|
||||
[
|
||||
blurAmount,
|
||||
blurMethod,
|
||||
buildBlurRegions,
|
||||
censorColor,
|
||||
faceDetections.length,
|
||||
faceDetectionsLayerId,
|
||||
selectedLayer,
|
||||
selectionKey,
|
||||
setLayerEffect,
|
||||
],
|
||||
);
|
||||
|
||||
const faceBlurPreview = React.useMemo<FaceBlurPreview | null>(() => {
|
||||
if (!hasDetectableSelection || !selectedLayer || selectedLayer.type !== "raster") {
|
||||
if (
|
||||
!hasDetectableSelection ||
|
||||
!selectedLayer ||
|
||||
selectedLayer.type !== "raster"
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -111,16 +170,26 @@ export function useFaceBlurWorkflow(options: UseFaceBlurWorkflowOptions) {
|
||||
|
||||
return {
|
||||
layerId: selectedLayer.id,
|
||||
effects: [{
|
||||
kind: "face-blur",
|
||||
enabled: true,
|
||||
method: blurMethod,
|
||||
amount: blurAmount,
|
||||
regions: buildBlurRegions(selectedFaceIndices),
|
||||
censorColor,
|
||||
}],
|
||||
effects: [
|
||||
{
|
||||
kind: "face-blur",
|
||||
enabled: true,
|
||||
method: blurMethod,
|
||||
amount: blurAmount,
|
||||
regions: buildBlurRegions(selectedFaceIndices),
|
||||
censorColor,
|
||||
},
|
||||
],
|
||||
};
|
||||
}, [blurAmount, blurMethod, buildBlurRegions, censorColor, hasDetectableSelection, selectedFaceIndices, selectedLayer]);
|
||||
}, [
|
||||
blurAmount,
|
||||
blurMethod,
|
||||
buildBlurRegions,
|
||||
censorColor,
|
||||
hasDetectableSelection,
|
||||
selectedFaceIndices,
|
||||
selectedLayer,
|
||||
]);
|
||||
|
||||
return {
|
||||
blurMethod,
|
||||
|
||||
Reference in New Issue
Block a user