fix: hit area detection when wandering Doro faces right (flip_h=true)#9
Open
last-Medjay wants to merge 1 commit into
Open
fix: hit area detection when wandering Doro faces right (flip_h=true)#9last-Medjay wants to merge 1 commit into
last-Medjay wants to merge 1 commit into
Conversation
3988c10 to
3bab298
Compare
When the wandering Doro turned to face right, clicks on body parts
(face, legs, etc.) would not trigger interactions. The model still
animated, but `recalc_mouse_position` returned coordinates far outside
the canvas so no hit-area test ever matched.
Root cause: in `model.gd`, `flip_h = true` sets the Node2D scale to
`(-0.3, 0.3)`. That negative-x scale flows through Godot's coordinate
transforms automatically:
1. `model.to_local(event.position)` already divides by the negative
scale, mirroring x once.
2. `position * model.get_scale()` then multiplies by the same
negative scale, mirroring x back to viewport space.
So at line 27 the position is *already* in unflipped viewport coords.
The extra `if model.flip_h: position.x = -position.x` on lines 28-29
was a spurious third flip, performed in viewport coords *before* the
center offset and canvas-scale division. The later flip on lines 36-37
is the correct one: it mirrors around the canvas origin (after the
viewport-center subtraction), which is what hit-area detection
expects when the model is rendered mirrored.
With both flips active, a click at viewport (320, 320) on a flipped
model came out as (1024, 0) in canvas coords instead of the correct
(0, 0) — one full canvas-width off, so no hit area ever triggered.
Fix: drop the redundant first flip; keep the canvas-space flip at the
end of the function. The unflipped (flip_h=false) code path is
unchanged — same diff outputs for every input I traced through.
Testing scope (please regression-check before merging):
- Bug analysis is platform-independent — depends only on Godot's
Node2D transform semantics and on `model.gd` setting a negative
x-scale for flip_h. Both apply on Windows the same way they
apply on Linux.
- Verified informally by manual click-testing on a downstream RHEL
9.7 / X11 build (via WSL 2 + WSLg). Walked the wandering Doro
right-ward and confirmed the SmileEyeClosed expression triggers
on the face hit area from both facing directions.
- NOT re-tested on the upstream Windows build. A regression check
there before merging would be appreciated, particularly on the
flip_h=false path to confirm nothing changes for Windows users
whose pets face left.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
3bab298 to
f90b580
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
摘要
修复了闲逛的 Doro 转向朝右(
flip_h = true)后无法触发身体部位点击交互的 bug。模型仍然有动画,但SmileEyeClosed、Sullen等表情从朝右姿态下永远不会被触发。根本原因
model.gd通过将 Node2D 的 scale 设置为(-0.3, 0.3)来实现flip_h。这个负的 x scale 会自动流经 Godot 自身的坐标变换,所以当hit_area_handler.gd中的recalc_mouse_position运行时:model.to_local(event.position)已经将 x 镜像了一次(除以负的 scale)。position * model.get_scale()又乘了一次(把 x 镜像回 viewport 坐标)。接着函数在第 28-29 行又做了第三次翻转——在 viewport 空间,在居中和 canvas-scale 转换之前;第 36-37 行做了第四次正确翻转,在 canvas 空间。第三次翻转就是 bug 所在。
数值验证:在朝右的模型上点击 viewport
(320, 320)得到的是 canvas(1024, 0)而不是正确的(0, 0)——偏移了整整一个 canvas 宽度。对朝右 Doro 的每次点击都落在 canvas 之外。修复方法
删除冗余的 viewport 空间翻转(第一个
if model.flip_h块)。保留函数末尾的 canvas 空间翻转——那才是正确的一次翻转,它围绕 canvas 原点做镜像,使得 hit-test 目标落在 hit-area 系统所期望的未翻转坐标系中。数学验证
将新旧两条代码路径在若干点击位置下逐一追踪:
flip_h=false, click=(320,320)(0, 0)(0, 0)flip_h=false, click=(500,100)(288, -352)(288, -352)flip_h=true, click=(320,320)(1024, 0)❌(0, 0)✓flip_h=true, click=(500,100)(1312, -352)❌(-288, -352)✓flip_h=false路径在新旧代码下逐字节相同——默认的朝左状态没有 regression 风险。flip_h=true路径现在产生的 canvas 坐标正确地镜像了未翻转布局:朝右 Doro 视觉右侧的点击会映射到与朝左 Doro 视觉左侧点击相同的 canvas 位置,这正是 hit-area 检测所需要的。测试范围
请在合并前于 Windows 上做一次 regression 检查。
model.gd为flip_h设置负 x-scale 这两点。在 Windows 上和在 Linux 上一样适用。SmileEyeClosed表情从朝左和朝右两个朝向都能可靠触发。flip_h=false路径,以确认朝左 pet 的用户不受影响。建议的手动测试步骤
SmileEyeClosed表情触发。也试一下后腿。相关说明
这个 fix 是在准备一个独立的下游 RHEL 9 / X11 移植时发现的。如果你想看看那项工作 —— 7 个 C# autoload 重写为跨平台、Linux 构建链、gd_cubism 在 Linux 上的编译等等 —— 可以看这里:
→ https://github.com/last-Medjay/Dororo-RHEL9-X11
不期望合并到上游(改动面太大,且涉及 Live2D SDK 在 Linux 上的构建,绑定了一些不可重新分发的二进制),但希望让 Linux 用户能找到它。如果 Linux 构建对上游社区有意义,欢迎在 follow-up issue 中讨论;此 PR 中不主动提议。
Summary (English)
Fixes a bug where the wandering Doro (闲逛的 Doro) stops responding to clicks on her body parts once she turns to face right (
flip_h = true). The model still animates, but no hit-area expression —SmileEyeClosed,Sullen, etc. — ever triggers from a right-facing pose.Root cause
model.gdimplementsflip_hby setting the Node2D's scale to(-0.3, 0.3). That negative-x scale silently flows through Godot's own coordinate transforms, so by the timerecalc_mouse_positionruns inhit_area_handler.gd:model.to_local(event.position)has already mirrored x (divided by the negative scale).position * model.get_scale()mirrors x again (back to viewport coords).The function then performed a third flip on lines 28-29 — in viewport space, before centering and canvas-scale conversion — and a fourth correct flip on lines 36-37 in canvas space. The third flip was the bug.
Numerically: a click at viewport
(320, 320)on a flipped model came out as canvas(1024, 0)instead of(0, 0)— one full canvas-width off. Every click on a flipped Doro fell outside the canvas.Fix
Remove the redundant in-viewport-space flip (the first
if model.flip_hblock). Keep the canvas-space flip at the end of the function — that's the correct one, mirroring around the canvas origin so the hit-test target lands in the unflipped coordinate system the hit-area system expects.(See diff above.)
Math verification
flip_h=false, click=(320,320)(0, 0)(0, 0)flip_h=false, click=(500,100)(288, -352)(288, -352)flip_h=true, click=(320,320)(1024, 0)❌(0, 0)✓flip_h=true, click=(500,100)(1312, -352)❌(-288, -352)✓The
flip_h=falsepath is byte-identical between old and new code — no regression risk for the default left-facing state.The
flip_h=truepath now produces canvas coords that correctly mirror the unflipped layout: a click on the visual-right of a flipped Doro maps to the same canvas position as a click on the visual-left of an unflipped one, which is what hit-area detection needs.Testing scope
Please regression-check on Windows before merging.
model.gdsetting a negative x-scale forflip_h. Both apply on Windows the same way they apply on Linux.SmileEyeClosedexpression triggers on the face hit area from both facing directions.flip_h=falsepath to confirm nothing changes for users whose pets face left.Suggested manual test plan
Related
The fix was discovered while preparing a separate downstream RHEL 9 / X11 port of this project. If you'd like to see that work — 7 C# autoloads rewritten as dual-platform, Linux build chain, gd_cubism compiled on Linux, etc. — it lives here:
→ https://github.com/last-Medjay/Dororo-RHEL9-X11
Not proposing to merge it (too much surface area, and the build relies on Live2D-derived binaries that can't be redistributed), but wanted you to know it exists so Linux users can find it. Happy to open a follow-up issue if a Linux build is of interest to the upstream community; not proposing it here.