Compare commits

...

4 Commits

Author SHA1 Message Date
AlexandreSi
1f9d7860cf Improve message 2021-12-10 17:59:18 +01:00
AlexandreSi
83d6c7a2a2 Move warning to Hint file 2021-12-10 16:21:30 +01:00
AlexandreSi
f7b0cfab1f Add a more precise check on object having platformer behavior 2021-12-10 16:01:04 +01:00
AlexandreSi
7e6a277335 Add warning when editing the collision mask of a platformer object 2021-12-10 15:28:01 +01:00
2 changed files with 102 additions and 61 deletions

View File

@@ -149,3 +149,8 @@ export const getExtraInstructionInformation = (type: string): ?Hint => {
return null; return null;
}; };
export const getWarningAboutPlatformerCollisionMaskEditing = (): ?Hint => ({
kind: 'warning',
message: t`You currently use a custom collision mask for an object that has the Platformer behavior. A platformer with a custom collision mask could experience issues if it is flipped horizontally near a wall. To avoid that, make sure your collision mask does not move when flipping it by centering it.`,
});

View File

@@ -1,6 +1,8 @@
// @flow // @flow
import { Trans } from '@lingui/macro'; import { Trans } from '@lingui/macro';
import { I18n } from '@lingui/react';
import React from 'react'; import React from 'react';
import every from 'lodash/every';
import FlatButton from '../../../../UI/FlatButton'; import FlatButton from '../../../../UI/FlatButton';
import EmptyMessage from '../../../../UI/EmptyMessage'; import EmptyMessage from '../../../../UI/EmptyMessage';
import { Line, Column } from '../../../../UI/Grid'; import { Line, Column } from '../../../../UI/Grid';
@@ -15,7 +17,6 @@ import {
} from '../Utils/SpriteObjectHelper'; } from '../Utils/SpriteObjectHelper';
import SpriteSelector from '../Utils/SpriteSelector'; import SpriteSelector from '../Utils/SpriteSelector';
import Window from '../../../../Utils/Window'; import Window from '../../../../Utils/Window';
import every from 'lodash/every';
import ResourcesLoader from '../../../../ResourcesLoader'; import ResourcesLoader from '../../../../ResourcesLoader';
import useForceUpdate from '../../../../Utils/UseForceUpdate'; import useForceUpdate from '../../../../Utils/UseForceUpdate';
import EditorMosaic, { import EditorMosaic, {
@@ -24,6 +25,8 @@ import EditorMosaic, {
} from '../../../../UI/EditorMosaic'; } from '../../../../UI/EditorMosaic';
import { useResponsiveWindowWidth } from '../../../../UI/Reponsive/ResponsiveWindowMeasurer'; import { useResponsiveWindowWidth } from '../../../../UI/Reponsive/ResponsiveWindowMeasurer';
import Background from '../../../../UI/Background'; import Background from '../../../../UI/Background';
import AlertMessage from '../../../../UI/AlertMessage';
import { getWarningAboutPlatformerCollisionMaskEditing } from '../../../../Hints';
const gd: libGDevelop = global.gd; const gd: libGDevelop = global.gd;
const horizontalMosaicNodes: EditorMosaicNode = { const horizontalMosaicNodes: EditorMosaicNode = {
@@ -75,6 +78,21 @@ const CollisionMasksEditor = (props: Props) => {
spriteIndex spriteIndex
); );
const objectHasPlatformerBehavior = props.object
.getAllBehaviorNames()
.toJSArray()
.map(behaviorName => props.object.getBehavior(behaviorName))
.some(
behavior =>
behavior.getTypeName() === 'PlatformBehavior::PlatformerObjectBehavior'
);
const warningAboutPlatformerCollisionMaskEditing =
!!sprite &&
!sprite.isCollisionMaskAutomatic() &&
objectHasPlatformerBehavior
? getWarningAboutPlatformerCollisionMaskEditing()
: null;
const updateCollisionMasks = React.useCallback( const updateCollisionMasks = React.useCallback(
() => { () => {
if (animation && sprite) { if (animation && sprite) {
@@ -215,68 +233,86 @@ const CollisionMasksEditor = (props: Props) => {
type: 'secondary', type: 'secondary',
noTitleBar: true, noTitleBar: true,
renderEditor: () => ( renderEditor: () => (
<Background> <I18n>
<Line> {({ i18n }) => (
<Column expand> <Background>
<SpriteSelector <Line>
spriteObject={spriteObject} <Column expand>
animationIndex={animationIndex} <SpriteSelector
directionIndex={directionIndex} spriteObject={spriteObject}
spriteIndex={spriteIndex} animationIndex={animationIndex}
chooseAnimation={chooseAnimation} directionIndex={directionIndex}
chooseDirection={chooseDirection} spriteIndex={spriteIndex}
chooseSprite={chooseSprite} chooseAnimation={chooseAnimation}
sameForAllAnimations={sameCollisionMasksForAnimations} chooseDirection={chooseDirection}
sameForAllSprites={sameCollisionMasksForSprites} chooseSprite={chooseSprite}
setSameForAllAnimations={setSameCollisionMasksForAllAnimations} sameForAllAnimations={sameCollisionMasksForAnimations}
setSameForAllSprites={setSameCollisionMasksForAllSprites} sameForAllSprites={sameCollisionMasksForSprites}
setSameForAllAnimationsLabel={ setSameForAllAnimations={
<Trans>Share same collision masks for all animations</Trans> setSameCollisionMasksForAllAnimations
} }
setSameForAllSpritesLabel={ setSameForAllSprites={setSameCollisionMasksForAllSprites}
<Trans> setSameForAllAnimationsLabel={
Share same collision masks for all sprites of this animation <Trans>
</Trans> Share same collision masks for all animations
} </Trans>
/> }
</Column> setSameForAllSpritesLabel={
</Line> <Trans>
{!!sprite && !sprite.isCollisionMaskAutomatic() && ( Share same collision masks for all sprites of this
<React.Fragment> animation
<PolygonsList </Trans>
polygons={sprite.getCustomCollisionMask()} }
onPolygonsUpdated={updateCollisionMasks} />
restoreCollisionMask={() => onSetCollisionMaskAutomatic(true)} </Column>
spriteWidth={spriteWidth}
spriteHeight={spriteHeight}
/>
</React.Fragment>
)}
{!!sprite && sprite.isCollisionMaskAutomatic() && (
<React.Fragment>
<EmptyMessage>
<Trans>
This sprite uses the default collision mask, a rectangle that
is as large as the sprite.
</Trans>
</EmptyMessage>
<Line justifyContent="center">
<FlatButton
label={<Trans>Use a custom collision mask</Trans>}
primary={false}
onClick={() => onSetCollisionMaskAutomatic(false)}
/>
</Line> </Line>
</React.Fragment> {!!sprite && !sprite.isCollisionMaskAutomatic() && (
<React.Fragment>
<PolygonsList
polygons={sprite.getCustomCollisionMask()}
onPolygonsUpdated={updateCollisionMasks}
restoreCollisionMask={() =>
onSetCollisionMaskAutomatic(true)
}
spriteWidth={spriteWidth}
spriteHeight={spriteHeight}
/>
</React.Fragment>
)}
{!!sprite && sprite.isCollisionMaskAutomatic() && (
<React.Fragment>
<EmptyMessage>
<Trans>
This sprite uses the default collision mask, a rectangle
that is as large as the sprite.
</Trans>
</EmptyMessage>
<Line justifyContent="center">
<FlatButton
label={<Trans>Use a custom collision mask</Trans>}
primary={false}
onClick={() => onSetCollisionMaskAutomatic(false)}
/>
</Line>
</React.Fragment>
)}
{warningAboutPlatformerCollisionMaskEditing && (
<AlertMessage
kind={warningAboutPlatformerCollisionMaskEditing.kind}
>
{i18n._(warningAboutPlatformerCollisionMaskEditing.message)}
</AlertMessage>
)}
{!sprite && (
<EmptyMessage>
<Trans>
Choose an animation and frame to edit the collision masks
</Trans>
</EmptyMessage>
)}
</Background>
)} )}
{!sprite && ( </I18n>
<EmptyMessage>
<Trans>
Choose an animation and frame to edit the collision masks
</Trans>
</EmptyMessage>
)}
</Background>
), ),
}, },
}; };