diff --git a/CHANGELOG.md b/CHANGELOG.md index 46ef0993b..b60c00068 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Updated Polish localisation. [@ReptiIe](https://github.com/ReptiIe) - Update script branch labels to include the condition logic if there is enough vertical space - Update script branch labels to stay on screen when scrolling through long scripts +- Sprite editor updated to allow canvas min width of 8px with 8px width increments +- When in collision tile drawing mode, actor sprite collision bounding boxes are now also visible ### Fixed diff --git a/src/components/sprites/MetaspriteEditor.tsx b/src/components/sprites/MetaspriteEditor.tsx index 0896382f7..3af0a0858 100644 --- a/src/components/sprites/MetaspriteEditor.tsx +++ b/src/components/sprites/MetaspriteEditor.tsx @@ -118,7 +118,7 @@ const MetaspriteDraggableTile = styled.div` : ""} `; -const SpriteBoundingBox = styled.div` +export const SpriteBoundingBox = styled.div` position: absolute; background: rgba(255, 193, 7, 0.58); box-shadow: 0px 0px 0px 1px rgba(255, 0, 0, 0.2) inset; diff --git a/src/components/sprites/MetaspriteGrid.tsx b/src/components/sprites/MetaspriteGrid.tsx index 2998c3065..ec74a7b51 100644 --- a/src/components/sprites/MetaspriteGrid.tsx +++ b/src/components/sprites/MetaspriteGrid.tsx @@ -19,6 +19,9 @@ const MetaspriteGrid = ({ onClick, children, }: MetaspriteGridProps) => { + // When canvas width is not 8 or a multiple of 16 then + // an offset is needed to align grid lines correctly + const offsetGridX = width % 16 !== 0 && width !== 8 ? `${4 * zoom}px` : "0"; return (
= 8 @@ -75,7 +79,7 @@ const MetaspriteGrid = ({ style={{ position: "relative", width, - transform: `translate3d(${(width / 2 - 8) * zoom}px, ${ + transform: `translate3d(${Math.max(0, width / 2 - 8) * zoom}px, ${ height * zoom }px, 0) scale(${zoom})`, transformOrigin: "top left", diff --git a/src/components/sprites/SpriteEditor.tsx b/src/components/sprites/SpriteEditor.tsx index e5ed257ef..ca5f896d2 100644 --- a/src/components/sprites/SpriteEditor.tsx +++ b/src/components/sprites/SpriteEditor.tsx @@ -610,9 +610,9 @@ export const SpriteEditor = ({ coordinate="w" value={sprite.canvasWidth} placeholder="16" - min={16} + min={8} max={160} - step={16} + step={8} onChange={onChangeCanvasWidth} /> { tile.sliceY, 8, 16, - width / 2 - 8 + tile.x * (tile.flipX ? -1 : 1), + Math.max(0, width / 2 - 8) + tile.x * (tile.flipX ? -1 : 1), height - 16 - tile.y * (tile.flipY ? -1 : 1), 8, 16 diff --git a/src/components/world/ActorView.tsx b/src/components/world/ActorView.tsx index 383d28b4b..b02d1a032 100644 --- a/src/components/world/ActorView.tsx +++ b/src/components/world/ActorView.tsx @@ -1,13 +1,17 @@ import React, { memo, useCallback, useEffect, useState } from "react"; import SpriteSheetCanvas from "./SpriteSheetCanvas"; -import { MIDDLE_MOUSE, TILE_SIZE } from "consts"; -import { actorSelectors } from "store/features/entities/entitiesState"; +import { MIDDLE_MOUSE, TILE_SIZE, TOOL_COLLISIONS } from "consts"; +import { + actorSelectors, + spriteSheetSelectors, +} from "store/features/entities/entitiesState"; import editorActions from "store/features/editor/editorActions"; import styled, { css } from "styled-components"; import { Palette } from "shared/lib/entities/entitiesTypes"; import { useAppDispatch, useAppSelector } from "store/hooks"; import renderActorContextMenu from "./renderActorContextMenu"; import { ContextMenu } from "ui/menu/ContextMenu"; +import { SpriteBoundingBox } from "components/sprites/MetaspriteEditor"; interface ActorViewProps { id: string; @@ -18,16 +22,25 @@ interface ActorViewProps { interface WrapperProps { selected?: boolean; + halfWidth: boolean; } const Wrapper = styled.div` position: absolute; - width: 16px; height: 8px; background-color: rgba(247, 45, 220, 0.5); outline: 1px solid rgba(140, 0, 177, 0.8); -webkit-transform: translate3d(0, 0, 0); + ${(props) => + props.halfWidth + ? css` + width: 8px; + ` + : css` + width: 16px; + `} + ${(props) => props.selected ? css` @@ -59,6 +72,9 @@ const ActorView = memo( const actor = useAppSelector((state) => actorSelectors.selectById(state, id) ); + const sprite = useAppSelector((state) => + spriteSheetSelectors.selectById(state, actor?.spriteSheetId ?? "") + ); const selected = useAppSelector( (state) => state.editor.type === "actor" && @@ -75,6 +91,13 @@ const ActorView = memo( (state.project.present.settings.colorMode === "mixed" && state.project.present.settings.previewAsMono) ); + const boundsWidth = sprite?.boundsWidth || 16; + const boundsHeight = sprite?.boundsHeight || 16; + const boundsX = sprite?.boundsX || 0; + const boundsY = sprite?.boundsY || 0; + const showBoundingBox = useAppSelector( + (state) => state.editor.tool === TOOL_COLLISIONS + ); const onMouseUp = useCallback(() => { dispatch(editorActions.dragActorStop()); @@ -141,6 +164,7 @@ const ActorView = memo( {selected && actor.isPinned && } + {showBoundingBox && ( + + )} )} {contextMenu && ( diff --git a/src/components/world/SpriteSheetCanvas.tsx b/src/components/world/SpriteSheetCanvas.tsx index ece9ce1d8..b715d1b7d 100644 --- a/src/components/world/SpriteSheetCanvas.tsx +++ b/src/components/world/SpriteSheetCanvas.tsx @@ -80,7 +80,7 @@ const SpriteSheetCanvas = ({ offsetPosition ? { top: -sprite.canvasHeight + 8, - left: 8 - sprite.canvasWidth / 2, + left: Math.min(0, 8 - sprite.canvasWidth / 2), } : undefined }