From 59a118539ee5067034fa46f363eea7a8656cea6e Mon Sep 17 00:00:00 2001
From: AlexandreSi <32449369+AlexandreSi@users.noreply.github.com>
Date: Mon, 23 Sep 2024 16:22:33 +0200
Subject: [PATCH] Make rectangular selection possible in instance properties
editor mobile
---
.../CompactInstancePropertiesEditor/index.js | 12 ++-
.../src/InstancesEditor/TileSetVisualizer.js | 86 +++++++++++++------
2 files changed, 70 insertions(+), 28 deletions(-)
diff --git a/newIDE/app/src/InstancesEditor/CompactInstancePropertiesEditor/index.js b/newIDE/app/src/InstancesEditor/CompactInstancePropertiesEditor/index.js
index 499d8ec8ca12..659c93b4db77 100644
--- a/newIDE/app/src/InstancesEditor/CompactInstancePropertiesEditor/index.js
+++ b/newIDE/app/src/InstancesEditor/CompactInstancePropertiesEditor/index.js
@@ -15,7 +15,7 @@ import IconButton from '../../UI/IconButton';
import { Line, Column, Spacer, marginsSize } from '../../UI/Grid';
import Text from '../../UI/Text';
import { type UnsavedChanges } from '../../MainFrame/UnsavedChangesContext';
-import ScrollView from '../../UI/ScrollView';
+import ScrollView, { type ScrollViewInterface } from '../../UI/ScrollView';
import EventsRootVariablesFinder from '../../Utils/EventsRootVariablesFinder';
import VariablesList, {
type HistoryHandler,
@@ -95,7 +95,7 @@ const CompactInstancePropertiesEditor = ({
onSelectTileMapTile,
}: Props) => {
const forceUpdate = useForceUpdate();
-
+ const scrollViewRef = React.useRef(null);
const instance = instances[0];
/**
* TODO: multiple instances support for variables list. Expected behavior should be:
@@ -105,6 +105,12 @@ const CompactInstancePropertiesEditor = ({
*/
const shouldDisplayVariablesList = instances.length === 1;
+ const onScrollY = React.useCallback(deltaY => {
+ if (scrollViewRef.current) {
+ scrollViewRef.current.scrollBy(deltaY);
+ }
+ }, []);
+
const { object, instanceSchema } = React.useMemo<{|
object?: gdObject,
instanceSchema?: Schema,
@@ -220,6 +226,7 @@ const CompactInstancePropertiesEditor = ({
scope="scene-editor-instance-properties"
>
diff --git a/newIDE/app/src/InstancesEditor/TileSetVisualizer.js b/newIDE/app/src/InstancesEditor/TileSetVisualizer.js
index ec916ad0a817..758837c7acc1 100644
--- a/newIDE/app/src/InstancesEditor/TileSetVisualizer.js
+++ b/newIDE/app/src/InstancesEditor/TileSetVisualizer.js
@@ -30,6 +30,7 @@ const styles = {
position: 'relative',
display: 'flex',
overflow: 'auto',
+ touchAction: 'none',
},
atlasImage: { flex: 1, imageRendering: 'pixelated' },
icon: { fontSize: 18 },
@@ -217,6 +218,7 @@ type Props = {|
e: SyntheticEvent,
atlasResourceName: string
) => void,
+ onScrollY: number => void,
|};
const TileSetVisualizer = ({
@@ -229,6 +231,7 @@ const TileSetVisualizer = ({
showPaintingToolbar,
interactive,
onAtlasImageLoaded,
+ onScrollY,
}: Props) => {
const forceUpdate = useForceUpdate();
const atlasResourceName = objectConfiguration
@@ -278,9 +281,7 @@ const TileSetVisualizer = ({
x: number,
y: number,
|}>(null);
- const [shouldCancelClick, setShouldCancelClick] = React.useState(
- false
- );
+ const [isLongTouch, setIsLongTouch] = React.useState(false);
const tooltipDisplayTimeoutId = React.useRef(null);
const [
rectangularSelectionTilePreview,
@@ -316,7 +317,6 @@ const TileSetVisualizer = ({
const displayTileIdTooltip = React.useCallback(
(e: ClientCoordinates) => {
- setShouldCancelClick(true);
if (!displayedTileSize || isBadlyConfigured) return;
const imageCoordinates = getImageCoordinatesFromPointerEvent(e);
@@ -341,7 +341,15 @@ const TileSetVisualizer = ({
[displayedTileSize, columnCount, rowCount, isBadlyConfigured]
);
- const longTouchProps = useLongTouch(displayTileIdTooltip);
+ const handleLongTouch = React.useCallback(
+ (e: ClientCoordinates) => {
+ setIsLongTouch(true);
+ displayTileIdTooltip(e);
+ },
+ [displayTileIdTooltip]
+ );
+
+ const longTouchProps = useLongTouch(handleLongTouch, {doNotCancelOnScroll: true});
React.useEffect(
() => {
@@ -356,7 +364,12 @@ const TileSetVisualizer = ({
(event: PointerEvent) => {
if (isBadlyConfigured) return;
if (event.pointerType === 'touch') {
- setTouchStartCoordinates({ x: event.pageX, y: event.pageY });
+ const coordinates = getImageCoordinatesFromPointerEvent(event);
+ if (!coordinates) return;
+ setTouchStartCoordinates({
+ x: coordinates.mouseX,
+ y: coordinates.mouseY,
+ });
}
const imageCoordinates = getImageCoordinatesFromPointerEvent(event);
if (!imageCoordinates) return;
@@ -374,11 +387,33 @@ const TileSetVisualizer = ({
isBadlyConfigured ||
!clickStartCoordinates ||
!displayedTileSize ||
- (!allowMultipleSelection && !allowRectangleSelection) ||
- event.pointerType === 'touch'
+ (!allowMultipleSelection && !allowRectangleSelection)
) {
return;
}
+
+ let startCoordinates = clickStartCoordinates;
+
+ const isTouchDevice = event.pointerType === 'touch';
+
+ if (isTouchDevice) {
+ if (!touchStartCoordinates) return;
+
+ if (isLongTouch) {
+ startCoordinates = touchStartCoordinates;
+ } else {
+ const coordinates = getImageCoordinatesFromPointerEvent(event);
+ if (!coordinates) return;
+ if (tilesetContainerRef.current) {
+ const deltaY = -event.movementY;
+ const deltaX =
+ touchStartCoordinates.x - coordinates.mouseXWithoutScrollLeft;
+ tilesetContainerRef.current.scrollLeft = deltaX;
+ onScrollY(deltaY);
+ }
+ return;
+ }
+ }
const imageCoordinates = getImageCoordinatesFromPointerEvent(event);
if (!imageCoordinates) return;
@@ -389,10 +424,11 @@ const TileSetVisualizer = ({
rowCount,
displayedTileSize,
});
+
const { x: startX, y: startY } = getGridCoordinatesFromPointerCoordinates(
{
- pointerX: clickStartCoordinates.x,
- pointerY: clickStartCoordinates.y,
+ pointerX: startCoordinates.x,
+ pointerY: startCoordinates.y,
columnCount,
rowCount,
displayedTileSize,
@@ -416,6 +452,9 @@ const TileSetVisualizer = ({
allowMultipleSelection,
allowRectangleSelection,
clickStartCoordinates,
+ isLongTouch,
+ touchStartCoordinates,
+ onScrollY,
]
);
@@ -423,21 +462,15 @@ const TileSetVisualizer = ({
(event: PointerEvent) => {
try {
if (!displayedTileSize || isBadlyConfigured) return;
- if (shouldCancelClick) {
- setShouldCancelClick(false);
- return;
- }
- let isTouchDevice = false;
+ const isTouchDevice = event.pointerType === 'touch';
+ let startCoordinates = clickStartCoordinates;
- if (event.pointerType === 'touch') {
- isTouchDevice = true;
- if (
- !touchStartCoordinates ||
- Math.abs(event.pageX - touchStartCoordinates.x) > 30 ||
- Math.abs(event.pageY - touchStartCoordinates.y) > 30
- ) {
+ if (isTouchDevice) {
+ if (!isLongTouch || !touchStartCoordinates) {
return;
+ } else {
+ startCoordinates = touchStartCoordinates;
}
}
@@ -451,14 +484,14 @@ const TileSetVisualizer = ({
rowCount,
displayedTileSize,
});
- if (!clickStartCoordinates) return;
+ if (!startCoordinates) return;
const {
x: startX,
y: startY,
} = getGridCoordinatesFromPointerCoordinates({
- pointerX: clickStartCoordinates.x,
- pointerY: clickStartCoordinates.y,
+ pointerX: startCoordinates.x,
+ pointerY: startCoordinates.y,
columnCount,
rowCount,
displayedTileSize,
@@ -525,6 +558,7 @@ const TileSetVisualizer = ({
setClickStartCoordinates(null);
setRectangularSelectionTilePreview(null);
setTouchStartCoordinates(null);
+ setIsLongTouch(false);
}
},
[
@@ -539,7 +573,7 @@ const TileSetVisualizer = ({
allowMultipleSelection,
allowRectangleSelection,
clickStartCoordinates,
- shouldCancelClick,
+ isLongTouch,
touchStartCoordinates,
]
);