From 5a60307f03e42162cfd0171388c1377eb4d37095 Mon Sep 17 00:00:00 2001 From: Roman Trapeznikov Date: Wed, 29 Jul 2026 23:29:56 +0300 Subject: [PATCH] Allow image node to be placed in_world --- CHANGELOG.md | 31 +++--- .../support/graphics_client_context.cc | 4 +- src/ballistica/scene_v1/node/image_node.cc | 104 ++++++++++-------- src/ballistica/scene_v1/node/image_node.h | 7 ++ 4 files changed, 84 insertions(+), 62 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2282df4f6..285465507 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,6 +35,7 @@ hard-coded English, sourced from the `babuiltinassets` package so they are available before any real app-mode loads. (Adds a strings-only `babase` asset-package wrapper type for this pre-featureset layer.) +- Add `in_world` attribute to image node, as in text node (Thanks Dliwk!). ### 1.7.63 (build 22870, api 9, 2026-06-08) - Fixed mouse-wheel zooming in manual camera mode. @@ -88,7 +89,7 @@ connection or when we're in airplane mode or whatever which should save some battery, and also it lets us reconnect *exactly* when the network comes back online. - + ### 1.7.61 (build 22772, api 9, 2026-03-16) - Lucky the Leprechaun, just in time for ol' St. Patty's day (Thanks SoK!) @@ -186,9 +187,9 @@ from something like `a-0.bastdassets.260116` (YYMMDD). - Flatpak package name is now `net.froemling.bombsquad` instead of `net.froemling.BombSquad` along with improved package metadata. - Installing new flatpak builds alongside old flatpak builds will create 2 + Installing new flatpak builds alongside old flatpak builds will create 2 seperate installs. -- Added `flatpak-generate-flathub-manifest` make target that will generate +- Added `flatpak-generate-flathub-manifest` make target that will generate manifest for flathub in `build/flathub` - Updated Android audio stack to OpenALSoft 1.25.1 and oboe 1.10.0. - Updated Mac and Window audio stack to OpenALSoft 1.25.1. @@ -209,7 +210,7 @@ - Added a null audio device to prevent crash when no audio device is available - Flatpak permissions adjusted to allow gamepads to be properly detected and the configuration directory to be created if it does not already exist. - + ### 1.7.59 (build 22677, api 9, 2025-12-12) - Added a 'League President' button in the league-rank window. The back-end is still under construction, but it'll soon be possible to bid tickets to become @@ -248,7 +249,7 @@ - On Android builds, mice and trackpads now function the same as on Desktop builds instead of behaving like touches. This means buttons will highlight on mouse-over, scrollbars can be dragged, etc. - + ### 1.7.55 (build 22649, api 9, 2025-12-01) - The 'get-tokens' plus button now allows going back to whatever window one was @@ -296,7 +297,7 @@ spinner appear/disappear immediately instead of fading. - Widget ids can now be any string; there are no longer restrictions on which characters can be used. - + ### 1.7.53 (build 22597, api 9, 2025-10-25) - Fixes an issue where deleting player profiles would error. - App audio output should now update when the default sound device changes @@ -482,7 +483,7 @@ possible, the app now starts bootstrapping network stuff earlier in the boot process so it can proceed in parallel with other bootstrappy stuff (see `babase._env._bootstrap_networking()`). - + ### 1.7.46 (build 22472, api 9, 2025-08-05) - Resolves some networking issues from certain internet providers. - Working towards more consistent toolbar visibility more on small ui mode. @@ -668,7 +669,7 @@ shutdown. If you run into cases where the app consistently gets stuck when trying to exit or you see warnings about unexpected threads still running, please holler. - + ### 1.7.41 (build 22382, api 9, 2025-05-25) - Fixed a few unsafe accesses of cJSON objects that could be exploited to crash servers by feeding them bad json data. If you ever come across CXX code @@ -737,7 +738,7 @@ please let me know. - Added highlights to show players when they have unclaimed chests in their inbox or chests that can be opened. - + ### 1.7.38 (build 22318, api 9, 2025-03-20) - Added animations for reducing chest wait times or gaining tickets or tokens - Made MainWindow auto-recreate smarter. If something such as text input or a @@ -745,7 +746,7 @@ recreate once the suppression ends. - (build 22313) Fixed a possible client crash due to uninitialized memory when handling `BA_MESSAGE_HOST_INFO` data. - + ### 1.7.37 (build 22304, api 9, 2025-03-10) - Bumping api version to 9. As you'll see below, there's some UI changes that will require a bit of work for any UI mods to adapt to. If your mods don't @@ -988,7 +989,7 @@ see https://ballistica.net/whataretokens - Paid private hosting now uses tokens instead of tickets. - Wired up initial support for using asset-packages for bundled assets. -- bacloud workspace commands are now a bit smarter; you can now do things like +- bacloud workspace commands are now a bit smarter; you can now do things like `bacloud workspace put .` or even just `bacloud workspace put` and it will work. Previously such cases required explicitly passing the workspace name as a second argument. Both `workspace get` and `workspace put` now also have @@ -1026,7 +1027,7 @@ version and then upgrading to later builds of the same version containing incompatibilities with the older sys scripts. This should help with that problem. - + ### 1.7.35 (build 21889, api 8, 2024-06-20) - Fixed an issue where the engine would block at exit on some version of Linux until Ctrl-D was pressed in the calling terminal. @@ -1076,7 +1077,7 @@ two forms. Now it is possible to provide both. - Spaz classes now have a `default_hitpoints` which makes customizing that easier (Thanks rabbitboom!) -- Added `docker-gui-release`, `docker-gui-debug`, `docker-server-release`, +- Added `docker-gui-release`, `docker-gui-debug`, `docker-server-release`, `docker-server-debug`, `docker-clean` and `docker-save` targets to Makefile. - Fixed an issue in Assault where being teleported back to base with a sticky @@ -1101,7 +1102,7 @@ when running builds after pulling small updates from git. - Added github workflow for making docker image and sphinx docs nightly - Added github workflow for making build release on tag creation - + ### 1.7.34 (build 21823, api 8, 2024-04-26) - Bumped Python version from 3.11 to 3.12 for all builds and project tools. One of the things this means is that we can use `typing.override` instead of the @@ -1158,7 +1159,7 @@ default `.toml`. This can be handy when procedurally generating server configs. If no `--config` path is explicitly passed, it will look for `config.json` and `config.toml` in the same dir as the script in that order. - + ### 1.7.33 (build 21795, api 8, 2024-03-24) - Stress test input-devices are now a bit smarter; they won't press any buttons while UIs are up (this could cause lots of chaos if it happened). diff --git a/src/ballistica/base/graphics/support/graphics_client_context.cc b/src/ballistica/base/graphics/support/graphics_client_context.cc index 237ce8640..5201cdc9d 100644 --- a/src/ballistica/base/graphics/support/graphics_client_context.cc +++ b/src/ballistica/base/graphics/support/graphics_client_context.cc @@ -8,8 +8,8 @@ namespace ballistica::base { GraphicsClientContext::GraphicsClientContext() - : auto_graphics_quality{ - g_base->graphics_server->renderer()->GetAutoGraphicsQuality()}, + : auto_graphics_quality{g_base->graphics_server->renderer() + ->GetAutoGraphicsQuality()}, auto_texture_quality{ g_base->graphics_server->renderer()->GetAutoTextureQuality()}, texture_compression_types{ diff --git a/src/ballistica/scene_v1/node/image_node.cc b/src/ballistica/scene_v1/node/image_node.cc index 32a495132..064a26c92 100644 --- a/src/ballistica/scene_v1/node/image_node.cc +++ b/src/ballistica/scene_v1/node/image_node.cc @@ -40,6 +40,7 @@ class ImageNodeType : public NodeType { BA_FLOAT_ATTR(vr_depth, vr_depth, set_vr_depth); BA_BOOL_ATTR(host_only, host_only, set_host_only); BA_BOOL_ATTR(front, front, set_front); + BA_BOOL_ATTR(in_world, in_world, set_in_world); #undef BA_NODE_TYPE_CLASS ImageNodeType() @@ -64,7 +65,8 @@ class ImageNodeType : public NodeType { mesh_transparent(this), vr_depth(this), host_only(this), - front(this) {} + front(this), + in_world(this) {} }; static NodeType* node_type{}; @@ -184,8 +186,8 @@ void ImageNode::SetScale(const std::vector& vals) { } void ImageNode::SetPosition(const std::vector& vals) { - if (vals.size() != 2) { - throw Exception("Expected float array of length 2 for position", + if (vals.size() != 2 && vals.size() != 3) { + throw Exception("Expected float array of length 2 or 3 for position", PyExcType::kValue); } dirty_ = true; @@ -227,9 +229,10 @@ void ImageNode::Draw(base::FrameDef* frame_def) { vr_use_fixed = false; } - base::RenderPass& pass(*(vr_use_fixed ? frame_def->GetOverlayFixedPass() - : front_ ? frame_def->overlay_front_pass() - : frame_def->overlay_pass())); + base::RenderPass& pass(*(in_world_ ? frame_def->overlay_3d_pass() + : vr_use_fixed ? frame_def->GetOverlayFixedPass() + : front_ ? frame_def->overlay_front_pass() + : frame_def->overlay_pass())); // If the pass we're drawing into changes dimensions, recalc. // Otherwise we break if a window is resized. @@ -252,45 +255,51 @@ void ImageNode::Draw(base::FrameDef* frame_def) { tx *= scale_mult_x; ty *= scale_mult_y; } - switch (attach_) { - case Attach::BOTTOM_LEFT: - case Attach::BOTTOM_CENTER: - case Attach::BOTTOM_RIGHT: { - center_y = ty; - break; - } - case Attach::TOP_LEFT: - case Attach::TOP_CENTER: - case Attach::TOP_RIGHT: { - center_y = screen_height + ty; - break; - } - case Attach::CENTER_LEFT: - case Attach::CENTER_RIGHT: - case Attach::CENTER: { - center_y = screen_center_y + ty; - break; + if (in_world_) { + // World space; use position directly with no screen alignment. + center_x = tx; + center_y = ty; + } else { + switch (attach_) { + case Attach::BOTTOM_LEFT: + case Attach::BOTTOM_CENTER: + case Attach::BOTTOM_RIGHT: { + center_y = ty; + break; + } + case Attach::TOP_LEFT: + case Attach::TOP_CENTER: + case Attach::TOP_RIGHT: { + center_y = screen_height + ty; + break; + } + case Attach::CENTER_LEFT: + case Attach::CENTER_RIGHT: + case Attach::CENTER: { + center_y = screen_center_y + ty; + break; + } } - } - switch (attach_) { - case Attach::TOP_LEFT: - case Attach::CENTER_LEFT: - case Attach::BOTTOM_LEFT: { - center_x = tx; - break; - } - case Attach::TOP_CENTER: - case Attach::CENTER: - case Attach::BOTTOM_CENTER: { - center_x = screen_center_x + tx; - break; - } - case Attach::TOP_RIGHT: - case Attach::CENTER_RIGHT: - case Attach::BOTTOM_RIGHT: { - center_x = screen_width + tx; - break; + switch (attach_) { + case Attach::TOP_LEFT: + case Attach::CENTER_LEFT: + case Attach::BOTTOM_LEFT: { + center_x = tx; + break; + } + case Attach::TOP_CENTER: + case Attach::CENTER: + case Attach::BOTTOM_CENTER: { + center_x = screen_center_x + tx; + break; + } + case Attach::TOP_RIGHT: + case Attach::CENTER_RIGHT: + case Attach::BOTTOM_RIGHT: { + center_x = screen_width + tx; + break; + } } } if (fill_screen_) { @@ -304,6 +313,7 @@ void ImageNode::Draw(base::FrameDef* frame_def) { width_ = width; height_ = height; } + center_z_ = position_.size() > 2 ? position_[2] : 0.0f; dirty_ = false; } float fin_center_x = center_x_; @@ -395,7 +405,9 @@ void ImageNode::Draw(base::FrameDef* frame_def) { { auto xf = c.ScopedTransform(); c.Translate(fin_center_x, fin_center_y, - vr ? vr_depth_ : g_base->graphics->overlay_node_z_depth()); + in_world_ ? center_z_ + : vr ? vr_depth_ + : g_base->graphics->overlay_node_z_depth()); if (rotate_ != 0.0f) { c.Rotate(rotate_, 0, 0, 1); } @@ -421,7 +433,9 @@ void ImageNode::Draw(base::FrameDef* frame_def) { { auto xf = c.ScopedTransform(); c.Translate(fin_center_x, fin_center_y, - vr ? vr_depth_ : g_base->graphics->overlay_node_z_depth()); + in_world_ ? center_z_ + : vr ? vr_depth_ + : g_base->graphics->overlay_node_z_depth()); if (rotate_ != 0.0f) { c.Rotate(rotate_, 0, 0, 1); } diff --git a/src/ballistica/scene_v1/node/image_node.h b/src/ballistica/scene_v1/node/image_node.h index fe1384923..cd92658cb 100644 --- a/src/ballistica/scene_v1/node/image_node.h +++ b/src/ballistica/scene_v1/node/image_node.h @@ -70,6 +70,11 @@ class ImageNode : public Node { void set_host_only(bool val) { host_only_ = val; } auto front() const -> bool { return front_; } void set_front(bool val) { front_ = val; } + auto in_world() const -> bool { return in_world_; } + void set_in_world(bool val) { + in_world_ = val; + dirty_ = true; + } private: enum class Attach : uint8_t { @@ -86,6 +91,7 @@ class ImageNode : public Node { bool host_only_{}; bool front_{}; + bool in_world_{}; bool absolute_scale_{true}; bool premultiplied_{}; bool fill_screen_{}; @@ -97,6 +103,7 @@ class ImageNode : public Node { float opacity_{1.0f}; float center_x_{}; float center_y_{}; + float center_z_{}; float width_{}; float height_{}; float tilt_translate_{};