mask
This commit is contained in:
@@ -6,28 +6,35 @@ type MaskSettingsProps = {
|
||||
};
|
||||
|
||||
/**
|
||||
* MaskSettings - تنظیمات mask mode برای shapes
|
||||
* MaskSettings - تنظیمات masking برای objects
|
||||
*
|
||||
* این component اجازه میده کاربر یک shape رو به mask تبدیل کنه
|
||||
* فقط برای shapes قابل استفاده است (rectangle, circle, triangle, abstract)
|
||||
* دو حالت دارد:
|
||||
* 1. برای shapes: تبدیل shape به mask (isMask)
|
||||
* 2. برای objects: انتخاب یک mask برای apply کردن (maskId)
|
||||
*/
|
||||
const MaskSettings = ({ objectId }: MaskSettingsProps) => {
|
||||
const { objects, updateObject, selectedObjectId, setSelectedObjectId } = useEditorStore();
|
||||
|
||||
|
||||
const object = objects.find((obj) => obj.id === objectId);
|
||||
|
||||
|
||||
if (!object) return null;
|
||||
|
||||
|
||||
const canBeMask = object.type === "rectangle";
|
||||
|
||||
if (!canBeMask) return null;
|
||||
|
||||
const isMask = object.isMask || false;
|
||||
const currentShowGuide = object.showMaskGuide !== false;
|
||||
|
||||
// Get all available masks (excluding self if it's a shape)
|
||||
const availableMasks = objects.filter(
|
||||
(obj) => obj.isMask && obj.id !== objectId && obj.visible !== false
|
||||
);
|
||||
|
||||
const handleToggleMask = (checked: boolean) => {
|
||||
updateObject(objectId, { isMask: checked, showMaskGuide: checked ? true : undefined });
|
||||
|
||||
updateObject(objectId, {
|
||||
isMask: checked,
|
||||
showMaskGuide: checked ? true : undefined,
|
||||
maskId: undefined // Clear maskId when becoming a mask
|
||||
});
|
||||
|
||||
if (checked && selectedObjectId === objectId) {
|
||||
setSelectedObjectId(null);
|
||||
}
|
||||
@@ -37,37 +44,119 @@ const MaskSettings = ({ objectId }: MaskSettingsProps) => {
|
||||
updateObject(objectId, { showMaskGuide: checked });
|
||||
};
|
||||
|
||||
const handleSelectMask = (maskId: string) => {
|
||||
updateObject(objectId, { maskId: maskId || undefined });
|
||||
};
|
||||
|
||||
const handleToggleMaskInvert = (checked: boolean) => {
|
||||
updateObject(objectId, { maskInvert: checked });
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="p-4 border-b">
|
||||
<div className="flex items-center justify-between mb-3">
|
||||
<div className="flex flex-col gap-1">
|
||||
<span className="text-sm font-medium">استفاده به عنوان ماسک</span>
|
||||
<span className="text-xs text-gray-500">
|
||||
ناحیهای که با ماسک همپوشانی دارد مخفی میشود
|
||||
</span>
|
||||
</div>
|
||||
<Switch
|
||||
checked={isMask}
|
||||
onCheckedChange={handleToggleMask}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{isMask && (
|
||||
<>
|
||||
<div className="p-4 border-b space-y-4">
|
||||
{/* Section 1: Convert shape to mask (only for shapes) */}
|
||||
{canBeMask && (
|
||||
<div>
|
||||
<div className="flex items-center justify-between mb-3">
|
||||
<span className="text-sm">نمایش راهنمای ماسک</span>
|
||||
<div className="flex flex-col gap-1">
|
||||
<span className="text-sm font-medium">استفاده به عنوان ماسک</span>
|
||||
<span className="text-xs text-gray-500">
|
||||
این شکل را به ماسک تبدیل کن
|
||||
</span>
|
||||
</div>
|
||||
<Switch
|
||||
checked={currentShowGuide}
|
||||
onCheckedChange={handleToggleGuide}
|
||||
checked={isMask}
|
||||
onCheckedChange={handleToggleMask}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="p-2 bg-blue-50 rounded-md">
|
||||
<p className="text-xs text-blue-700">
|
||||
💡 قسمتهای همپوشانی با این ماسک مخفی میشوند.
|
||||
|
||||
{isMask && (
|
||||
<>
|
||||
<div className="flex items-center justify-between mb-3">
|
||||
<span className="text-sm">نمایش راهنمای ماسک</span>
|
||||
<Switch
|
||||
checked={currentShowGuide}
|
||||
onCheckedChange={handleToggleGuide}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="p-2 bg-blue-50 rounded-md">
|
||||
<p className="text-xs text-blue-700">
|
||||
💡 این شکل به ماسک تبدیل شد. از تنظیمات objects دیگر میتوانید این ماسک را apply کنید.
|
||||
</p>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Section 2: Apply mask to object (for all non-mask objects) */}
|
||||
{!isMask && availableMasks.length > 0 && (
|
||||
<div>
|
||||
<div className="mb-3">
|
||||
<span className="text-sm font-medium">اعمال ماسک</span>
|
||||
<p className="text-xs text-gray-500 mt-1">
|
||||
یک ماسک برای این object انتخاب کنید
|
||||
</p>
|
||||
</div>
|
||||
</>
|
||||
|
||||
<div className="space-y-2 max-h-48 overflow-y-auto">
|
||||
{availableMasks.map((mask) => {
|
||||
const isActive = object.maskId === mask.id;
|
||||
const maskLabel = `${mask.shapeType === "circle" ? "دایره" : mask.shapeType === "triangle" ? "مثلث" : mask.shapeType === "abstract" ? "ستاره" : "مربع"} `;
|
||||
|
||||
return (
|
||||
<div
|
||||
key={mask.id}
|
||||
className={`flex items-center justify-between p-2 rounded-lg border transition-colors ${isActive ? "border-blue-500 bg-blue-50" : "border-gray-200 hover:border-gray-300"
|
||||
}`}
|
||||
>
|
||||
<span className="text-sm flex-1">{maskLabel}</span>
|
||||
<Switch
|
||||
checked={isActive}
|
||||
onCheckedChange={(checked) => handleSelectMask(checked ? mask.id : "")}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
|
||||
{object.maskId && (
|
||||
<>
|
||||
<div className="flex items-center justify-between mt-4 pt-3 border-t">
|
||||
<span className="text-xs">نمایش فقط همپوشانی</span>
|
||||
<Switch
|
||||
checked={object.maskInvert === false}
|
||||
onCheckedChange={(checked) => handleToggleMaskInvert(!checked)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* نمایش وضعیت گروهبندی */}
|
||||
{(() => {
|
||||
const maskObj = objects.find(m => m.id === object.maskId);
|
||||
const isGrouped = object.groupId && maskObj?.groupId === object.groupId;
|
||||
|
||||
return (
|
||||
<div className={`mt-3 p-2 rounded-md ${isGrouped ? "bg-purple-50" : "bg-green-50"}`}>
|
||||
<p className={`text-xs ${isGrouped ? "text-purple-700" : "text-green-700"}`}>
|
||||
{isGrouped ? (
|
||||
<>
|
||||
🔗 گروهبندی شده: Object و ماسک با هم حرکت میکنند. برای لغو، object را انتخاب کنید و دکمه "لغو گروهبندی" را بزنید.
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
✓ ماسک اعمال شد. {object.maskInvert === false ? "فقط قسمتهای همپوشانی نمایش داده میشوند." : "قسمتهای همپوشانی مخفی میشوند."}
|
||||
<br />
|
||||
💡 برای گروهبندی با ماسک، object را انتخاب کنید و دکمه "گروهبندی با ماسک" را بزنید.
|
||||
</>
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
})()}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user