-
Notifications
You must be signed in to change notification settings - Fork 24.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Fabric] Fixes findNodeAtPoint when views were inverted #45519
[Fabric] Fixes findNodeAtPoint when views were inverted #45519
Conversation
@realsoelynn has imported this pull request. If you are a Meta employee, you can view this diff on Phabricator. |
Thank you so much for quickly looking into the fix for this Since this is relying on scaleX and scaleY, it will have issue when rotate is involved. (I added a new test case in the reproducer app as shown in the screenshot) I am thinking of consolidating this |
I'm not familiar with measurement, will find some time to try to figure it out :) |
@realsoelynn Hi, sorry I have no solution to consolidate them right now. But I tried to fix your rotated repro demo :) . |
@realsoelynn has imported this pull request. If you are a Meta employee, you can view this diff on Phabricator. |
C++ Test for findNodeAtPoint Just dumping this test case i wrote a while back. Please help me add to the PR TEST(FindNodeAtPointTest, invertedList) {
auto builder = simpleComponentBuilder();
// clang-format off
auto element =
Element<ScrollViewShadowNode>()
.props([] {
auto sharedProps = std::make_shared<ScrollViewProps>();
sharedProps->transform = Transform::VerticalInversion();
return sharedProps;
})
.tag(1)
.finalize([](ScrollViewShadowNode &shadowNode){
auto layoutMetrics = EmptyLayoutMetrics;
layoutMetrics.frame.size = {100, 200};
shadowNode.setLayoutMetrics(layoutMetrics);
})
.children({
Element<ViewShadowNode>()
.tag(2)
.finalize([](ViewShadowNode &shadowNode){
auto layoutMetrics = EmptyLayoutMetrics;
layoutMetrics.frame.origin = {0, 0};
layoutMetrics.frame.size = {100, 100};
shadowNode.setLayoutMetrics(layoutMetrics);
}),
Element<ViewShadowNode>()
.tag(3)
.finalize([](ViewShadowNode &shadowNode){
auto layoutMetrics = EmptyLayoutMetrics;
layoutMetrics.frame.origin = {0, 100};
layoutMetrics.frame.size = {100, 100};
shadowNode.setLayoutMetrics(layoutMetrics);
})
});
// clang-format on
auto parentShadowNode = builder.build(element);
EXPECT_EQ(
LayoutableShadowNode::findNodeAtPoint(parentShadowNode, {10, 10})
->getTag(),
3);
EXPECT_EQ(
LayoutableShadowNode::findNodeAtPoint(parentShadowNode, {10, 105})
->getTag(),
2);
} |
@zhongwuzw Please take a look at this other author PR #45571 Your current solution handled perfectly for horizontal and vertical inversion. But, we want to to be able to handle different type of rotation transformation. #45571 I don't agree with the Inversion check in that PR. But, the added new Point transformation function has the right idea to solve rotational transform Cc: @coado |
@realsoelynn Is there any way to run cpp tests on emulator locally? |
Do you mean this inversion check? |
Maybe we can combine the two PRs: one for a quick path to handle horizontal and vertical inversion, and another for a transform fallback to matrix inversion calculation ? |
I mean |
@zhongwuzw yep. do you mind pulling in @coado commit to this PR? |
bool Transform::inv() { | ||
if (*this == Transform::Identity()) { | ||
return true; | ||
} | ||
|
||
double inv[16], det; | ||
int i; | ||
auto m = this->matrix; | ||
|
||
inv[0] = m[5] * m[10] * m[15] - m[5] * m[11] * m[14] - m[9] * m[6] * m[15] + | ||
m[9] * m[7] * m[14] + m[13] * m[6] * m[11] - m[13] * m[7] * m[10]; | ||
|
||
inv[4] = -m[4] * m[10] * m[15] + m[4] * m[11] * m[14] + m[8] * m[6] * m[15] - | ||
m[8] * m[7] * m[14] - m[12] * m[6] * m[11] + m[12] * m[7] * m[10]; | ||
|
||
inv[8] = m[4] * m[9] * m[15] - m[4] * m[11] * m[13] - m[8] * m[5] * m[15] + | ||
m[8] * m[7] * m[13] + m[12] * m[5] * m[11] - m[12] * m[7] * m[9]; | ||
|
||
inv[12] = -m[4] * m[9] * m[14] + m[4] * m[10] * m[13] + m[8] * m[5] * m[14] - | ||
m[8] * m[6] * m[13] - m[12] * m[5] * m[10] + m[12] * m[6] * m[9]; | ||
|
||
inv[1] = -m[1] * m[10] * m[15] + m[1] * m[11] * m[14] + m[9] * m[2] * m[15] - | ||
m[9] * m[3] * m[14] - m[13] * m[2] * m[11] + m[13] * m[3] * m[10]; | ||
|
||
inv[5] = m[0] * m[10] * m[15] - m[0] * m[11] * m[14] - m[8] * m[2] * m[15] + | ||
m[8] * m[3] * m[14] + m[12] * m[2] * m[11] - m[12] * m[3] * m[10]; | ||
|
||
inv[9] = -m[0] * m[9] * m[15] + m[0] * m[11] * m[13] + m[8] * m[1] * m[15] - | ||
m[8] * m[3] * m[13] - m[12] * m[1] * m[11] + m[12] * m[3] * m[9]; | ||
|
||
inv[13] = m[0] * m[9] * m[14] - m[0] * m[10] * m[13] - m[8] * m[1] * m[14] + | ||
m[8] * m[2] * m[13] + m[12] * m[1] * m[10] - m[12] * m[2] * m[9]; | ||
|
||
inv[2] = m[1] * m[6] * m[15] - m[1] * m[7] * m[14] - m[5] * m[2] * m[15] + | ||
m[5] * m[3] * m[14] + m[13] * m[2] * m[7] - m[13] * m[3] * m[6]; | ||
|
||
inv[6] = -m[0] * m[6] * m[15] + m[0] * m[7] * m[14] + m[4] * m[2] * m[15] - | ||
m[4] * m[3] * m[14] - m[12] * m[2] * m[7] + m[12] * m[3] * m[6]; | ||
|
||
inv[10] = m[0] * m[5] * m[15] - m[0] * m[7] * m[13] - m[4] * m[1] * m[15] + | ||
m[4] * m[3] * m[13] + m[12] * m[1] * m[7] - m[12] * m[3] * m[5]; | ||
|
||
inv[14] = -m[0] * m[5] * m[14] + m[0] * m[6] * m[13] + m[4] * m[1] * m[14] - | ||
m[4] * m[2] * m[13] - m[12] * m[1] * m[6] + m[12] * m[2] * m[5]; | ||
|
||
inv[3] = -m[1] * m[6] * m[11] + m[1] * m[7] * m[10] + m[5] * m[2] * m[11] - | ||
m[5] * m[3] * m[10] - m[9] * m[2] * m[7] + m[9] * m[3] * m[6]; | ||
|
||
inv[7] = m[0] * m[6] * m[11] - m[0] * m[7] * m[10] - m[4] * m[2] * m[11] + | ||
m[4] * m[3] * m[10] + m[8] * m[2] * m[7] - m[8] * m[3] * m[6]; | ||
|
||
inv[11] = -m[0] * m[5] * m[11] + m[0] * m[7] * m[9] + m[4] * m[1] * m[11] - | ||
m[4] * m[3] * m[9] - m[8] * m[1] * m[7] + m[8] * m[3] * m[5]; | ||
|
||
inv[15] = m[0] * m[5] * m[10] - m[0] * m[6] * m[9] - m[4] * m[1] * m[10] + | ||
m[4] * m[2] * m[9] + m[8] * m[1] * m[6] - m[8] * m[2] * m[5]; | ||
|
||
det = m[0] * inv[0] + m[1] * inv[4] + m[2] * inv[8] + m[3] * inv[12]; | ||
|
||
if (det == 0) | ||
return false; | ||
|
||
det = 1.0 / det; | ||
|
||
for (i = 0; i < 16; i++) | ||
this->matrix[i] = inv[i] * det; | ||
|
||
return true; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i don't think we need this.
I think right now changes are merged in a way that omits handling rotations. I don't see my part of the code in |
@coado Because of conflict I just merged some parts of the code from you, after I combine them, I'll push the whole code. Also I would remove the overflow part which we can concentrate on transform things. |
5b655d3
to
cec195a
Compare
@realsoelynn has imported this pull request. If you are a Meta employee, you can view this diff on Phabricator. |
Sorry about my late reply It's failing UT on Failure: Expected equality of these values:
LayoutableShadowNode::findNodeAtPoint(parentShadowNode, {119, 119})->getTag()
Which is: 3
2 I am figuring out how to run C++ Unit Test like above to run without BUCK. (I will keep you folks posted about it once i learn more about it.) |
inv[0] = m[5] * m[10] * m[15] - m[5] * m[11] * m[14] - m[9] * m[6] * m[15] + | ||
m[9] * m[7] * m[14] + m[13] * m[6] * m[11] - m[13] * m[7] * m[10]; | ||
|
||
inv[4] = -m[4] * m[10] * m[15] + m[4] * m[11] * m[14] + m[8] * m[6] * m[15] - | ||
m[8] * m[7] * m[14] - m[12] * m[6] * m[11] + m[12] * m[7] * m[10]; | ||
|
||
inv[8] = m[4] * m[9] * m[15] - m[4] * m[11] * m[13] - m[8] * m[5] * m[15] + | ||
m[8] * m[7] * m[13] + m[12] * m[5] * m[11] - m[12] * m[7] * m[9]; | ||
|
||
inv[12] = -m[4] * m[9] * m[14] + m[4] * m[10] * m[13] + m[8] * m[5] * m[14] - | ||
m[8] * m[6] * m[13] - m[12] * m[5] * m[10] + m[12] * m[6] * m[9]; | ||
|
||
inv[1] = -m[1] * m[10] * m[15] + m[1] * m[11] * m[14] + m[9] * m[2] * m[15] - | ||
m[9] * m[3] * m[14] - m[13] * m[2] * m[11] + m[13] * m[3] * m[10]; | ||
|
||
inv[5] = m[0] * m[10] * m[15] - m[0] * m[11] * m[14] - m[8] * m[2] * m[15] + | ||
m[8] * m[3] * m[14] + m[12] * m[2] * m[11] - m[12] * m[3] * m[10]; | ||
|
||
inv[9] = -m[0] * m[9] * m[15] + m[0] * m[11] * m[13] + m[8] * m[1] * m[15] - | ||
m[8] * m[3] * m[13] - m[12] * m[1] * m[11] + m[12] * m[3] * m[9]; | ||
|
||
inv[13] = m[0] * m[9] * m[14] - m[0] * m[10] * m[13] - m[8] * m[1] * m[14] + | ||
m[8] * m[2] * m[13] + m[12] * m[1] * m[10] - m[12] * m[2] * m[9]; | ||
|
||
inv[2] = m[1] * m[6] * m[15] - m[1] * m[7] * m[14] - m[5] * m[2] * m[15] + | ||
m[5] * m[3] * m[14] + m[13] * m[2] * m[7] - m[13] * m[3] * m[6]; | ||
|
||
inv[6] = -m[0] * m[6] * m[15] + m[0] * m[7] * m[14] + m[4] * m[2] * m[15] - | ||
m[4] * m[3] * m[14] - m[12] * m[2] * m[7] + m[12] * m[3] * m[6]; | ||
|
||
inv[10] = m[0] * m[5] * m[15] - m[0] * m[7] * m[13] - m[4] * m[1] * m[15] + | ||
m[4] * m[3] * m[13] + m[12] * m[1] * m[7] - m[12] * m[3] * m[5]; | ||
|
||
inv[14] = -m[0] * m[5] * m[14] + m[0] * m[6] * m[13] + m[4] * m[1] * m[14] - | ||
m[4] * m[2] * m[13] - m[12] * m[1] * m[6] + m[12] * m[2] * m[5]; | ||
|
||
inv[3] = -m[1] * m[6] * m[11] + m[1] * m[7] * m[10] + m[5] * m[2] * m[11] - | ||
m[5] * m[3] * m[10] - m[9] * m[2] * m[7] + m[9] * m[3] * m[6]; | ||
|
||
inv[7] = m[0] * m[6] * m[11] - m[0] * m[7] * m[10] - m[4] * m[2] * m[11] + | ||
m[4] * m[3] * m[10] + m[8] * m[2] * m[7] - m[8] * m[3] * m[6]; | ||
|
||
inv[11] = -m[0] * m[5] * m[11] + m[0] * m[7] * m[9] + m[4] * m[1] * m[11] - | ||
m[4] * m[3] * m[9] - m[8] * m[1] * m[7] + m[8] * m[3] * m[5]; | ||
|
||
inv[15] = m[0] * m[5] * m[10] - m[0] * m[6] * m[9] - m[4] * m[1] * m[10] + | ||
m[4] * m[2] * m[9] + m[8] * m[1] * m[6] - m[8] * m[2] * m[5]; | ||
|
||
det = m[0] * inv[0] + m[1] * inv[4] + m[2] * inv[8] + m[3] * inv[12]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@coado Can i have a link to details explanation about this matrix calculation?
I would like to understand more about it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've opened a draft, just to check if the idea is correct. So, for now I just copied the implementation from the stackoverflow. There is a more detailed implementation of this in mesa library here.
Seems this test is wrong, the tag should be 3, not 2 ? |
Isn't the view with tag 3 scaled down? It seems like the touch point is within the boundaries of unscaled view with tag 2, so the test is correct, but I might be missing something. |
@realsoelynn I just translate C++ ut to React code like below: I hit the breakpoint and it returns
|
@zhongwuzw sorry about my delay. Let's go with your original solution for now to do a simple inversion (without @coado changes). As @coado For your changes, let me work with you more later after this PR is merged as i need to prioritize and research into the algorithms more. Thank you both for your patient. |
cec195a
to
3aa37d5
Compare
packages/react-native/ReactCommon/react/renderer/core/LayoutableShadowNode.cpp
Show resolved
Hide resolved
@realsoelynn has imported this pull request. If you are a Meta employee, you can view this diff on Phabricator. |
Hmm strange CircleCI failure. @zhongwuzw please help us rebase it. |
…/fix_inverted_inspection
@realsoelynn Done. :) |
@realsoelynn has imported this pull request. If you are a Meta employee, you can view this diff on Phabricator. |
@realsoelynn merged this pull request in 1d1646a. |
This pull request was successfully merged by @zhongwuzw in 1d1646a When will my fix make it into a release? | How to file a pick request? |
Summary:
FIxes #45502 . cc @realsoelynn
Changelog:
[GENERAL] [FIXED] - Fixes findNodeAtPoint when views were inverted
Test Plan:
Demo in #45502 .