| | |
| | | MenuItem, |
| | | InputLabel, |
| | | FormControl, |
| | | FormHelperText, |
| | | Checkbox, |
| | | FormControlLabel, |
| | | Stack, |
| | | Divider, |
| | | } from '@mui/material'; |
| | | import MuiInput from '@mui/material/Input'; |
| | | import { styled } from '@mui/material/styles'; |
| | | import { useTranslate } from 'react-admin'; |
| | | |
| | | const Input = styled(MuiInput)` |
| | | width: 42px; |
| | | `; |
| | | |
| | | const MapSettings = (props) => { |
| | | const { sprite, onSubmit } = props; |
| | | const translate = useTranslate(); |
| | | |
| | | const { control, handleSubmit, reset, watch, setValue } = useForm({ |
| | | const { control, handleSubmit, reset, watch } = useForm({ |
| | | defaultValues: { |
| | | x: sprite?.position.x || 0, |
| | | y: sprite?.position.y || 0, |
| | |
| | | }, |
| | | }); |
| | | |
| | | // 监听表单值的变化 |
| | | // 监听所有字段的变化 |
| | | const watchAllFields = watch(); |
| | | |
| | | useEffect(() => { |
| | |
| | | } |
| | | }; |
| | | |
| | | // 旋转滑块的刻度 |
| | | 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: 2 }}> |
| | | <Box component="form" onSubmit={handleSubmit(onFormSubmit)} noValidate sx={{ mt: 0 }}> |
| | | <Grid container spacing={2}> |
| | | {/* 位置 */} |
| | | <Grid item xs={12}> |
| | | <Typography variant="h6">{translate('map.settings.position')}</Typography> |
| | | <Typography variant="inherit"> |
| | | {translate('page.map.settings.map.base.position')} |
| | | </Typography> |
| | | </Grid> |
| | | <Grid item xs={6}> |
| | | <Grid item xs={6} pt={0} sx={{ |
| | | paddingTop: '8px !important', |
| | | paddingLeft: '8px !important', |
| | | }}> |
| | | <Controller |
| | | name="x" |
| | | control={control} |
| | |
| | | type="number" |
| | | fullWidth |
| | | onChange={(e) => { |
| | | const value = parseFloat(e.target.value); |
| | | field.onChange(e); |
| | | updateSprite({ ...watchAllFields, x: parseFloat(e.target.value) }); |
| | | if (!isNaN(value)) { |
| | | updateSprite({ ...watchAllFields, x: value }); |
| | | } |
| | | }} |
| | | /> |
| | | )} |
| | | /> |
| | | </Grid> |
| | | <Grid item xs={6}> |
| | | <Grid item xs={6} sx={{ |
| | | paddingTop: '8px !important', |
| | | paddingLeft: '8px !important', |
| | | }}> |
| | | <Controller |
| | | name="y" |
| | | control={control} |
| | |
| | | type="number" |
| | | fullWidth |
| | | onChange={(e) => { |
| | | const value = parseFloat(e.target.value); |
| | | field.onChange(e); |
| | | updateSprite({ ...watchAllFields, y: parseFloat(e.target.value) }); |
| | | if (!isNaN(value)) { |
| | | updateSprite({ ...watchAllFields, y: value }); |
| | | } |
| | | }} |
| | | /> |
| | | )} |
| | |
| | | |
| | | {/* 缩放 */} |
| | | <Grid item xs={12}> |
| | | <Typography variant="h6">{translate('map.settings.scale')}</Typography> |
| | | <Typography variant="inherit"> |
| | | {translate('page.map.settings.map.base.scale')} |
| | | </Typography> |
| | | </Grid> |
| | | <Grid item xs={6}> |
| | | <Grid item xs={6} sx={{ |
| | | paddingTop: '8px !important', |
| | | paddingLeft: '8px !important', |
| | | }}> |
| | | <Controller |
| | | name="scaleX" |
| | | control={control} |
| | | render={({ field }) => ( |
| | | <TextField |
| | | {...field} |
| | | label="Scale X" |
| | | 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); |
| | | updateSprite({ ...watchAllFields, scaleX: parseFloat(e.target.value) }); |
| | | if (!isNaN(value)) { |
| | | updateSprite({ ...watchAllFields, scaleX: value }); |
| | | } |
| | | }} |
| | | /> |
| | | )} |
| | | /> |
| | | </Grid> |
| | | <Grid item xs={6}> |
| | | <Grid item xs={6} sx={{ |
| | | paddingTop: '8px !important', |
| | | paddingLeft: '8px !important', |
| | | }}> |
| | | <Controller |
| | | name="scaleY" |
| | | control={control} |
| | | render={({ field }) => ( |
| | | <TextField |
| | | {...field} |
| | | label="Scale Y" |
| | | 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); |
| | | updateSprite({ ...watchAllFields, scaleY: parseFloat(e.target.value) }); |
| | | if (!isNaN(value)) { |
| | | updateSprite({ ...watchAllFields, scaleY: value }); |
| | | } |
| | | }} |
| | | /> |
| | | )} |
| | |
| | | |
| | | {/* 旋转 */} |
| | | <Grid item xs={12}> |
| | | <Typography variant="h6">{translate('map.settings.rotation')}</Typography> |
| | | <Typography variant="inherit"> |
| | | {translate('page.map.settings.map.base.rotation')} |
| | | </Typography> |
| | | </Grid> |
| | | <Grid item xs={12}> |
| | | <Controller |
| | | name="rotation" |
| | | control={control} |
| | | render={({ field }) => ( |
| | | <Slider |
| | | {...field} |
| | | min={0} |
| | | max={360} |
| | | step={1} |
| | | valueLabelDisplay="auto" |
| | | onChange={(e, value) => { |
| | | field.onChange(value); |
| | | updateSprite({ ...watchAllFields, rotation: value }); |
| | | }} |
| | | <Box display="flex" alignItems="center"> |
| | | <Box flex={1} mr={2}> |
| | | <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 width={80}> |
| | | <Controller |
| | | name="rotation" |
| | | control={control} |
| | | render={({ field }) => ( |
| | | <TextField |
| | | {...field} |
| | | label="" |
| | | type="number" |
| | | fullWidth |
| | | inputProps={{ min: 0, max: 360 }} |
| | | onChange={(e) => { |
| | | const value = parseFloat(e.target.value); |
| | | if (!isNaN(value)) { |
| | | field.onChange(value); |
| | | updateSprite({ ...watchAllFields, rotation: value }); |
| | | } |
| | | }} |
| | | /> |
| | | )} |
| | | /> |
| | | </Box> |
| | | </Box> |
| | | </Grid> |
| | | <Grid item xs={12}> |
| | | <Divider /> |
| | | </Grid> |
| | | |
| | | {/* 复制 */} |
| | | <Grid item xs={12}> |
| | | <Typography variant="h6">{translate('map.settings.copy')}</Typography> |
| | | <Typography variant="inherit"> |
| | | {translate('page.map.settings.map.copy.title')} |
| | | </Typography> |
| | | </Grid> |
| | | <Grid item xs={6}> |
| | | <Grid item xs={6} sx={{ |
| | | paddingTop: '8px !important', |
| | | paddingLeft: '8px !important', |
| | | }}> |
| | | <Controller |
| | | name="copyDirection" |
| | | control={control} |
| | | render={({ field }) => ( |
| | | <FormControl fullWidth> |
| | | <InputLabel>{translate('map.settings.copyDirection')}</InputLabel> |
| | | <Select {...field} label={translate('map.settings.copyDirection')}> |
| | | <MenuItem value="left">{translate('map.settings.left')}</MenuItem> |
| | | <MenuItem value="right">{translate('map.settings.right')}</MenuItem> |
| | | <MenuItem value="up">{translate('map.settings.up')}</MenuItem> |
| | | <MenuItem value="down">{translate('map.settings.down')}</MenuItem> |
| | | <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}> |
| | | <Grid item xs={6} sx={{ |
| | | paddingTop: '8px !important', |
| | | paddingLeft: '8px !important', |
| | | }}> |
| | | <Controller |
| | | name="copyCount" |
| | | control={control} |
| | | render={({ field }) => ( |
| | | <TextField |
| | | {...field} |
| | | label={translate('map.settings.copyCount')} |
| | | label={translate('page.map.settings.map.copy.count')} |
| | | type="number" |
| | | fullWidth |
| | | inputProps={{ min: 1 }} |
| | |
| | | <Grid item xs={12}> |
| | | <Stack direction="row" spacing={2}> |
| | | <Button type="submit" variant="contained" color="primary"> |
| | | {translate('common.submit')} |
| | | {translate('ra.action.confirm')} |
| | | </Button> |
| | | <Button variant="outlined" color="secondary" onClick={() => reset()}> |
| | | {translate('common.reset')} |
| | | {translate('common.action.reset')} |
| | | </Button> |
| | | </Stack> |
| | | </Grid> |