inverting touch point
Summary:
This is a continuation of solving this issue, which was partially solved here. The PR introduces calculating matrix inverse that is optimized for 4x4 affine transformations. It's divided into three main parts: calculating determinant inverse, 3x3 matrix inverse, and translation inverse. The 3x3 matrix inverse calculation algorithm is based on David G. Simpson's implementation from Nasa https://caps.gsfc.nasa.gov/simpson/software/m33inv_f90.txt.
For now I've removed the part of the code that checks specifically for vertical and horizontal transformation, but I have an idea to bring it back in the Invert function, which could speed up in these cases (I think we can do the same for rotations).
Currently, it's not possible to click on View outside of its parent bounds. I can add the check that will traverse down the tree if the component has any overflowing children.
Should I close my previous draft to this issue?
Cc: @realsoelynn
Changelog:
[IOS][FIXED] - inverting touch point in findNodeAtPoint
Test Plan:
extended examples from this reproducer: https://github.com/realsoelynn/rn-inspectortools-transform-related-reproducer
import React from 'react';
import type {PropsWithChildren} from 'react';
import {
Pressable,
SafeAreaView,
ScrollView,
StyleSheet,
Text,
View,
} from 'react-native';
type SectionProps = PropsWithChildren<{
title: string;
}>;
function Section({children, title}: SectionProps): React.JSX.Element {
return (
<View style={styles.sectionContainer}>
<Text style={styles.sectionTitle}>{title}</Text>
<View style={{backgroundColor: '#808080'}}>{children}</View>
</View>
);
}
type ItemProps = PropsWithChildren<{
title: string;
}>;
function Item({title}: ItemProps): React.JSX.Element {
return (
<Pressable
style={styles.item}
onPress={() => console.log(title + ' pressed.')}>
<Text>{title}</Text>
</Pressable>
);
}
function App(): React.JSX.Element {
return (
<SafeAreaView>
<ScrollView>
<Section title="Nested Transform Example">
<View
style={{
transform: [{translateX: 100}, {rotate: '90deg'}],
width: '200',
}}>
<View
style={{
transform: [{scaleY: -1}],
}}>
<Item title="Item 1" />
<Item title="Item 2" />
<Item title="Item 3" />
</View>
</View>
</Section>
<Section title="Rotation Transform Example">
<View
style={{
transform: [{rotate: '45deg'}],
}}>
<Item title="Item 1" />
<Item title="Item 2" />
<Item title="Item 3" />
</View>
</Section>
<Section title="Scale Transform Example">
<View
style={{
transform: [{scale: 1.2}],
}}>
<Item title="Item 1" />
<Item title="Item 2" />
<Item title="Item 3" />
</View>
</Section>
<Section title="Translate X Transform Example">
<View
style={{
transform: [{translateX: 100}],
}}>
<Item title="Item 1" />
<Item title="Item 2" />
<Item title="Item 3" />
</View>
</Section>
<Section title="Translate Y Transform Example">
<View
style={{
transform: [{translateY: 30}],
}}>
<Item title="Item 1" />
<Item title="Item 2" />
<Item title="Item 3" />
</View>
</Section>
<Section title="Skew Transform Example">
<View
style={{
transform: [{skewX: '20deg'}, {skewY: '20deg'}],
}}>
<Item title="Item 1" />
<Item title="Item 2" />
<Item title="Item 3" />
</View>
</Section>
<Section title="Projection Transform Example">
<View
style={{
transform: [{perspective: 400}, {rotateY: '50deg'}],
}}>
<Item title="Item 1" />
<Item title="Item 2" />
<Item title="Item 3" />
</View>
</Section>
<Section title="Inverted ScrollView Example">
<ScrollView
contentInsetAdjustmentBehavior="automatic"
style={{
transform: [{scaleY: -1}],
}}>
<Item title="Item 1" />
<Item title="Item 2" />
<Item title="Item 3" />
</ScrollView>
</Section>
<Section title="Inverted Parent View Example">
<View
style={{
transform: [{scaleY: -1}],
}}>
<Item title="Item 1" />
<Item title="Item 2" />
<Item title="Item 3" />
</View>
</Section>
<Section title="Double Inversion Example">
<View
style={{
transform: [{rotateY: '180deg'}],
}}>
<View
style={{
transform: [{scaleY: -1}],
}}>
<Item title="Item 1" />
<Item title="Item 2" />
<Item title="Item 3" />
</View>
</View>
</Section>
</ScrollView>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
sectionContainer: {
marginTop: 32,
paddingHorizontal: 24,
},
sectionTitle: {
fontSize: 24,
fontWeight: '600',
},
item: {
backgroundColor: '#f9c2ff',
padding: 20,
marginVertical: 8,
marginHorizontal: 16,
width: '50%',
},
sectionDescription: {
marginTop: 8,
fontSize: 18,
fontWeight: '400',
},
highlight: {
fontWeight: '700',
},
});
export default App;