-
-
Notifications
You must be signed in to change notification settings - Fork 22.5k
Cleanup and simplify camera override API #52285
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
base: master
Are you sure you want to change the base?
Conversation
Oh, actually, #49334 won't be fixed since that's a 3.3.2 bug. Nonetheless, the same bug is present in master which this will fix and I'm happy to backport this once it's approved and merged. |
scene/main/viewport.h
Outdated
#ifdef TOOLS_ENABLED | ||
struct Camera2DOverride { | ||
bool enabled = false; | ||
ObjectID previous_camera = ObjectID(); |
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.
ObjectID
is default initialized so you don't need to assign a new one here (same below).
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.
Ah, good spot! Thanks, fixed now. 🙂
380c128
to
06ed733
Compare
@akien-mga unless there are further comments on code cleanliness, this should be good to be merged, I'm just finishing the merge conflict resolution, it looks rather trivial. But I'd still wait before merging. I'm not entirely sure whether it was @reduz 's suggestion back when this was first implemented to not use nodes or it was my initiative. Also, besides switching to nodes, this PR also switches from the regular It would be good to get his - or other experienced member's, maybe @Calinou since this is partially a UX change as well - opinion on these aspects before merging. |
06ed733
to
cf7a6b9
Compare
@akien-mga do you think this could get reviewed sometime soon? I'm happy to merge and rebase but I'm putting it off for now until someone has the time for review. |
Camera overrides were replaced by the Game tab: #97257 |
Alright, I got around to doing this quite a bit later than I wanted but I think I've got the changes ready now. I started from scratch but the original goals stayed mostly unchanged, including fixing the linked issue. The only goal that's changed is switching to using the global transform for override 2D. The change made sense at the time when the only way to control the override camera was via the 2D editor camera which uses global transform. The difference in behaviours made for a bit jarring user experience. But now that the override camera can be controlled directly from the Game tab, I think leaving it as is is the better option to leave it consistent with regular cameras. My understanding is that the editor camera style of control is only left for compatibility and/or systems that don't support window embedding anyway. |
Now, let's see if I can wrangle git to reset the branch to be up to date with master first. 😆 |
cf7a6b9
to
b89c47b
Compare
4409de5
to
1b691f8
Compare
b78d5f2
to
de6f70d
Compare
2467875
to
f7066e0
Compare
- Harmonise the camera override 2D and 3D APIs - Switch to using Camera2D/3D nodes to provide override functionality. This makes for simpler code, gets rid of much of copy-pasted camera code and makes code that relies on current viewport camera such as VisibleOnScreenNotifiers and object picking work out of the box. - Make camera override code only accesible within DEBUG_ENABLED builds
f7066e0
to
9d1804e
Compare
Alright, I believe all check failures should be resolved now. The only real thing I had to change was wrap the camera override code with |
2D zooming is broken. It does not zoom on cursor. godot.windows.editor.dev.x86_64_tdZfnu3n85.mp4Expected (in editor): r2ionMO8pk.mp4 |
Well spotted, thanks for testing! I'll have a look at fixing this asap. |
Use top-left corner anchor mode for override camera 2D since our view offset calculations are based around that coordinate system.
Alright, 2D zooming should be fixed now. |
Related to that, I'd be keen to discuss with someone responsible for
|
I guess it's also stemming from the fact that there's currently no way to access to the combined camera transform why functions such as |
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.
Works correctly, though I tested mainly 2D.
I checked the code and looks like nice simplification.
This particular scenario can be handled in the character controller by freezing the character if they stand in an unloaded area. The floor will reappear below their feet when the camera gets close enough again to reload the area. |
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.
Tested locally, it works as expected.
Example in the 3D Waypoints demo, which uses projected Controls in 2D space to match the 3D world:
Before
waypoints_camera_override_before.mp4
After
waypoints_camera_override_after.mp4
However, when I uncheck the camera override after moving the camera and switching to Input mode, I will always get a script error:
Video that shows how to reproduce the error (it's most reproducible if you toggle the camera override on and off quickly):
waypoints_camera_override_script_error.mp4
Adding a null
check in the project code avoids it, but not every project will have this check in place. Also, if I add a null
check to early return at the top of _process()
, the whole block will eventually stop running when I would have gotten an error without the null
check:
waypoints_camera_override_null_check.mp4
Thanks for the review guys! I addressed your remarks and went over the code and fixed a few more formatting and spelling mistakes. I will do a final pass once the changes are finalized and the proposed changes are accepted. On a side note, shouldn't codespell catch spelling mistakes - such as overriden -> overridden in my case? Or should it not be relied upon as much? |
I'm sure there's a way to work around this. It just feels wrong to me that in order to use an editor tool the user needs to add code to handle that special case. 🤔 I'm not saying we shouldn't follow through with the changes for now but it may be worth looking into possible out-of-the-box solutions. For example, investigating a viability of adding a feature in visibility notifiers/enablers that would allow choosing whether they should only consider the override camera or both the override and overridden cameras for determining visibility. Also, I intentionally didn't expose the override API in the scripting bindings because, again, I think the usage of the tool should ideally be transparent to the user and I find it to be quite an elegant solution that |
The error is thrown because the camera instance is freed when override is turned off and a new one is created when it's turned on again. I find it more straightforward to just start with a fresh instance rather than keeping the old one around to be reused later. I can change it if caching instances is the more common approach in the codebase or more desirable in this situation. But I would argue that in this case the problem is that the script is caching and using an instance that gives no guarantees about its lifetime. The correct approach would be to either verify it's still valid using |
Remote tree is supposed to show all nodes. |
The change to using camera nodes also has potential downsides. If there's gameplay code depending on current camera, it might cause unexpected behaviour when the current camera suddenly changes to the overriden camera. I had a person ask me whether using the camera override will make the environment unload if they are using visibility culling, causing, for example, the player character to fall through the floor. Similar arguments were the reason, why I originally opted for only creating camera on the RenderingServer without creating the actual camera node. That way, everything would work as if the override camera never existed.
However, reevaluating that now, duplicate code had to be written to support the same functions that the camera nodes already support. Additionally, there are cases where we do want the override camera to work as normal camera, example would be the case described in the issue #49334. All these would have to be catered to separately if the camera override didn't use the camera nodes, whereas now they all "just work". Lastly, to follow up on the visibility culling argument, I think the camera override wouldn't be really that useful if nothing besides the area in player's close vicinity would be loaded and rendered anyway.
Any feedback is welcome. If there's another approach that I haven't thought of, I'm happy to rework this. Cheers!
Closes #49334