|  |  | 
 |  |  | import React, { useEffect } from 'react'; | 
 |  |  | import React, { useEffect, useState } from 'react'; | 
 |  |  | import { useForm, Controller } from 'react-hook-form'; | 
 |  |  | import { | 
 |  |  |     Box, | 
 |  |  | 
 |  |  |     Divider, | 
 |  |  | } from '@mui/material'; | 
 |  |  | import MuiInput from '@mui/material/Input'; | 
 |  |  | import { styled } from '@mui/material/styles'; | 
 |  |  | import { useTranslate } from 'react-admin'; | 
 |  |  | import * as Tool from '../tool'; | 
 |  |  | import ConfirmButton from '../../page/components/ConfirmButton'; | 
 |  |  | import CopyDrawer from './CopyDrawer'; | 
 |  |  |  | 
 |  |  | const MapSettings = (props) => { | 
 |  |  |     const { sprite, onSubmit } = props; | 
 |  |  |     const { sprite, setSpriteSettings, onSubmit, width, lastCopiedSprites, setLastCopiedSprites } = props; | 
 |  |  |     const translate = useTranslate(); | 
 |  |  |     const [copyVisible, setCopyVisible] = useState(false); | 
 |  |  |  | 
 |  |  |     const { control, handleSubmit, reset, watch } = useForm({ | 
 |  |  |         defaultValues: { | 
 |  |  |             x: sprite?.position.x || 0, | 
 |  |  |             y: sprite?.position.y || 0, | 
 |  |  |             scaleX: sprite?.scale.x || 1, | 
 |  |  |             scaleY: sprite?.scale.y || 1, | 
 |  |  |             x: sprite?.position?.x || 0, | 
 |  |  |             y: sprite?.position?.y || 0, | 
 |  |  |             scaleX: sprite?.scale?.x || 1, | 
 |  |  |             scaleY: sprite?.scale?.y || 1, | 
 |  |  |             rotation: (sprite?.rotation * 180) / Math.PI || 0, | 
 |  |  |             copyDirection: 'right', | 
 |  |  |             copyCount: 1, | 
 |  |  |             // 其他默认值... | 
 |  |  |         }, | 
 |  |  |     }); | 
 |  |  |  | 
 |  |  |     // 监听所有字段的变化 | 
 |  |  |     const watchAllFields = watch(); | 
 |  |  |  | 
 |  |  |     useEffect(() => { | 
 |  |  |         if (sprite) { | 
 |  |  |             setCopyVisible(false); | 
 |  |  |             reset({ | 
 |  |  |                 x: sprite.position.x, | 
 |  |  |                 y: sprite.position.y, | 
 |  |  |                 scaleX: sprite.scale.x, | 
 |  |  |                 scaleY: sprite.scale.y, | 
 |  |  |                 rotation: (sprite.rotation * 180) / Math.PI, | 
 |  |  |                 // 设置其他字段的初始值 | 
 |  |  |             }); | 
 |  |  |         } | 
 |  |  |     }, [sprite, reset]); | 
 |  |  |  | 
 |  |  |     // 更新精灵属性的函数 | 
 |  |  |     const updateSprite = (data) => { | 
 |  |  |         if (sprite) { | 
 |  |  |             sprite.position.x = data.x; | 
 |  |  | 
 |  |  |             sprite.scale.x = data.scaleX; | 
 |  |  |             sprite.scale.y = data.scaleY; | 
 |  |  |             sprite.rotation = (data.rotation * Math.PI) / 180; | 
 |  |  |             // 更新其他属性... | 
 |  |  |         } | 
 |  |  |     }; | 
 |  |  |  | 
 |  |  |     // 处理表单提交 | 
 |  |  |     const onFormSubmit = (data) => { | 
 |  |  |         updateSprite(data); | 
 |  |  |         if (onSubmit) { | 
 |  |  | 
 |  |  |         } | 
 |  |  |     }; | 
 |  |  |  | 
 |  |  |     // 旋转滑块的刻度 | 
 |  |  |     const rotationMarks = [ | 
 |  |  |         { value: 0, label: '0°' }, | 
 |  |  |         { value: 90, label: '90°' }, | 
 |  |  |         { value: 180, label: '180°' }, | 
 |  |  |         { value: 270, label: '270°' }, | 
 |  |  |         { value: 360, label: '360°' }, | 
 |  |  |     ]; | 
 |  |  |  | 
 |  |  |     return ( | 
 |  |  |         <Box component="form" onSubmit={handleSubmit(onFormSubmit)} noValidate sx={{ mt: 0 }}> | 
 |  |  |             <Grid container spacing={2}> | 
 |  |  |                 {/* position */} | 
 |  |  |                 <Grid item xs={12}> | 
 |  |  |                     <Typography variant="inherit"> | 
 |  |  |                         {translate('page.map.settings.map.base.position')} | 
 |  |  |                     </Typography> | 
 |  |  |                 </Grid> | 
 |  |  |                 <Grid item xs={6} pt={0} sx={{ | 
 |  |  |                     paddingTop: '8px !important', | 
 |  |  |                 }}> | 
 |  |  |                     <Controller | 
 |  |  |                         name="x" | 
 |  |  |                         control={control} | 
 |  |  |                         render={({ field }) => ( | 
 |  |  |                             <TextField | 
 |  |  |                                 {...field} | 
 |  |  |                                 label="X" | 
 |  |  |                                 type="number" | 
 |  |  |                                 fullWidth | 
 |  |  |                                 onChange={(e) => { | 
 |  |  |                                     const value = parseFloat(e.target.value); | 
 |  |  |                                     field.onChange(e); | 
 |  |  |                                     if (!isNaN(value)) { | 
 |  |  |                                         updateSprite({ ...watchAllFields, x: value }); | 
 |  |  |                                     } | 
 |  |  |                                 }} | 
 |  |  |                             /> | 
 |  |  |                         )} | 
 |  |  |                     /> | 
 |  |  |                 </Grid> | 
 |  |  |                 <Grid item xs={6} sx={{ | 
 |  |  |                     paddingTop: '8px !important', | 
 |  |  |                 }}> | 
 |  |  |                     <Controller | 
 |  |  |                         name="y" | 
 |  |  |                         control={control} | 
 |  |  |                         render={({ field }) => ( | 
 |  |  |                             <TextField | 
 |  |  |                                 {...field} | 
 |  |  |                                 label="Y" | 
 |  |  |                                 type="number" | 
 |  |  |                                 fullWidth | 
 |  |  |                                 onChange={(e) => { | 
 |  |  |                                     const value = parseFloat(e.target.value); | 
 |  |  |                                     field.onChange(e); | 
 |  |  |                                     if (!isNaN(value)) { | 
 |  |  |                                         updateSprite({ ...watchAllFields, y: value }); | 
 |  |  |                                     } | 
 |  |  |                                 }} | 
 |  |  |                             /> | 
 |  |  |                         )} | 
 |  |  |                     /> | 
 |  |  |                 </Grid> | 
 |  |  |         <> | 
 |  |  |             <Box component="form" onSubmit={handleSubmit(onFormSubmit)} noValidate sx={{ mt: 0 }}> | 
 |  |  |                 <Grid container spacing={1.4}> | 
 |  |  |                     {/* position */} | 
 |  |  |                     <Grid item xs={12}> | 
 |  |  |                         <Typography variant="inherit"> | 
 |  |  |                             {translate('page.map.settings.map.base.position')} | 
 |  |  |                         </Typography> | 
 |  |  |                     </Grid> | 
 |  |  |                     <Grid item xs={6} pt={0} sx={{ | 
 |  |  |                         paddingTop: '8px !important', | 
 |  |  |                     }}> | 
 |  |  |                         <Controller | 
 |  |  |                             name="x" | 
 |  |  |                             control={control} | 
 |  |  |                             render={({ field }) => ( | 
 |  |  |                                 <TextField | 
 |  |  |                                     {...field} | 
 |  |  |                                     label="X" | 
 |  |  |                                     type="number" | 
 |  |  |                                     fullWidth | 
 |  |  |                                     onChange={(e) => { | 
 |  |  |                                         const value = parseFloat(e.target.value); | 
 |  |  |                                         field.onChange(e); | 
 |  |  |                                         if (!isNaN(value)) { | 
 |  |  |                                             updateSprite({ ...watchAllFields, x: value }); | 
 |  |  |                                         } | 
 |  |  |                                     }} | 
 |  |  |                                 /> | 
 |  |  |                             )} | 
 |  |  |                         /> | 
 |  |  |                     </Grid> | 
 |  |  |                     <Grid item xs={6} sx={{ | 
 |  |  |                         paddingTop: '8px !important', | 
 |  |  |                     }}> | 
 |  |  |                         <Controller | 
 |  |  |                             name="y" | 
 |  |  |                             control={control} | 
 |  |  |                             render={({ field }) => ( | 
 |  |  |                                 <TextField | 
 |  |  |                                     {...field} | 
 |  |  |                                     label="Y" | 
 |  |  |                                     type="number" | 
 |  |  |                                     fullWidth | 
 |  |  |                                     onChange={(e) => { | 
 |  |  |                                         const value = parseFloat(e.target.value); | 
 |  |  |                                         field.onChange(e); | 
 |  |  |                                         if (!isNaN(value)) { | 
 |  |  |                                             updateSprite({ ...watchAllFields, y: value }); | 
 |  |  |                                         } | 
 |  |  |                                     }} | 
 |  |  |                                 /> | 
 |  |  |                             )} | 
 |  |  |                         /> | 
 |  |  |                     </Grid> | 
 |  |  |  | 
 |  |  |                 {/* scale */} | 
 |  |  |                 <Grid item xs={12}> | 
 |  |  |                     <Typography variant="inherit"> | 
 |  |  |                         {translate('page.map.settings.map.base.scale')} | 
 |  |  |                     </Typography> | 
 |  |  |                 </Grid> | 
 |  |  |                 <Grid item xs={6} sx={{ | 
 |  |  |                     paddingTop: '8px !important', | 
 |  |  |                 }}> | 
 |  |  |                     <Controller | 
 |  |  |                         name="scaleX" | 
 |  |  |                         control={control} | 
 |  |  |                         render={({ field }) => ( | 
 |  |  |                             <TextField | 
 |  |  |                                 {...field} | 
 |  |  |                                 label="X" | 
 |  |  |                                 type="number" | 
 |  |  |                                 fullWidth | 
 |  |  |                                 inputProps={{ step: 0.1, min: 0.1, max: 10 }} | 
 |  |  |                                 onChange={(e) => { | 
 |  |  |                                     const value = parseFloat(e.target.value); | 
 |  |  |                                     field.onChange(e); | 
 |  |  |                                     if (!isNaN(value)) { | 
 |  |  |                                         updateSprite({ ...watchAllFields, scaleX: value }); | 
 |  |  |                                     } | 
 |  |  |                                 }} | 
 |  |  |                             /> | 
 |  |  |                         )} | 
 |  |  |                     /> | 
 |  |  |                 </Grid> | 
 |  |  |                 <Grid item xs={6} sx={{ | 
 |  |  |                     paddingTop: '8px !important', | 
 |  |  |                 }}> | 
 |  |  |                     <Controller | 
 |  |  |                         name="scaleY" | 
 |  |  |                         control={control} | 
 |  |  |                         render={({ field }) => ( | 
 |  |  |                             <TextField | 
 |  |  |                                 {...field} | 
 |  |  |                                 label="Y" | 
 |  |  |                                 type="number" | 
 |  |  |                                 fullWidth | 
 |  |  |                                 inputProps={{ step: 0.1, min: 0.1, max: 10 }} | 
 |  |  |                                 onChange={(e) => { | 
 |  |  |                                     const value = parseFloat(e.target.value); | 
 |  |  |                                     field.onChange(e); | 
 |  |  |                                     if (!isNaN(value)) { | 
 |  |  |                                         updateSprite({ ...watchAllFields, scaleY: value }); | 
 |  |  |                                     } | 
 |  |  |                                 }} | 
 |  |  |                             /> | 
 |  |  |                         )} | 
 |  |  |                     /> | 
 |  |  |                 </Grid> | 
 |  |  |                     {/* scale */} | 
 |  |  |                     <Grid item xs={12}> | 
 |  |  |                         <Typography variant="inherit"> | 
 |  |  |                             {translate('page.map.settings.map.base.scale')} | 
 |  |  |                         </Typography> | 
 |  |  |                     </Grid> | 
 |  |  |                     <Grid item xs={6} sx={{ | 
 |  |  |                         paddingTop: '8px !important', | 
 |  |  |                     }}> | 
 |  |  |                         <Controller | 
 |  |  |                             name="scaleX" | 
 |  |  |                             control={control} | 
 |  |  |                             render={({ field }) => ( | 
 |  |  |                                 <TextField | 
 |  |  |                                     {...field} | 
 |  |  |                                     label="X" | 
 |  |  |                                     type="number" | 
 |  |  |                                     fullWidth | 
 |  |  |                                     inputProps={{ step: 0.1, min: 0.1, max: 10 }} | 
 |  |  |                                     onChange={(e) => { | 
 |  |  |                                         const value = parseFloat(e.target.value); | 
 |  |  |                                         field.onChange(e); | 
 |  |  |                                         if (!isNaN(value)) { | 
 |  |  |                                             updateSprite({ ...watchAllFields, scaleX: value }); | 
 |  |  |                                         } | 
 |  |  |                                     }} | 
 |  |  |                                 /> | 
 |  |  |                             )} | 
 |  |  |                         /> | 
 |  |  |                     </Grid> | 
 |  |  |                     <Grid item xs={6} sx={{ | 
 |  |  |                         paddingTop: '8px !important', | 
 |  |  |                     }}> | 
 |  |  |                         <Controller | 
 |  |  |                             name="scaleY" | 
 |  |  |                             control={control} | 
 |  |  |                             render={({ field }) => ( | 
 |  |  |                                 <TextField | 
 |  |  |                                     {...field} | 
 |  |  |                                     label="Y" | 
 |  |  |                                     type="number" | 
 |  |  |                                     fullWidth | 
 |  |  |                                     inputProps={{ step: 0.1, min: 0.1, max: 10 }} | 
 |  |  |                                     onChange={(e) => { | 
 |  |  |                                         const value = parseFloat(e.target.value); | 
 |  |  |                                         field.onChange(e); | 
 |  |  |                                         if (!isNaN(value)) { | 
 |  |  |                                             updateSprite({ ...watchAllFields, scaleY: value }); | 
 |  |  |                                         } | 
 |  |  |                                     }} | 
 |  |  |                                 /> | 
 |  |  |                             )} | 
 |  |  |                         /> | 
 |  |  |                     </Grid> | 
 |  |  |  | 
 |  |  |                 {/* rotation */} | 
 |  |  |                 <Grid item xs={12}> | 
 |  |  |                     <Typography variant="inherit"> | 
 |  |  |                         {translate('page.map.settings.map.base.rotation')} | 
 |  |  |                     </Typography> | 
 |  |  |                 </Grid> | 
 |  |  |                 <Grid item xs={12}> | 
 |  |  |                     <Box display="flex" alignItems="center"> | 
 |  |  |                         <Box flex={1} mr={3}> | 
 |  |  |                             <Controller | 
 |  |  |                                 name="rotation" | 
 |  |  |                                 control={control} | 
 |  |  |                                 render={({ field }) => ( | 
 |  |  |                                     <Slider | 
 |  |  |                                         {...field} | 
 |  |  |                                         // size="small" | 
 |  |  |                                         min={0} | 
 |  |  |                                         max={360} | 
 |  |  |                                         step={1} | 
 |  |  |                                         valueLabelDisplay="auto" | 
 |  |  |                                         valueLabelFormat={(value) => `${value}°`} | 
 |  |  |                                         onChange={(e, value) => { | 
 |  |  |                                             field.onChange(value); | 
 |  |  |                                             updateSprite({ ...watchAllFields, rotation: value }); | 
 |  |  |                                         }} | 
 |  |  |                                     /> | 
 |  |  |                                 )} | 
 |  |  |                             /> | 
 |  |  |                         </Box> | 
 |  |  |                         <Box > | 
 |  |  |                             <Controller | 
 |  |  |                                 name="rotation" | 
 |  |  |                                 control={control} | 
 |  |  |                                 render={({ field }) => ( | 
 |  |  |                                     <MuiInput | 
 |  |  |                                         {...field} | 
 |  |  |                                         size="small" | 
 |  |  |                                         value={field.value} | 
 |  |  |                                         onChange={(e) => { | 
 |  |  |                                             const value = e.target.value === '' ? 0 : Number(e.target.value); | 
 |  |  |                                             if (!isNaN(value)) { | 
 |  |  |                     {/* rotation */} | 
 |  |  |                     <Grid item xs={12}> | 
 |  |  |                         <Typography variant="inherit"> | 
 |  |  |                             {translate('page.map.settings.map.base.rotation')} | 
 |  |  |                         </Typography> | 
 |  |  |                     </Grid> | 
 |  |  |                     <Grid item xs={12}> | 
 |  |  |                         <Box display="flex" alignItems="center"> | 
 |  |  |                             <Box flex={1} mr={3}> | 
 |  |  |                                 <Controller | 
 |  |  |                                     name="rotation" | 
 |  |  |                                     control={control} | 
 |  |  |                                     render={({ field }) => ( | 
 |  |  |                                         <Slider | 
 |  |  |                                             {...field} | 
 |  |  |                                             // size="small" | 
 |  |  |                                             min={0} | 
 |  |  |                                             max={360} | 
 |  |  |                                             step={1} | 
 |  |  |                                             valueLabelDisplay="auto" | 
 |  |  |                                             valueLabelFormat={(value) => `${value}°`} | 
 |  |  |                                             onChange={(e, value) => { | 
 |  |  |                                                 field.onChange(value); | 
 |  |  |                                                 updateSprite({ ...watchAllFields, rotation: value }); | 
 |  |  |                                             } | 
 |  |  |                                         }} | 
 |  |  |                                         onBlur={() => { | 
 |  |  |                                             if (field.value < 0) { | 
 |  |  |                                                 field.onChange(0); | 
 |  |  |                                             } else if (field.value > 360) { | 
 |  |  |                                                 field.onChange(360); | 
 |  |  |                                             } | 
 |  |  |                                         }} | 
 |  |  |                                         inputProps={{ | 
 |  |  |                                             step: 1, | 
 |  |  |                                             min: 0, | 
 |  |  |                                             max: 360, | 
 |  |  |                                             type: 'number', | 
 |  |  |                                             'aria-labelledby': 'input-slider', | 
 |  |  |                                         }} | 
 |  |  |                                     /> | 
 |  |  |                                 )} | 
 |  |  |                             /> | 
 |  |  |                                             }} | 
 |  |  |                                         /> | 
 |  |  |                                     )} | 
 |  |  |                                 /> | 
 |  |  |                             </Box> | 
 |  |  |                             <Box > | 
 |  |  |                                 <Controller | 
 |  |  |                                     name="rotation" | 
 |  |  |                                     control={control} | 
 |  |  |                                     render={({ field }) => ( | 
 |  |  |                                         <MuiInput | 
 |  |  |                                             {...field} | 
 |  |  |                                             size="small" | 
 |  |  |                                             value={field.value} | 
 |  |  |                                             onChange={(e) => { | 
 |  |  |                                                 const value = e.target.value === '' ? 0 : Number(e.target.value); | 
 |  |  |                                                 if (!isNaN(value)) { | 
 |  |  |                                                     field.onChange(value); | 
 |  |  |                                                     updateSprite({ ...watchAllFields, rotation: value }); | 
 |  |  |                                                 } | 
 |  |  |                                             }} | 
 |  |  |                                             onBlur={() => { | 
 |  |  |                                                 if (field.value < 0) { | 
 |  |  |                                                     field.onChange(0); | 
 |  |  |                                                 } else if (field.value > 360) { | 
 |  |  |                                                     field.onChange(360); | 
 |  |  |                                                 } | 
 |  |  |                                             }} | 
 |  |  |                                             inputProps={{ | 
 |  |  |                                                 step: 1, | 
 |  |  |                                                 min: 0, | 
 |  |  |                                                 max: 360, | 
 |  |  |                                                 type: 'number', | 
 |  |  |                                                 'aria-labelledby': 'input-slider', | 
 |  |  |                                             }} | 
 |  |  |                                         /> | 
 |  |  |                                     )} | 
 |  |  |                                 /> | 
 |  |  |                             </Box> | 
 |  |  |                         </Box> | 
 |  |  |                     </Box> | 
 |  |  |                 </Grid> | 
 |  |  |                 <Grid item xs={12}> | 
 |  |  |                     <Divider /> | 
 |  |  |                 </Grid> | 
 |  |  |                     </Grid> | 
 |  |  |  | 
 |  |  |                 {/* copy */} | 
 |  |  |                 <Grid item xs={12}> | 
 |  |  |                     <Typography variant="inherit"> | 
 |  |  |                         {translate('page.map.settings.map.copy.title')} | 
 |  |  |                     </Typography> | 
 |  |  |                 </Grid> | 
 |  |  |                 <Grid item xs={6} sx={{ | 
 |  |  |                     paddingTop: '8px !important', | 
 |  |  |                 }}> | 
 |  |  |                     <Controller | 
 |  |  |                         name="copyDirection" | 
 |  |  |                         control={control} | 
 |  |  |                         render={({ field }) => ( | 
 |  |  |                             <FormControl fullWidth> | 
 |  |  |                                 <InputLabel> | 
 |  |  |                                     {translate('page.map.settings.map.copy.direction')} | 
 |  |  |                                 </InputLabel> | 
 |  |  |                                 <Select | 
 |  |  |                     <Grid item xs={12}> | 
 |  |  |                         <Divider /> | 
 |  |  |                     </Grid> | 
 |  |  |  | 
 |  |  |                     {/* copy */} | 
 |  |  |                     <Grid item xs={12}> | 
 |  |  |                         <Typography variant="inherit"> | 
 |  |  |                             {translate('page.map.settings.map.copy.title')} | 
 |  |  |                         </Typography> | 
 |  |  |                     </Grid> | 
 |  |  |                     <Grid item xs={6} sx={{ | 
 |  |  |                         paddingTop: '8px !important', | 
 |  |  |                     }}> | 
 |  |  |                         <Controller | 
 |  |  |                             name="copyDirection" | 
 |  |  |                             control={control} | 
 |  |  |                             render={({ field }) => ( | 
 |  |  |                                 <FormControl fullWidth> | 
 |  |  |                                     <InputLabel> | 
 |  |  |                                         {translate('page.map.settings.map.copy.direction')} | 
 |  |  |                                     </InputLabel> | 
 |  |  |                                     <Select | 
 |  |  |                                         {...field} | 
 |  |  |                                         label={translate('page.map.settings.map.copy.direction')} | 
 |  |  |                                     > | 
 |  |  |                                         <MenuItem value="left"> | 
 |  |  |                                             {translate('page.map.settings.map.copy.left')} | 
 |  |  |                                         </MenuItem> | 
 |  |  |                                         <MenuItem value="right"> | 
 |  |  |                                             {translate('page.map.settings.map.copy.right')} | 
 |  |  |                                         </MenuItem> | 
 |  |  |                                         <MenuItem value="up"> | 
 |  |  |                                             {translate('page.map.settings.map.copy.up')} | 
 |  |  |                                         </MenuItem> | 
 |  |  |                                         <MenuItem value="down"> | 
 |  |  |                                             {translate('page.map.settings.map.copy.down')} | 
 |  |  |                                         </MenuItem> | 
 |  |  |                                     </Select> | 
 |  |  |                                 </FormControl> | 
 |  |  |                             )} | 
 |  |  |                         /> | 
 |  |  |                     </Grid> | 
 |  |  |                     <Grid item xs={6} sx={{ | 
 |  |  |                         paddingTop: '8px !important', | 
 |  |  |                     }}> | 
 |  |  |                         <Controller | 
 |  |  |                             name="copyCount" | 
 |  |  |                             control={control} | 
 |  |  |                             render={({ field }) => ( | 
 |  |  |                                 <TextField | 
 |  |  |                                     {...field} | 
 |  |  |                                     label={translate('page.map.settings.map.copy.direction')} | 
 |  |  |                                 > | 
 |  |  |                                     <MenuItem value="left"> | 
 |  |  |                                         {translate('page.map.settings.map.copy.left')} | 
 |  |  |                                     </MenuItem> | 
 |  |  |                                     <MenuItem value="right"> | 
 |  |  |                                         {translate('page.map.settings.map.copy.right')} | 
 |  |  |                                     </MenuItem> | 
 |  |  |                                     <MenuItem value="up"> | 
 |  |  |                                         {translate('page.map.settings.map.copy.up')} | 
 |  |  |                                     </MenuItem> | 
 |  |  |                                     <MenuItem value="down"> | 
 |  |  |                                         {translate('page.map.settings.map.copy.down')} | 
 |  |  |                                     </MenuItem> | 
 |  |  |                                 </Select> | 
 |  |  |                             </FormControl> | 
 |  |  |                         )} | 
 |  |  |                     /> | 
 |  |  |                 </Grid> | 
 |  |  |                 <Grid item xs={6} sx={{ | 
 |  |  |                     paddingTop: '8px !important', | 
 |  |  |                 }}> | 
 |  |  |                     <Controller | 
 |  |  |                         name="copyCount" | 
 |  |  |                         control={control} | 
 |  |  |                         render={({ field }) => ( | 
 |  |  |                             <TextField | 
 |  |  |                                 {...field} | 
 |  |  |                                 label={translate('page.map.settings.map.copy.count')} | 
 |  |  |                                 type="number" | 
 |  |  |                                 fullWidth | 
 |  |  |                                 inputProps={{ min: 1 }} | 
 |  |  |                             /> | 
 |  |  |                         )} | 
 |  |  |                     /> | 
 |  |  |                 </Grid> | 
 |  |  |                                     label={translate('page.map.settings.map.copy.count')} | 
 |  |  |                                     type="number" | 
 |  |  |                                     fullWidth | 
 |  |  |                                     inputProps={{ min: 1 }} | 
 |  |  |                                 /> | 
 |  |  |                             )} | 
 |  |  |                         /> | 
 |  |  |                     </Grid> | 
 |  |  |                     <Grid item xs={12}> | 
 |  |  |                         <Stack direction="row" spacing={2}> | 
 |  |  |                             <Button variant="contained" color="primary" onClick={() => { | 
 |  |  |                                 setCopyVisible(true); | 
 |  |  |                             }}> | 
 |  |  |                                 {translate('page.map.settings.map.copy.execute')} | 
 |  |  |                             </Button> | 
 |  |  |                             <Button variant="text" color="primary" onClick={() => { | 
 |  |  |                                 if (lastCopiedSprites && lastCopiedSprites.length > 0) { | 
 |  |  |                                     lastCopiedSprites.forEach(copiedSprite => { | 
 |  |  |                                         Tool.getMapContainer().removeChild(copiedSprite); | 
 |  |  |                                     }) | 
 |  |  |                                     setLastCopiedSprites([]); | 
 |  |  |                                 } | 
 |  |  |                             }}> | 
 |  |  |                                 {translate('page.map.settings.map.copy.reverse')} | 
 |  |  |                             </Button> | 
 |  |  |                         </Stack> | 
 |  |  |                     </Grid> | 
 |  |  |  | 
 |  |  |                 {/* more */} | 
 |  |  |                 <Grid item xs={12}> | 
 |  |  |                     <Typography variant="inherit"> | 
 |  |  |                         {translate('page.map.settings.map.more.title')} | 
 |  |  |                     </Typography> | 
 |  |  |                     <Grid item xs={12}> | 
 |  |  |                         <Divider /> | 
 |  |  |                     </Grid> | 
 |  |  |  | 
 |  |  |                     {/* more */} | 
 |  |  |                     <Grid item xs={12}> | 
 |  |  |                         <Typography variant="inherit"> | 
 |  |  |                             {translate('page.map.settings.map.more.title')} | 
 |  |  |                         </Typography> | 
 |  |  |                     </Grid> | 
 |  |  |                     <Grid item xs={12}> | 
 |  |  |                         <Stack direction="row" spacing={2}> | 
 |  |  |                             <Button variant="outlined" color="error" onClick={() => { | 
 |  |  |                                 Tool.getMapContainer().removeChild(sprite); | 
 |  |  |                                 setSpriteSettings(null); | 
 |  |  |                                 Tool.removeSelectedEffect(); | 
 |  |  |                                 reset(); | 
 |  |  |                             }}> | 
 |  |  |                                 {translate('ra.action.delete')} | 
 |  |  |                             </Button> | 
 |  |  |                             {/* <ConfirmButton /> */} | 
 |  |  |                         </Stack> | 
 |  |  |                     </Grid> | 
 |  |  |                 </Grid> | 
 |  |  |                 <Grid item xs={12}> | 
 |  |  |                     <Stack direction="row" spacing={2}> | 
 |  |  |                         <Button variant="outlined" color="error"> | 
 |  |  |                             {translate('ra.action.delete')} | 
 |  |  |                         </Button> | 
 |  |  |                     </Stack> | 
 |  |  |                 </Grid> | 
 |  |  |             </Grid> | 
 |  |  |         </Box> | 
 |  |  |             </Box > | 
 |  |  |  | 
 |  |  |             <CopyDrawer | 
 |  |  |                 open={copyVisible} | 
 |  |  |                 onCancel={() => { | 
 |  |  |                     setCopyVisible(false); | 
 |  |  |                 }} | 
 |  |  |                 width={width} | 
 |  |  |                 sprite={sprite} | 
 |  |  |                 value={{ | 
 |  |  |                     copyDirect: watch('copyDirection'), | 
 |  |  |                     copyCount: watch('copyCount'), | 
 |  |  |                 }} | 
 |  |  |                 handleOnCopy={() => { | 
 |  |  |  | 
 |  |  |                 }} | 
 |  |  |                 setLastCopiedSprites={setLastCopiedSprites} | 
 |  |  |                 setSpriteSettings={setSpriteSettings} | 
 |  |  |             /> | 
 |  |  |         </> | 
 |  |  |     ); | 
 |  |  | }; | 
 |  |  |  |