|  |  |  | 
|---|
|  |  |  | import React, { useEffect } from 'react'; | 
|---|
|  |  |  | import React, { useEffect, useState } from 'react'; | 
|---|
|  |  |  | import { useForm, Controller } from 'react-hook-form'; | 
|---|
|  |  |  | import { | 
|---|
|  |  |  | Box, | 
|---|
|  |  |  | 
|---|
|  |  |  | InputLabel, | 
|---|
|  |  |  | FormControl, | 
|---|
|  |  |  | Stack, | 
|---|
|  |  |  | Divider, | 
|---|
|  |  |  | } from '@mui/material'; | 
|---|
|  |  |  | import MuiInput from '@mui/material/Input'; | 
|---|
|  |  |  | 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, setValue } = useForm({ | 
|---|
|  |  |  | 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, | 
|---|
|  |  |  | // 设置其他字段的初始值 | 
|---|
|  |  |  | 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={1}> | 
|---|
|  |  |  | {/* 位置 */} | 
|---|
|  |  |  | <Grid item xs={12}> | 
|---|
|  |  |  | <Typography variant="button"> | 
|---|
|  |  |  | {translate('page.map.settings.map.base.position')} | 
|---|
|  |  |  | </Typography> | 
|---|
|  |  |  | </Grid> | 
|---|
|  |  |  | <Grid item xs={6}> | 
|---|
|  |  |  | <Controller | 
|---|
|  |  |  | name="x" | 
|---|
|  |  |  | control={control} | 
|---|
|  |  |  | render={({ field }) => ( | 
|---|
|  |  |  | <TextField | 
|---|
|  |  |  | {...field} | 
|---|
|  |  |  | label="X" | 
|---|
|  |  |  | type="number" | 
|---|
|  |  |  | fullWidth | 
|---|
|  |  |  | onChange={(e) => { | 
|---|
|  |  |  | field.onChange(e); | 
|---|
|  |  |  | updateSprite({ ...watchAllFields, x: parseFloat(e.target.value) }); | 
|---|
|  |  |  | }} | 
|---|
|  |  |  | /> | 
|---|
|  |  |  | )} | 
|---|
|  |  |  | /> | 
|---|
|  |  |  | </Grid> | 
|---|
|  |  |  | <Grid item xs={6}> | 
|---|
|  |  |  | <Controller | 
|---|
|  |  |  | name="y" | 
|---|
|  |  |  | control={control} | 
|---|
|  |  |  | render={({ field }) => ( | 
|---|
|  |  |  | <TextField | 
|---|
|  |  |  | {...field} | 
|---|
|  |  |  | label="Y" | 
|---|
|  |  |  | type="number" | 
|---|
|  |  |  | fullWidth | 
|---|
|  |  |  | onChange={(e) => { | 
|---|
|  |  |  | field.onChange(e); | 
|---|
|  |  |  | updateSprite({ ...watchAllFields, y: parseFloat(e.target.value) }); | 
|---|
|  |  |  | }} | 
|---|
|  |  |  | /> | 
|---|
|  |  |  | )} | 
|---|
|  |  |  | /> | 
|---|
|  |  |  | </Grid> | 
|---|
|  |  |  |  | 
|---|
|  |  |  | {/* 缩放 */} | 
|---|
|  |  |  | <Grid item xs={12}> | 
|---|
|  |  |  | <Typography variant="button"> | 
|---|
|  |  |  | {translate('page.map.settings.map.base.scale')} | 
|---|
|  |  |  | </Typography> | 
|---|
|  |  |  | </Grid> | 
|---|
|  |  |  | <Grid item xs={6}> | 
|---|
|  |  |  | <Controller | 
|---|
|  |  |  | name="scaleX" | 
|---|
|  |  |  | control={control} | 
|---|
|  |  |  | render={({ field }) => ( | 
|---|
|  |  |  | <TextField | 
|---|
|  |  |  | {...field} | 
|---|
|  |  |  | label="Scale X" | 
|---|
|  |  |  | type="number" | 
|---|
|  |  |  | fullWidth | 
|---|
|  |  |  | inputProps={{ step: 0.1, min: 0.1, max: 10 }} | 
|---|
|  |  |  | onChange={(e) => { | 
|---|
|  |  |  | field.onChange(e); | 
|---|
|  |  |  | updateSprite({ ...watchAllFields, scaleX: parseFloat(e.target.value) }); | 
|---|
|  |  |  | }} | 
|---|
|  |  |  | /> | 
|---|
|  |  |  | )} | 
|---|
|  |  |  | /> | 
|---|
|  |  |  | </Grid> | 
|---|
|  |  |  | <Grid item xs={6}> | 
|---|
|  |  |  | <Controller | 
|---|
|  |  |  | name="scaleY" | 
|---|
|  |  |  | control={control} | 
|---|
|  |  |  | render={({ field }) => ( | 
|---|
|  |  |  | <TextField | 
|---|
|  |  |  | {...field} | 
|---|
|  |  |  | label="Scale Y" | 
|---|
|  |  |  | type="number" | 
|---|
|  |  |  | fullWidth | 
|---|
|  |  |  | inputProps={{ step: 0.1, min: 0.1, max: 10 }} | 
|---|
|  |  |  | onChange={(e) => { | 
|---|
|  |  |  | field.onChange(e); | 
|---|
|  |  |  | updateSprite({ ...watchAllFields, scaleY: parseFloat(e.target.value) }); | 
|---|
|  |  |  | }} | 
|---|
|  |  |  | /> | 
|---|
|  |  |  | )} | 
|---|
|  |  |  | /> | 
|---|
|  |  |  | </Grid> | 
|---|
|  |  |  |  | 
|---|
|  |  |  | {/* 旋转 */} | 
|---|
|  |  |  | <Grid item xs={12}> | 
|---|
|  |  |  | <Typography variant="button"> | 
|---|
|  |  |  | {translate('page.map.settings.map.base.rotation')} | 
|---|
|  |  |  | </Typography> | 
|---|
|  |  |  | </Grid> | 
|---|
|  |  |  | <Grid item xs={8}> | 
|---|
|  |  |  | <Controller | 
|---|
|  |  |  | name="rotation" | 
|---|
|  |  |  | control={control} | 
|---|
|  |  |  | render={({ field }) => ( | 
|---|
|  |  |  | <Slider | 
|---|
|  |  |  | {...field} | 
|---|
|  |  |  | min={0} | 
|---|
|  |  |  | max={360} | 
|---|
|  |  |  | step={1} | 
|---|
|  |  |  | marks={rotationMarks} | 
|---|
|  |  |  | valueLabelDisplay="auto" | 
|---|
|  |  |  | valueLabelFormat={(value) => `${value}°`} | 
|---|
|  |  |  | onChange={(e, value) => { | 
|---|
|  |  |  | field.onChange(value); | 
|---|
|  |  |  | updateSprite({ ...watchAllFields, rotation: value }); | 
|---|
|  |  |  | }} | 
|---|
|  |  |  | /> | 
|---|
|  |  |  | )} | 
|---|
|  |  |  | /> | 
|---|
|  |  |  | </Grid> | 
|---|
|  |  |  | <Grid item xs={4}> | 
|---|
|  |  |  | <Controller | 
|---|
|  |  |  | name="rotation" | 
|---|
|  |  |  | control={control} | 
|---|
|  |  |  | render={({ field }) => ( | 
|---|
|  |  |  | <TextField | 
|---|
|  |  |  | {...field} | 
|---|
|  |  |  | label={`${translate('page.map.settings.map.base.rotation')} (°)`} | 
|---|
|  |  |  | type="number" | 
|---|
|  |  |  | fullWidth | 
|---|
|  |  |  | inputProps={{ min: 0, max: 360 }} | 
|---|
|  |  |  | onChange={(e) => { | 
|---|
|  |  |  | field.onChange(e); | 
|---|
|  |  |  | updateSprite({ ...watchAllFields, rotation: parseFloat(e.target.value) }); | 
|---|
|  |  |  | }} | 
|---|
|  |  |  | /> | 
|---|
|  |  |  | )} | 
|---|
|  |  |  | /> | 
|---|
|  |  |  | </Grid> | 
|---|
|  |  |  |  | 
|---|
|  |  |  | {/* 复制 */} | 
|---|
|  |  |  | <Grid item xs={12}> | 
|---|
|  |  |  | <Typography variant="button"> | 
|---|
|  |  |  | {translate('page.map.settings.map.copy.title')} | 
|---|
|  |  |  | </Typography> | 
|---|
|  |  |  | </Grid> | 
|---|
|  |  |  | <Grid item xs={6}> | 
|---|
|  |  |  | <Controller | 
|---|
|  |  |  | name="copyDirection" | 
|---|
|  |  |  | control={control} | 
|---|
|  |  |  | render={({ field }) => ( | 
|---|
|  |  |  | <FormControl fullWidth> | 
|---|
|  |  |  | <InputLabel> | 
|---|
|  |  |  | {translate('page.map.settings.map.copy.direction')} | 
|---|
|  |  |  | </InputLabel> | 
|---|
|  |  |  | <Select | 
|---|
|  |  |  | <> | 
|---|
|  |  |  | <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={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}> | 
|---|
|  |  |  | <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="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> | 
|---|
|  |  |  |  | 
|---|
|  |  |  | {/* 提交按钮 */} | 
|---|
|  |  |  | <Grid item xs={12}> | 
|---|
|  |  |  | <Stack direction="row" spacing={2}> | 
|---|
|  |  |  | <Button type="submit" variant="contained" color="primary"> | 
|---|
|  |  |  | {translate('ra.action.confirm')} | 
|---|
|  |  |  | </Button> | 
|---|
|  |  |  | <Button variant="outlined" color="secondary" onClick={() => reset()}> | 
|---|
|  |  |  | {translate('common.action.reset')} | 
|---|
|  |  |  | </Button> | 
|---|
|  |  |  | </Stack> | 
|---|
|  |  |  | {/* 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)) { | 
|---|
|  |  |  | 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> | 
|---|
|  |  |  | </Grid> | 
|---|
|  |  |  |  | 
|---|
|  |  |  | <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.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> | 
|---|
|  |  |  |  | 
|---|
|  |  |  | <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> | 
|---|
|  |  |  | </Box> | 
|---|
|  |  |  | </Box > | 
|---|
|  |  |  |  | 
|---|
|  |  |  | <CopyDrawer | 
|---|
|  |  |  | open={copyVisible} | 
|---|
|  |  |  | onCancel={() => { | 
|---|
|  |  |  | setCopyVisible(false); | 
|---|
|  |  |  | }} | 
|---|
|  |  |  | width={width} | 
|---|
|  |  |  | sprite={sprite} | 
|---|
|  |  |  | value={{ | 
|---|
|  |  |  | copyDirect: watch('copyDirection'), | 
|---|
|  |  |  | copyCount: watch('copyCount'), | 
|---|
|  |  |  | }} | 
|---|
|  |  |  | handleOnCopy={() => { | 
|---|
|  |  |  |  | 
|---|
|  |  |  | }} | 
|---|
|  |  |  | setLastCopiedSprites={setLastCopiedSprites} | 
|---|
|  |  |  | setSpriteSettings={setSpriteSettings} | 
|---|
|  |  |  | /> | 
|---|
|  |  |  | </> | 
|---|
|  |  |  | ); | 
|---|
|  |  |  | }; | 
|---|
|  |  |  |  | 
|---|