summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/input/input_event.cpp106
-rw-r--r--core/input/input_event.h12
-rw-r--r--core/input/input_map.cpp42
-rw-r--r--core/input/input_map.h4
-rw-r--r--doc/classes/AnimationNodeOneShot.xml15
-rw-r--r--doc/classes/BitMap.xml13
-rw-r--r--doc/classes/Environment.xml7
-rw-r--r--doc/classes/RenderingServer.xml2
-rw-r--r--doc/classes/Tree.xml8
-rw-r--r--doc/classes/XRInterfaceExtension.xml50
-rw-r--r--doc/classes/XRServer.xml18
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.cpp2
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.h2
-rw-r--r--editor/import/resource_importer_scene.cpp5
-rw-r--r--editor/plugins/animation_blend_tree_editor_plugin.cpp3
-rw-r--r--editor/plugins/canvas_item_editor_plugin.cpp1
-rw-r--r--editor/plugins/sprite_frames_editor_plugin.cpp2
-rw-r--r--modules/gdscript/gdscript_analyzer.cpp2
-rw-r--r--modules/gltf/gltf_document.cpp1
-rw-r--r--modules/mobile_vr/mobile_vr_interface.cpp2
-rw-r--r--modules/mobile_vr/mobile_vr_interface.h2
-rw-r--r--modules/webxr/webxr_interface_js.cpp2
-rw-r--r--modules/webxr/webxr_interface_js.h2
-rw-r--r--platform/linuxbsd/os_linuxbsd.cpp8
-rw-r--r--scene/2d/collision_object_2d.cpp4
-rw-r--r--scene/2d/collision_object_2d.h2
-rw-r--r--scene/3d/collision_object_3d.cpp4
-rw-r--r--scene/3d/collision_object_3d.h2
-rw-r--r--scene/animation/animation_blend_tree.cpp2
-rw-r--r--scene/gui/base_button.cpp7
-rw-r--r--scene/gui/rich_text_label.cpp2
-rw-r--r--scene/gui/text_edit.cpp8
-rw-r--r--scene/gui/view_panner.cpp11
-rw-r--r--scene/gui/view_panner.h3
-rw-r--r--scene/resources/bit_map.cpp2
-rw-r--r--scene/resources/environment.cpp37
-rw-r--r--scene/resources/environment.h6
-rw-r--r--scene/resources/mesh_library.cpp33
-rw-r--r--scene/resources/sky_material.cpp2
-rw-r--r--servers/rendering/rasterizer_dummy.h2
-rw-r--r--servers/rendering/renderer_rd/effects_rd.cpp42
-rw-r--r--servers/rendering/renderer_rd/effects_rd.h6
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_environment_rd.cpp4
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_environment_rd.h4
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_rd.cpp19
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_rd.h2
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp1
-rw-r--r--servers/rendering/renderer_rd/shaders/tonemap.glsl10
-rw-r--r--servers/rendering/renderer_scene.h2
-rw-r--r--servers/rendering/renderer_scene_cull.h2
-rw-r--r--servers/rendering/renderer_scene_render.h2
-rw-r--r--servers/rendering/renderer_viewport.cpp47
-rw-r--r--servers/rendering/rendering_server_default.cpp6
-rw-r--r--servers/rendering/rendering_server_default.h2
-rw-r--r--servers/rendering/shader_language.cpp2
-rw-r--r--servers/rendering_server.cpp2
-rw-r--r--servers/rendering_server.h2
-rw-r--r--servers/xr/xr_interface.cpp3
-rw-r--r--servers/xr/xr_interface.h9
-rw-r--r--servers/xr/xr_interface_extension.cpp36
-rw-r--r--servers/xr/xr_interface_extension.h11
-rw-r--r--servers/xr_server.cpp50
-rw-r--r--servers/xr_server.h18
63 files changed, 473 insertions, 247 deletions
diff --git a/core/input/input_event.cpp b/core/input/input_event.cpp
index c608076a21..4e18efde81 100644
--- a/core/input/input_event.cpp
+++ b/core/input/input_event.cpp
@@ -86,7 +86,7 @@ Ref<InputEvent> InputEvent::xformed_by(const Transform2D &p_xform, const Vector2
return Ref<InputEvent>((InputEvent *)this);
}
-bool InputEvent::action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float *p_raw_strength, float p_deadzone) const {
+bool InputEvent::action_match(const Ref<InputEvent> &p_event, bool p_exact_match, float p_deadzone, bool *r_pressed, float *r_strength, float *r_raw_strength) const {
return false;
}
@@ -412,35 +412,32 @@ Ref<InputEventKey> InputEventKey::create_reference(Key p_keycode) {
return ie;
}
-bool InputEventKey::action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float *p_raw_strength, float p_deadzone) const {
+bool InputEventKey::action_match(const Ref<InputEvent> &p_event, bool p_exact_match, float p_deadzone, bool *r_pressed, float *r_strength, float *r_raw_strength) const {
Ref<InputEventKey> key = p_event;
if (key.is_null()) {
return false;
}
- bool match = false;
- if (get_keycode() == Key::NONE) {
- Key code = get_physical_keycode_with_modifiers();
- Key event_code = key->get_physical_keycode_with_modifiers();
-
- match = get_physical_keycode() == key->get_physical_keycode() && (!key->is_pressed() || (code & event_code) == code);
+ bool match;
+ if (keycode != Key::NONE) {
+ match = keycode == key->keycode;
} else {
- Key code = get_keycode_with_modifiers();
- Key event_code = key->get_keycode_with_modifiers();
-
- match = get_keycode() == key->get_keycode() && (!key->is_pressed() || (code & event_code) == code);
+ match = get_physical_keycode() == key->get_physical_keycode();
+ }
+ if (p_exact_match) {
+ match &= get_modifiers_mask() == key->get_modifiers_mask();
}
if (match) {
bool pressed = key->is_pressed();
- if (p_pressed != nullptr) {
- *p_pressed = pressed;
+ if (r_pressed != nullptr) {
+ *r_pressed = pressed;
}
float strength = pressed ? 1.0f : 0.0f;
- if (p_strength != nullptr) {
- *p_strength = strength;
+ if (r_strength != nullptr) {
+ *r_strength = strength;
}
- if (p_raw_strength != nullptr) {
- *p_raw_strength = strength;
+ if (r_raw_strength != nullptr) {
+ *r_raw_strength = strength;
}
}
return match;
@@ -585,24 +582,27 @@ Ref<InputEvent> InputEventMouseButton::xformed_by(const Transform2D &p_xform, co
return mb;
}
-bool InputEventMouseButton::action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float *p_raw_strength, float p_deadzone) const {
+bool InputEventMouseButton::action_match(const Ref<InputEvent> &p_event, bool p_exact_match, float p_deadzone, bool *r_pressed, float *r_strength, float *r_raw_strength) const {
Ref<InputEventMouseButton> mb = p_event;
if (mb.is_null()) {
return false;
}
- bool match = mb->button_index == button_index;
+ bool match = button_index == mb->button_index;
+ if (p_exact_match) {
+ match &= get_modifiers_mask() == mb->get_modifiers_mask();
+ }
if (match) {
bool pressed = mb->is_pressed();
- if (p_pressed != nullptr) {
- *p_pressed = pressed;
+ if (r_pressed != nullptr) {
+ *r_pressed = pressed;
}
float strength = pressed ? 1.0f : 0.0f;
- if (p_strength != nullptr) {
- *p_strength = strength;
+ if (r_strength != nullptr) {
+ *r_strength = strength;
}
- if (p_raw_strength != nullptr) {
- *p_raw_strength = strength;
+ if (r_raw_strength != nullptr) {
+ *r_raw_strength = strength;
}
}
@@ -887,36 +887,40 @@ bool InputEventJoypadMotion::is_pressed() const {
return Math::abs(axis_value) >= 0.5f;
}
-bool InputEventJoypadMotion::action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float *p_raw_strength, float p_deadzone) const {
+bool InputEventJoypadMotion::action_match(const Ref<InputEvent> &p_event, bool p_exact_match, float p_deadzone, bool *r_pressed, float *r_strength, float *r_raw_strength) const {
Ref<InputEventJoypadMotion> jm = p_event;
if (jm.is_null()) {
return false;
}
- bool match = (axis == jm->axis); // Matches even if not in the same direction, but returns a "not pressed" event.
+ // Matches even if not in the same direction, but returns a "not pressed" event.
+ bool match = axis == jm->axis;
+ if (p_exact_match) {
+ match &= (axis_value < 0) == (jm->axis_value < 0);
+ }
if (match) {
float jm_abs_axis_value = Math::abs(jm->get_axis_value());
bool same_direction = (((axis_value < 0) == (jm->axis_value < 0)) || jm->axis_value == 0);
bool pressed = same_direction && jm_abs_axis_value >= p_deadzone;
- if (p_pressed != nullptr) {
- *p_pressed = pressed;
+ if (r_pressed != nullptr) {
+ *r_pressed = pressed;
}
- if (p_strength != nullptr) {
+ if (r_strength != nullptr) {
if (pressed) {
if (p_deadzone == 1.0f) {
- *p_strength = 1.0f;
+ *r_strength = 1.0f;
} else {
- *p_strength = CLAMP(Math::inverse_lerp(p_deadzone, 1.0f, jm_abs_axis_value), 0.0f, 1.0f);
+ *r_strength = CLAMP(Math::inverse_lerp(p_deadzone, 1.0f, jm_abs_axis_value), 0.0f, 1.0f);
}
} else {
- *p_strength = 0.0f;
+ *r_strength = 0.0f;
}
}
- if (p_raw_strength != nullptr) {
+ if (r_raw_strength != nullptr) {
if (same_direction) { // NOT pressed, because we want to ignore the deadzone.
- *p_raw_strength = jm_abs_axis_value;
+ *r_raw_strength = jm_abs_axis_value;
} else {
- *p_raw_strength = 0.0f;
+ *r_raw_strength = 0.0f;
}
}
}
@@ -994,7 +998,7 @@ float InputEventJoypadButton::get_pressure() const {
return pressure;
}
-bool InputEventJoypadButton::action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float *p_raw_strength, float p_deadzone) const {
+bool InputEventJoypadButton::action_match(const Ref<InputEvent> &p_event, bool p_exact_match, float p_deadzone, bool *r_pressed, float *r_strength, float *r_raw_strength) const {
Ref<InputEventJoypadButton> jb = p_event;
if (jb.is_null()) {
return false;
@@ -1003,15 +1007,15 @@ bool InputEventJoypadButton::action_match(const Ref<InputEvent> &p_event, bool *
bool match = button_index == jb->button_index;
if (match) {
bool pressed = jb->is_pressed();
- if (p_pressed != nullptr) {
- *p_pressed = pressed;
+ if (r_pressed != nullptr) {
+ *r_pressed = pressed;
}
float strength = pressed ? 1.0f : 0.0f;
- if (p_strength != nullptr) {
- *p_strength = strength;
+ if (r_strength != nullptr) {
+ *r_strength = strength;
}
- if (p_raw_strength != nullptr) {
- *p_raw_strength = strength;
+ if (r_raw_strength != nullptr) {
+ *r_raw_strength = strength;
}
}
@@ -1288,7 +1292,7 @@ bool InputEventAction::is_action(const StringName &p_action) const {
return action == p_action;
}
-bool InputEventAction::action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float *p_raw_strength, float p_deadzone) const {
+bool InputEventAction::action_match(const Ref<InputEvent> &p_event, bool p_exact_match, float p_deadzone, bool *r_pressed, float *r_strength, float *r_raw_strength) const {
Ref<InputEventAction> act = p_event;
if (act.is_null()) {
return false;
@@ -1297,15 +1301,15 @@ bool InputEventAction::action_match(const Ref<InputEvent> &p_event, bool *p_pres
bool match = action == act->action;
if (match) {
bool pressed = act->pressed;
- if (p_pressed != nullptr) {
- *p_pressed = pressed;
+ if (r_pressed != nullptr) {
+ *r_pressed = pressed;
}
float strength = pressed ? 1.0f : 0.0f;
- if (p_strength != nullptr) {
- *p_strength = strength;
+ if (r_strength != nullptr) {
+ *r_strength = strength;
}
- if (p_raw_strength != nullptr) {
- *p_raw_strength = strength;
+ if (r_raw_strength != nullptr) {
+ *r_raw_strength = strength;
}
}
return match;
diff --git a/core/input/input_event.h b/core/input/input_event.h
index 29450dfc52..114db46623 100644
--- a/core/input/input_event.h
+++ b/core/input/input_event.h
@@ -79,7 +79,7 @@ public:
virtual Ref<InputEvent> xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs = Vector2()) const;
- virtual bool action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float *p_raw_strength, float p_deadzone) const;
+ virtual bool action_match(const Ref<InputEvent> &p_event, bool p_exact_match, float p_deadzone, bool *r_pressed, float *r_strength, float *r_raw_strength) const;
virtual bool is_match(const Ref<InputEvent> &p_event, bool p_exact_match = true) const;
virtual bool is_action_type() const;
@@ -192,7 +192,7 @@ public:
Key get_keycode_with_modifiers() const;
Key get_physical_keycode_with_modifiers() const;
- virtual bool action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float *p_raw_strength, float p_deadzone) const override;
+ virtual bool action_match(const Ref<InputEvent> &p_event, bool p_exact_match, float p_deadzone, bool *r_pressed, float *r_strength, float *r_raw_strength) const override;
virtual bool is_match(const Ref<InputEvent> &p_event, bool p_exact_match = true) const override;
virtual bool is_action_type() const override { return true; }
@@ -255,7 +255,7 @@ public:
virtual Ref<InputEvent> xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs = Vector2()) const override;
- virtual bool action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float *p_raw_strength, float p_deadzone) const override;
+ virtual bool action_match(const Ref<InputEvent> &p_event, bool p_exact_match, float p_deadzone, bool *r_pressed, float *r_strength, float *r_raw_strength) const override;
virtual bool is_match(const Ref<InputEvent> &p_event, bool p_exact_match = true) const override;
virtual bool is_action_type() const override { return true; }
@@ -315,7 +315,7 @@ public:
virtual bool is_pressed() const override;
- virtual bool action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float *p_raw_strength, float p_deadzone) const override;
+ virtual bool action_match(const Ref<InputEvent> &p_event, bool p_exact_match, float p_deadzone, bool *r_pressed, float *r_strength, float *r_raw_strength) const override;
virtual bool is_match(const Ref<InputEvent> &p_event, bool p_exact_match = true) const override;
virtual bool is_action_type() const override { return true; }
@@ -344,7 +344,7 @@ public:
void set_pressure(float p_pressure);
float get_pressure() const;
- virtual bool action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float *p_raw_strength, float p_deadzone) const override;
+ virtual bool action_match(const Ref<InputEvent> &p_event, bool p_exact_match, float p_deadzone, bool *r_pressed, float *r_strength, float *r_raw_strength) const override;
virtual bool is_match(const Ref<InputEvent> &p_event, bool p_exact_match = true) const override;
virtual bool is_action_type() const override { return true; }
@@ -437,7 +437,7 @@ public:
virtual bool is_action(const StringName &p_action) const;
- virtual bool action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float *p_raw_strength, float p_deadzone) const override;
+ virtual bool action_match(const Ref<InputEvent> &p_event, bool p_exact_match, float p_deadzone, bool *r_pressed, float *r_strength, float *r_raw_strength) const override;
virtual bool is_match(const Ref<InputEvent> &p_event, bool p_exact_match = true) const override;
virtual bool is_action_type() const override { return true; }
diff --git a/core/input/input_map.cpp b/core/input/input_map.cpp
index 753ac72ab6..41083b4c47 100644
--- a/core/input/input_map.cpp
+++ b/core/input/input_map.cpp
@@ -126,15 +126,13 @@ List<StringName> InputMap::get_actions() const {
return actions;
}
-List<Ref<InputEvent>>::Element *InputMap::_find_event(Action &p_action, const Ref<InputEvent> &p_event, bool p_exact_match, bool *p_pressed, float *p_strength, float *p_raw_strength) const {
+List<Ref<InputEvent>>::Element *InputMap::_find_event(Action &p_action, const Ref<InputEvent> &p_event, bool p_exact_match, bool *r_pressed, float *r_strength, float *r_raw_strength) const {
ERR_FAIL_COND_V(!p_event.is_valid(), nullptr);
for (List<Ref<InputEvent>>::Element *E = p_action.inputs.front(); E; E = E->next()) {
int device = E->get()->get_device();
if (device == ALL_DEVICES || device == p_event->get_device()) {
- if (p_exact_match && E->get()->is_match(p_event, true)) {
- return E;
- } else if (!p_exact_match && E->get()->action_match(p_event, p_pressed, p_strength, p_raw_strength, p_action.deadzone)) {
+ if (E->get()->action_match(p_event, p_exact_match, p_action.deadzone, r_pressed, r_strength, r_raw_strength)) {
return E;
}
}
@@ -217,40 +215,28 @@ bool InputMap::event_is_action(const Ref<InputEvent> &p_event, const StringName
return event_get_action_status(p_event, p_action, p_exact_match);
}
-bool InputMap::event_get_action_status(const Ref<InputEvent> &p_event, const StringName &p_action, bool p_exact_match, bool *p_pressed, float *p_strength, float *p_raw_strength) const {
+bool InputMap::event_get_action_status(const Ref<InputEvent> &p_event, const StringName &p_action, bool p_exact_match, bool *r_pressed, float *r_strength, float *r_raw_strength) const {
OrderedHashMap<StringName, Action>::Element E = input_map.find(p_action);
ERR_FAIL_COND_V_MSG(!E, false, suggest_actions(p_action));
Ref<InputEventAction> input_event_action = p_event;
if (input_event_action.is_valid()) {
- bool pressed = input_event_action->is_pressed();
- if (p_pressed != nullptr) {
- *p_pressed = pressed;
+ const bool pressed = input_event_action->is_pressed();
+ if (r_pressed != nullptr) {
+ *r_pressed = pressed;
+ }
+ const float strength = pressed ? input_event_action->get_strength() : 0.0f;
+ if (r_strength != nullptr) {
+ *r_strength = strength;
}
- if (p_strength != nullptr) {
- *p_strength = pressed ? input_event_action->get_strength() : 0.0f;
+ if (r_raw_strength != nullptr) {
+ *r_raw_strength = strength;
}
return input_event_action->get_action() == p_action;
}
- bool pressed;
- float strength;
- float raw_strength;
- List<Ref<InputEvent>>::Element *event = _find_event(E.get(), p_event, p_exact_match, &pressed, &strength, &raw_strength);
- if (event != nullptr) {
- if (p_pressed != nullptr) {
- *p_pressed = pressed;
- }
- if (p_strength != nullptr) {
- *p_strength = strength;
- }
- if (p_raw_strength != nullptr) {
- *p_raw_strength = raw_strength;
- }
- return true;
- } else {
- return false;
- }
+ List<Ref<InputEvent>>::Element *event = _find_event(E.get(), p_event, p_exact_match, r_pressed, r_strength, r_raw_strength);
+ return event != nullptr;
}
const OrderedHashMap<StringName, InputMap::Action> &InputMap::get_action_map() const {
diff --git a/core/input/input_map.h b/core/input/input_map.h
index e896d1f679..79b4d1038f 100644
--- a/core/input/input_map.h
+++ b/core/input/input_map.h
@@ -58,7 +58,7 @@ private:
OrderedHashMap<String, List<Ref<InputEvent>>> default_builtin_cache;
OrderedHashMap<String, List<Ref<InputEvent>>> default_builtin_with_overrides_cache;
- List<Ref<InputEvent>>::Element *_find_event(Action &p_action, const Ref<InputEvent> &p_event, bool p_exact_match = false, bool *p_pressed = nullptr, float *p_strength = nullptr, float *p_raw_strength = nullptr) const;
+ List<Ref<InputEvent>>::Element *_find_event(Action &p_action, const Ref<InputEvent> &p_event, bool p_exact_match = false, bool *r_pressed = nullptr, float *r_strength = nullptr, float *r_raw_strength = nullptr) const;
Array _action_get_events(const StringName &p_action);
Array _get_actions();
@@ -83,7 +83,7 @@ public:
const List<Ref<InputEvent>> *action_get_events(const StringName &p_action);
bool event_is_action(const Ref<InputEvent> &p_event, const StringName &p_action, bool p_exact_match = false) const;
- bool event_get_action_status(const Ref<InputEvent> &p_event, const StringName &p_action, bool p_exact_match = false, bool *p_pressed = nullptr, float *p_strength = nullptr, float *p_raw_strength = nullptr) const;
+ bool event_get_action_status(const Ref<InputEvent> &p_event, const StringName &p_action, bool p_exact_match = false, bool *r_pressed = nullptr, float *r_strength = nullptr, float *r_raw_strength = nullptr) const;
const OrderedHashMap<StringName, Action> &get_action_map() const;
void load_from_project_settings();
diff --git a/doc/classes/AnimationNodeOneShot.xml b/doc/classes/AnimationNodeOneShot.xml
index 116b54e39e..71ed82cf46 100644
--- a/doc/classes/AnimationNodeOneShot.xml
+++ b/doc/classes/AnimationNodeOneShot.xml
@@ -10,19 +10,6 @@
<link title="AnimationTree">$DOCS_URL/tutorials/animation/animation_tree.html</link>
<link title="Third Person Shooter Demo">https://godotengine.org/asset-library/asset/678</link>
</tutorials>
- <methods>
- <method name="get_mix_mode" qualifiers="const">
- <return type="int" enum="AnimationNodeOneShot.MixMode" />
- <description>
- </description>
- </method>
- <method name="set_mix_mode">
- <return type="void" />
- <argument index="0" name="mode" type="int" enum="AnimationNodeOneShot.MixMode" />
- <description>
- </description>
- </method>
- </methods>
<members>
<member name="autorestart" type="bool" setter="set_autorestart" getter="has_autorestart" default="false">
If [code]true[/code], the sub-animation will restart automatically after finishing.
@@ -37,6 +24,8 @@
</member>
<member name="fadeout_time" type="float" setter="set_fadeout_time" getter="get_fadeout_time" default="0.1">
</member>
+ <member name="mix_mode" type="int" setter="set_mix_mode" getter="get_mix_mode" enum="AnimationNodeOneShot.MixMode" default="0">
+ </member>
<member name="sync" type="bool" setter="set_use_sync" getter="is_using_sync" default="false">
</member>
</members>
diff --git a/doc/classes/BitMap.xml b/doc/classes/BitMap.xml
index dc655ee3b0..ebcdcab75e 100644
--- a/doc/classes/BitMap.xml
+++ b/doc/classes/BitMap.xml
@@ -9,6 +9,12 @@
<tutorials>
</tutorials>
<methods>
+ <method name="convert_to_image" qualifiers="const">
+ <return type="Image" />
+ <description>
+ Returns an image of the same size as the bitmap and with a [enum Image.Format] of type [code]FORMAT_L8[/code]. [code]true[/code] bits of the bitmap are being converted into white pixels, and [code]false[/code] bits into black.
+ </description>
+ </method>
<method name="create">
<return type="void" />
<argument index="0" name="size" type="Vector2" />
@@ -64,6 +70,13 @@
[code]epsilon[/code] is passed to RDP to control how accurately the polygons cover the bitmap: a lower [code]epsilon[/code] corresponds to more points in the polygons.
</description>
</method>
+ <method name="resize">
+ <return type="void" />
+ <argument index="0" name="new_size" type="Vector2" />
+ <description>
+ Resizes the image to [code]new_size[/code].
+ </description>
+ </method>
<method name="set_bit">
<return type="void" />
<argument index="0" name="position" type="Vector2" />
diff --git a/doc/classes/Environment.xml b/doc/classes/Environment.xml
index b31162f10f..c8c0494378 100644
--- a/doc/classes/Environment.xml
+++ b/doc/classes/Environment.xml
@@ -154,6 +154,13 @@
<member name="glow_levels/7" type="float" setter="set_glow_level" getter="get_glow_level" default="0.0">
The intensity of the 7th level of glow. This is the most "global" level (blurriest).
</member>
+ <member name="glow_map" type="Texture" setter="set_glow_map" getter="get_glow_map">
+ The texture that should be used as a glow map to [i]multiply[/i] the resulting glow color according to [member glow_map_strength]. This can be used to create a "lens dirt" effect. The texture's RGB color channels are used for modulation, but the alpha channel is ignored.
+ [b]Note:[/b] The texture will be stretched to fit the screen. Therefore, it's recommended to use a texture with an aspect ratio that matches your project's base aspect ratio (typically 16:9).
+ </member>
+ <member name="glow_map_strength" type="float" setter="set_glow_map_strength" getter="get_glow_map_strength" default="0.8">
+ How strong of an impact the [member glow_map] should have on the overall glow effect. A strength of [code]0.0[/code] means the glow map has no effect on the overall glow effect. A strength of [code]1.0[/code] means the glow has a full effect on the overall glow effect (and can turn off glow entirely in specific areas of the screen if the glow map has black areas).
+ </member>
<member name="glow_mix" type="float" setter="set_glow_mix" getter="get_glow_mix" default="0.05">
</member>
<member name="glow_normalized" type="bool" setter="set_glow_normalized" getter="is_glow_normalized" default="false">
diff --git a/doc/classes/RenderingServer.xml b/doc/classes/RenderingServer.xml
index ff370bd953..446db40dd8 100644
--- a/doc/classes/RenderingServer.xml
+++ b/doc/classes/RenderingServer.xml
@@ -994,6 +994,8 @@
<argument index="8" name="hdr_bleed_threshold" type="float" />
<argument index="9" name="hdr_bleed_scale" type="float" />
<argument index="10" name="hdr_luminance_cap" type="float" />
+ <argument index="11" name="glow_map_strength" type="float" />
+ <argument index="12" name="glow_map" type="RID" />
<description>
</description>
</method>
diff --git a/doc/classes/Tree.xml b/doc/classes/Tree.xml
index 106bcf9d37..6392d0853f 100644
--- a/doc/classes/Tree.xml
+++ b/doc/classes/Tree.xml
@@ -53,7 +53,7 @@
<argument index="0" name="parent" type="Object" default="null" />
<argument index="1" name="idx" type="int" default="-1" />
<description>
- Creates an item in the tree and adds it as a child of [code]parent[/code].
+ Creates an item in the tree and adds it as a child of [code]parent[/code], which can be either a valid [TreeItem] or [code]null[/code].
If [code]parent[/code] is [code]null[/code], the root item will be the parent, or the new item will be the root itself if the tree is empty.
The new item will be the [code]idx[/code]th child of parent, or it will be the last child if there are not enough siblings.
</description>
@@ -173,7 +173,7 @@
<argument index="0" name="item" type="Object" />
<argument index="1" name="column" type="int" default="-1" />
<description>
- Returns the rectangle area for the specified item. If [code]column[/code] is specified, only get the position and size of that column, otherwise get the rectangle containing all columns.
+ Returns the rectangle area for the specified [TreeItem]. If [code]column[/code] is specified, only get the position and size of that column, otherwise get the rectangle containing all columns.
</description>
</method>
<method name="get_item_at_position" qualifiers="const">
@@ -187,7 +187,7 @@
<return type="TreeItem" />
<argument index="0" name="from" type="Object" />
<description>
- Returns the next selected item after the given one, or [code]null[/code] if the end is reached.
+ Returns the next selected [TreeItem] after the given one, or [code]null[/code] if the end is reached.
If [code]from[/code] is [code]null[/code], this returns the first selected item.
</description>
</method>
@@ -241,7 +241,7 @@
<return type="void" />
<argument index="0" name="item" type="Object" />
<description>
- Causes the [Tree] to jump to the specified item.
+ Causes the [Tree] to jump to the specified [TreeItem].
</description>
</method>
<method name="set_column_clip_content">
diff --git a/doc/classes/XRInterfaceExtension.xml b/doc/classes/XRInterfaceExtension.xml
index d2bb6aa59a..cd09f83335 100644
--- a/doc/classes/XRInterfaceExtension.xml
+++ b/doc/classes/XRInterfaceExtension.xml
@@ -9,46 +9,52 @@
<tutorials>
</tutorials>
<methods>
- <method name="_commit_views" qualifiers="virtual">
+ <method name="_end_frame" qualifiers="virtual">
<return type="void" />
- <argument index="0" name="render_target" type="RID" />
- <argument index="1" name="screen_rect" type="Rect2" />
<description>
+ Called if interface is active and queues have been submitted.
</description>
</method>
<method name="_get_anchor_detection_is_enabled" qualifiers="virtual const">
<return type="bool" />
<description>
+ Return [code]true[/code] if anchor detection is enabled for this interface.
</description>
</method>
<method name="_get_camera_feed_id" qualifiers="virtual const">
<return type="int" />
<description>
+ Returns the camera feed id for the [CameraFeed] registered with the [CameraServer] that should be presented as the background on an AR capable device (if applicable).
</description>
</method>
<method name="_get_camera_transform" qualifiers="virtual">
<return type="Transform3D" />
<description>
+ Returns the [Transform3D] that positions the [XRCamera3D] in the world.
</description>
</method>
<method name="_get_capabilities" qualifiers="virtual const">
<return type="int" />
<description>
+ Returns the capabilities of this interface.
</description>
</method>
<method name="_get_name" qualifiers="virtual const">
<return type="StringName" />
<description>
+ Returns the name of this interface.
</description>
</method>
<method name="_get_play_area" qualifiers="virtual const">
<return type="PackedVector3Array" />
<description>
+ Returns an [PackedVector3Array] that denotes the play areas boundaries (if applicable).
</description>
</method>
<method name="_get_play_area_mode" qualifiers="virtual const">
<return type="int" />
<description>
+ Returns the [enum XRInterface.PlayAreaMode] that sets up our play area.
</description>
</method>
<method name="_get_projection_for_view" qualifiers="virtual">
@@ -58,27 +64,32 @@
<argument index="2" name="z_near" type="float" />
<argument index="3" name="z_far" type="float" />
<description>
+ Returns the projection matrix for the given view as a [PackedFloat64Array].
</description>
</method>
<method name="_get_render_target_size" qualifiers="virtual">
<return type="Vector2" />
<description>
+ Returns the size of our render target for this interface, this overrides the size of the [Viewport] marked as the xr viewport.
</description>
</method>
<method name="_get_suggested_pose_names" qualifiers="virtual const">
<return type="PackedStringArray" />
<argument index="0" name="tracker_name" type="StringName" />
<description>
+ Returns a [PackedStringArray] with pose names configured by this interface. Note that user configuration can override this list.
</description>
</method>
<method name="_get_suggested_tracker_names" qualifiers="virtual const">
<return type="PackedStringArray" />
<description>
+ Returns a [PackedStringArray] with tracker names configured by this interface. Note that user configuration can override this list.
</description>
</method>
<method name="_get_tracking_status" qualifiers="virtual const">
<return type="int" />
<description>
+ Returns a [enum XRInterface.TrackingStatus] specifying the current status of our tracking.
</description>
</method>
<method name="_get_transform_for_view" qualifiers="virtual">
@@ -86,50 +97,80 @@
<argument index="0" name="view" type="int" />
<argument index="1" name="cam_transform" type="Transform3D" />
<description>
+ Returns a [Transform3D] for a given view.
</description>
</method>
<method name="_get_view_count" qualifiers="virtual">
<return type="int" />
<description>
+ Returns the number of views this interface requires, 1 for mono, 2 for stereoscopic.
</description>
</method>
<method name="_initialize" qualifiers="virtual">
<return type="bool" />
<description>
+ Initializes the interface, returns [code]true[/code] on success.
</description>
</method>
<method name="_is_initialized" qualifiers="virtual const">
<return type="bool" />
<description>
+ Returns [code]true[/code] if this interface has been initialised.
</description>
</method>
<method name="_notification" qualifiers="virtual">
<return type="void" />
<argument index="0" name="what" type="int" />
<description>
+ Informs the interface of an applicable system notification.
+ </description>
+ </method>
+ <method name="_post_draw_viewport" qualifiers="virtual">
+ <return type="void" />
+ <argument index="0" name="render_target" type="RID" />
+ <argument index="1" name="screen_rect" type="Rect2" />
+ <description>
+ Called after the XR [Viewport] draw logic has completed.
+ </description>
+ </method>
+ <method name="_pre_draw_viewport" qualifiers="virtual">
+ <return type="bool" />
+ <argument index="0" name="render_target" type="RID" />
+ <description>
+ Called if this is our primary [XRInterfaceExtension] before we start processing a [Viewport] for every active XR [Viewport], returns [code]true[/code] if that viewport should be rendered. An XR interface may return [code]false[/code] if the user has taken off their headset and we can pause rendering.
+ </description>
+ </method>
+ <method name="_pre_render" qualifiers="virtual">
+ <return type="void" />
+ <description>
+ Called if this [XRInterfaceExtension] is active before rendering starts, most XR interfaces will sync tracking at this point in time.
</description>
</method>
<method name="_process" qualifiers="virtual">
<return type="void" />
<description>
+ Called if this [XRInterfaceExtension] is active before our physics and game process is called. most XR interfaces will update its [XRPositionalTracker]s at this point in time.
</description>
</method>
<method name="_set_anchor_detection_is_enabled" qualifiers="virtual">
<return type="void" />
<argument index="0" name="enabled" type="bool" />
<description>
+ Enables anchor detection on this interface if supported.
</description>
</method>
<method name="_set_play_area_mode" qualifiers="virtual const">
<return type="bool" />
<argument index="0" name="mode" type="int" />
<description>
+ Set the play area mode for this interface.
</description>
</method>
<method name="_supports_play_area_mode" qualifiers="virtual const">
<return type="bool" />
<argument index="0" name="mode" type="int" enum="XRInterface.PlayAreaMode" />
<description>
+ Returns [code]true[/code] if this interface supports this play area mode.
</description>
</method>
<method name="_trigger_haptic_pulse" qualifiers="virtual">
@@ -141,11 +182,13 @@
<argument index="4" name="duration_sec" type="float" />
<argument index="5" name="delay_sec" type="float" />
<description>
+ Triggers a haptic pulse to be emitted on the specified tracker.
</description>
</method>
<method name="_uninitialize" qualifiers="virtual">
<return type="void" />
<description>
+ Uninitialize the interface.
</description>
</method>
<method name="add_blit">
@@ -169,6 +212,7 @@
<return type="RID" />
<argument index="0" name="render_target" type="RID" />
<description>
+ Returns a valid [RID] for a texture to which we should render the current frame if supported by the interface.
</description>
</method>
</methods>
diff --git a/doc/classes/XRServer.xml b/doc/classes/XRServer.xml
index 3a7fdea8d0..335ca4c35f 100644
--- a/doc/classes/XRServer.xml
+++ b/doc/classes/XRServer.xml
@@ -69,24 +69,6 @@
Returns a list of available interfaces the ID and name of each interface.
</description>
</method>
- <method name="get_last_commit_usec">
- <return type="int" />
- <description>
- Returns the absolute timestamp (in μs) of the last [XRServer] commit of the AR/VR eyes to [RenderingServer]. The value comes from an internal call to [method Time.get_ticks_usec].
- </description>
- </method>
- <method name="get_last_frame_usec">
- <return type="int" />
- <description>
- Returns the duration (in μs) of the last frame. This is computed as the difference between [method get_last_commit_usec] and [method get_last_process_usec] when committing.
- </description>
- </method>
- <method name="get_last_process_usec">
- <return type="int" />
- <description>
- Returns the absolute timestamp (in μs) of the last [XRServer] process callback. The value comes from an internal call to [method Time.get_ticks_usec].
- </description>
- </method>
<method name="get_reference_frame" qualifiers="const">
<return type="Transform3D" />
<description>
diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp
index 31dda16b26..121dc86fb2 100644
--- a/drivers/gles3/rasterizer_scene_gles3.cpp
+++ b/drivers/gles3/rasterizer_scene_gles3.cpp
@@ -208,7 +208,7 @@ void RasterizerSceneGLES3::environment_set_canvas_max_layer(RID p_env, int p_max
void RasterizerSceneGLES3::environment_set_ambient_light(RID p_env, const Color &p_color, RS::EnvironmentAmbientSource p_ambient, float p_energy, float p_sky_contribution, RS::EnvironmentReflectionSource p_reflection_source) {
}
-void RasterizerSceneGLES3::environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap) {
+void RasterizerSceneGLES3::environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, float p_glow_map_strength, RID p_glow_map) {
}
void RasterizerSceneGLES3::environment_glow_set_use_bicubic_upscale(bool p_enable) {
diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h
index 0f8c2e88b4..246b908c14 100644
--- a/drivers/gles3/rasterizer_scene_gles3.h
+++ b/drivers/gles3/rasterizer_scene_gles3.h
@@ -115,7 +115,7 @@ public:
void environment_set_canvas_max_layer(RID p_env, int p_max_layer) override;
void environment_set_ambient_light(RID p_env, const Color &p_color, RS::EnvironmentAmbientSource p_ambient = RS::ENV_AMBIENT_SOURCE_BG, float p_energy = 1.0, float p_sky_contribution = 0.0, RS::EnvironmentReflectionSource p_reflection_source = RS::ENV_REFLECTION_SOURCE_BG) override;
- void environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap) override;
+ void environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, float p_glow_map_strength, RID p_glow_map) override;
void environment_glow_set_use_bicubic_upscale(bool p_enable) override;
void environment_glow_set_use_high_quality(bool p_enable) override;
diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp
index af9a2f9ebe..0fefa0f3c4 100644
--- a/editor/import/resource_importer_scene.cpp
+++ b/editor/import/resource_importer_scene.cpp
@@ -282,7 +282,8 @@ bool ResourceImporterScene::get_option_visibility(const String &p_path, const St
}
}
- if (p_option == "meshes/lightmap_texel_size" && int(p_options["meshes/light_baking"]) < 3) {
+ if (p_option == "meshes/lightmap_texel_size" && int(p_options["meshes/light_baking"]) != 2) {
+ // Only display the lightmap texel size import option when using the Static Lightmaps light baking mode.
return false;
}
@@ -1476,7 +1477,7 @@ void ResourceImporterScene::get_import_options(const String &p_path, List<Import
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "meshes/ensure_tangents"), true));
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "meshes/generate_lods"), true));
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "meshes/create_shadow_meshes"), true));
- r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "meshes/light_baking", PROPERTY_HINT_ENUM, "Disabled,Static (VoxelGI/SDFGI),Static Lightmaps,Dynamic (VoxelGI only)", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), 1));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "meshes/light_baking", PROPERTY_HINT_ENUM, "Disabled,Static (VoxelGI/SDFGI),Static Lightmaps (VoxelGI/SDFGI/LightmapGI),Dynamic (VoxelGI only)", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), 1));
r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "meshes/lightmap_texel_size", PROPERTY_HINT_RANGE, "0.001,100,0.001"), 0.1));
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "skins/use_named_skins"), true));
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "animation/import"), true));
diff --git a/editor/plugins/animation_blend_tree_editor_plugin.cpp b/editor/plugins/animation_blend_tree_editor_plugin.cpp
index b889742b19..e46c81b77e 100644
--- a/editor/plugins/animation_blend_tree_editor_plugin.cpp
+++ b/editor/plugins/animation_blend_tree_editor_plugin.cpp
@@ -898,6 +898,9 @@ void AnimationNodeBlendTreeEditor::_node_renamed(const String &p_text, Ref<Anima
}
void AnimationNodeBlendTreeEditor::_node_renamed_focus_out(Node *le, Ref<AnimationNode> p_node) {
+ if (le == nullptr) {
+ return; // The text_submitted signal triggered the graph update and freed the LineEdit.
+ }
_node_renamed(le->call("get_text"), p_node);
}
diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp
index 4093c70c47..1aae82f66f 100644
--- a/editor/plugins/canvas_item_editor_plugin.cpp
+++ b/editor/plugins/canvas_item_editor_plugin.cpp
@@ -1117,6 +1117,7 @@ bool CanvasItemEditor::_gui_input_rulers_and_guides(const Ref<InputEvent> &p_eve
}
bool CanvasItemEditor::_gui_input_zoom_or_pan(const Ref<InputEvent> &p_event, bool p_already_accepted) {
+ panner->set_force_drag(tool == TOOL_PAN);
bool panner_active = panner->gui_input(p_event, warped_panning ? viewport->get_global_rect() : Rect2());
if (panner->is_panning() != pan_pressed) {
pan_pressed = panner->is_panning();
diff --git a/editor/plugins/sprite_frames_editor_plugin.cpp b/editor/plugins/sprite_frames_editor_plugin.cpp
index 9013eaf9d8..014fa0e7a5 100644
--- a/editor/plugins/sprite_frames_editor_plugin.cpp
+++ b/editor/plugins/sprite_frames_editor_plugin.cpp
@@ -821,7 +821,7 @@ void SpriteFramesEditor::_update_library(bool p_skip_selector) {
for (int i = 0; i < frames->get_frame_count(edited_anim); i++) {
String name;
- Ref<Texture> frame = frames->get_frame(edited_anim, i);
+ Ref<Texture2D> frame = frames->get_frame(edited_anim, i);
if (frame.is_null()) {
name = itos(i) + ": " + TTR("(empty)");
diff --git a/modules/gdscript/gdscript_analyzer.cpp b/modules/gdscript/gdscript_analyzer.cpp
index 0d295c3a51..d11174227a 100644
--- a/modules/gdscript/gdscript_analyzer.cpp
+++ b/modules/gdscript/gdscript_analyzer.cpp
@@ -1586,7 +1586,7 @@ void GDScriptAnalyzer::resolve_match_pattern(GDScriptParser::PatternNode *p_matc
if (p_match_pattern->dictionary[i].key) {
reduce_expression(p_match_pattern->dictionary[i].key);
if (!p_match_pattern->dictionary[i].key->is_constant) {
- push_error(R"(Expression in dictionary pattern key must be a constant.)", p_match_pattern->expression);
+ push_error(R"(Expression in dictionary pattern key must be a constant.)", p_match_pattern->dictionary[i].key);
}
}
diff --git a/modules/gltf/gltf_document.cpp b/modules/gltf/gltf_document.cpp
index 5a931ed839..51608273a1 100644
--- a/modules/gltf/gltf_document.cpp
+++ b/modules/gltf/gltf_document.cpp
@@ -6843,6 +6843,7 @@ Error GLTFDocument::write_to_filesystem(Ref<GLTFState> state, const String &p_pa
}
Node *GLTFDocument::generate_scene(Ref<GLTFState> state, int32_t p_bake_fps) {
+ ERR_FAIL_NULL_V(state, nullptr);
ERR_FAIL_INDEX_V(0, state->root_nodes.size(), nullptr);
GLTFNodeIndex gltf_root = state->root_nodes.write[0];
Node *gltf_root_node = state->get_scene_node(gltf_root);
diff --git a/modules/mobile_vr/mobile_vr_interface.cpp b/modules/mobile_vr/mobile_vr_interface.cpp
index 49044c4afe..8cd23ffb24 100644
--- a/modules/mobile_vr/mobile_vr_interface.cpp
+++ b/modules/mobile_vr/mobile_vr_interface.cpp
@@ -463,7 +463,7 @@ CameraMatrix MobileVRInterface::get_projection_for_view(uint32_t p_view, double
return eye;
};
-Vector<BlitToScreen> MobileVRInterface::commit_views(RID p_render_target, const Rect2 &p_screen_rect) {
+Vector<BlitToScreen> MobileVRInterface::post_draw_viewport(RID p_render_target, const Rect2 &p_screen_rect) {
_THREAD_SAFE_METHOD_
Vector<BlitToScreen> blit_to_screen;
diff --git a/modules/mobile_vr/mobile_vr_interface.h b/modules/mobile_vr/mobile_vr_interface.h
index 47dc33c0c7..8ecca3a2ae 100644
--- a/modules/mobile_vr/mobile_vr_interface.h
+++ b/modules/mobile_vr/mobile_vr_interface.h
@@ -151,7 +151,7 @@ public:
virtual Transform3D get_camera_transform() override;
virtual Transform3D get_transform_for_view(uint32_t p_view, const Transform3D &p_cam_transform) override;
virtual CameraMatrix get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) override;
- virtual Vector<BlitToScreen> commit_views(RID p_render_target, const Rect2 &p_screen_rect) override;
+ virtual Vector<BlitToScreen> post_draw_viewport(RID p_render_target, const Rect2 &p_screen_rect) override;
virtual void process() override;
diff --git a/modules/webxr/webxr_interface_js.cpp b/modules/webxr/webxr_interface_js.cpp
index 8eb0d8ff90..86b857f72c 100644
--- a/modules/webxr/webxr_interface_js.cpp
+++ b/modules/webxr/webxr_interface_js.cpp
@@ -385,7 +385,7 @@ CameraMatrix WebXRInterfaceJS::get_projection_for_view(uint32_t p_view, double p
return eye;
}
-Vector<BlitToScreen> WebXRInterfaceJS::commit_views(RID p_render_target, const Rect2 &p_screen_rect) {
+Vector<BlitToScreen> WebXRInterfaceJS::post_draw_viewport(RID p_render_target, const Rect2 &p_screen_rect) {
Vector<BlitToScreen> blit_to_screen;
if (!initialized) {
diff --git a/modules/webxr/webxr_interface_js.h b/modules/webxr/webxr_interface_js.h
index 8eddfbe484..31858194f6 100644
--- a/modules/webxr/webxr_interface_js.h
+++ b/modules/webxr/webxr_interface_js.h
@@ -88,7 +88,7 @@ public:
virtual Transform3D get_camera_transform() override;
virtual Transform3D get_transform_for_view(uint32_t p_view, const Transform3D &p_cam_transform) override;
virtual CameraMatrix get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) override;
- virtual Vector<BlitToScreen> commit_views(RID p_render_target, const Rect2 &p_screen_rect) override;
+ virtual Vector<BlitToScreen> post_draw_viewport(RID p_render_target, const Rect2 &p_screen_rect) override;
virtual void process() override;
diff --git a/platform/linuxbsd/os_linuxbsd.cpp b/platform/linuxbsd/os_linuxbsd.cpp
index b5f127bb16..e95a865636 100644
--- a/platform/linuxbsd/os_linuxbsd.cpp
+++ b/platform/linuxbsd/os_linuxbsd.cpp
@@ -448,7 +448,7 @@ Error OS_LinuxBSD::move_to_trash(const String &p_path) {
// Create needed directories for decided trash can location.
{
- DirAccess *dir_access = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ DirAccessRef dir_access = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
Error err = dir_access->make_dir_recursive(trash_path);
// Issue an error if trash can is not created properly.
@@ -457,7 +457,6 @@ Error OS_LinuxBSD::move_to_trash(const String &p_path) {
ERR_FAIL_COND_V_MSG(err != OK, err, "Could not create the trash path \"" + trash_path + "\"/files");
err = dir_access->make_dir_recursive(trash_path + "/info");
ERR_FAIL_COND_V_MSG(err != OK, err, "Could not create the trash path \"" + trash_path + "\"/info");
- memdelete(dir_access);
}
// The trash can is successfully created, now we check that we don't exceed our file name length limit.
@@ -497,16 +496,15 @@ Error OS_LinuxBSD::move_to_trash(const String &p_path) {
String trash_info = "[Trash Info]\nPath=" + p_path.uri_encode() + "\nDeletionDate=" + timestamp + "\n";
{
Error err;
- FileAccess *file = FileAccess::open(trash_path + "/info/" + file_name + ".trashinfo", FileAccess::WRITE, &err);
+ FileAccessRef file = FileAccess::open(trash_path + "/info/" + file_name + ".trashinfo", FileAccess::WRITE, &err);
ERR_FAIL_COND_V_MSG(err != OK, err, "Can't create trashinfo file:" + trash_path + "/info/" + file_name + ".trashinfo");
file->store_string(trash_info);
file->close();
// Rename our resource before moving it to the trash can.
- DirAccess *dir_access = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ DirAccessRef dir_access = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
err = dir_access->rename(p_path, p_path.get_base_dir() + "/" + file_name);
ERR_FAIL_COND_V_MSG(err != OK, err, "Can't rename file \"" + p_path + "\"");
- memdelete(dir_access);
}
// Move the given resource to the trash can.
diff --git a/scene/2d/collision_object_2d.cpp b/scene/2d/collision_object_2d.cpp
index 0f4e3c8bed..70c7e48fd4 100644
--- a/scene/2d/collision_object_2d.cpp
+++ b/scene/2d/collision_object_2d.cpp
@@ -268,7 +268,7 @@ uint32_t CollisionObject2D::create_shape_owner(Object *p_owner) {
id = shapes.back()->key() + 1;
}
- sd.owner = p_owner;
+ sd.owner_id = p_owner ? p_owner->get_instance_id() : ObjectID();
shapes[id] = sd;
@@ -382,7 +382,7 @@ Transform2D CollisionObject2D::shape_owner_get_transform(uint32_t p_owner) const
Object *CollisionObject2D::shape_owner_get_owner(uint32_t p_owner) const {
ERR_FAIL_COND_V(!shapes.has(p_owner), nullptr);
- return shapes[p_owner].owner;
+ return ObjectDB::get_instance(shapes[p_owner].owner_id);
}
void CollisionObject2D::shape_owner_add_shape(uint32_t p_owner, const Ref<Shape2D> &p_shape) {
diff --git a/scene/2d/collision_object_2d.h b/scene/2d/collision_object_2d.h
index 9463b2c429..f2b7eecc7b 100644
--- a/scene/2d/collision_object_2d.h
+++ b/scene/2d/collision_object_2d.h
@@ -59,7 +59,7 @@ private:
PhysicsServer2D::BodyMode body_mode = PhysicsServer2D::BODY_MODE_STATIC;
struct ShapeData {
- Object *owner = nullptr;
+ ObjectID owner_id;
Transform2D xform;
struct Shape {
Ref<Shape2D> shape;
diff --git a/scene/3d/collision_object_3d.cpp b/scene/3d/collision_object_3d.cpp
index df7c044f9e..3ab09550fa 100644
--- a/scene/3d/collision_object_3d.cpp
+++ b/scene/3d/collision_object_3d.cpp
@@ -484,7 +484,7 @@ uint32_t CollisionObject3D::create_shape_owner(Object *p_owner) {
id = shapes.back()->key() + 1;
}
- sd.owner = p_owner;
+ sd.owner_id = p_owner ? p_owner->get_instance_id() : ObjectID();
shapes[id] = sd;
@@ -563,7 +563,7 @@ Transform3D CollisionObject3D::shape_owner_get_transform(uint32_t p_owner) const
Object *CollisionObject3D::shape_owner_get_owner(uint32_t p_owner) const {
ERR_FAIL_COND_V(!shapes.has(p_owner), nullptr);
- return shapes[p_owner].owner;
+ return ObjectDB::get_instance(shapes[p_owner].owner_id);
}
void CollisionObject3D::shape_owner_add_shape(uint32_t p_owner, const Ref<Shape3D> &p_shape) {
diff --git a/scene/3d/collision_object_3d.h b/scene/3d/collision_object_3d.h
index f560753543..e92843d784 100644
--- a/scene/3d/collision_object_3d.h
+++ b/scene/3d/collision_object_3d.h
@@ -57,7 +57,7 @@ private:
PhysicsServer3D::BodyMode body_mode = PhysicsServer3D::BODY_MODE_STATIC;
struct ShapeData {
- Object *owner = nullptr;
+ ObjectID owner_id;
Transform3D xform;
struct ShapeBase {
RID debug_shape;
diff --git a/scene/animation/animation_blend_tree.cpp b/scene/animation/animation_blend_tree.cpp
index 2740103a4a..9d37b2d6ac 100644
--- a/scene/animation/animation_blend_tree.cpp
+++ b/scene/animation/animation_blend_tree.cpp
@@ -371,6 +371,8 @@ void AnimationNodeOneShot::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_use_sync", "enable"), &AnimationNodeOneShot::set_use_sync);
ClassDB::bind_method(D_METHOD("is_using_sync"), &AnimationNodeOneShot::is_using_sync);
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "mix_mode", PROPERTY_HINT_ENUM, "Blend,Add"), "set_mix_mode", "get_mix_mode");
+
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fadein_time", PROPERTY_HINT_RANGE, "0,60,0.01,or_greater"), "set_fadein_time", "get_fadein_time");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fadeout_time", PROPERTY_HINT_RANGE, "0,60,0.01,or_greater"), "set_fadeout_time", "get_fadeout_time");
diff --git a/scene/gui/base_button.cpp b/scene/gui/base_button.cpp
index bcb2b0c50e..5f937acb8d 100644
--- a/scene/gui/base_button.cpp
+++ b/scene/gui/base_button.cpp
@@ -382,8 +382,11 @@ Ref<ButtonGroup> BaseButton::get_button_group() const {
}
void BaseButton::set_shortcut_context(Node *p_node) {
- ERR_FAIL_NULL_MSG(p_node, "Shortcut context node can't be null.");
- shortcut_context = p_node->get_instance_id();
+ if (p_node != nullptr) {
+ shortcut_context = p_node->get_instance_id();
+ } else {
+ shortcut_context = ObjectID();
+ }
}
Node *BaseButton::get_shortcut_context() const {
diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp
index e9d346f943..bc386e9813 100644
--- a/scene/gui/rich_text_label.cpp
+++ b/scene/gui/rich_text_label.cpp
@@ -3154,7 +3154,7 @@ void RichTextLabel::append_text(const String &p_bbcode) {
indent_level++;
push_list(indent_level, LIST_NUMBERS, false);
pos = brk_end + 1;
- tag_stack.push_front(tag);
+ tag_stack.push_front("ol");
} else if (tag == "ol type=a") {
indent_level++;
push_list(indent_level, LIST_LETTERS, false);
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index fe1aaab557..7db1fae2b6 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -650,7 +650,7 @@ void TextEdit::_notification(int p_what) {
}
}
- bool draw_placeholder = text[0].length() == 0;
+ bool draw_placeholder = text.size() == 1 && text[0].length() == 0;
// Get the highlighted words.
String highlighted_text = get_selected_text();
@@ -6020,7 +6020,7 @@ void TextEdit::_update_scrollbars() {
h_scroll->set_begin(Point2(0, size.height - hmin.height));
h_scroll->set_end(Point2(size.width - vmin.width, size.height));
- bool draw_placeholder = text[0].length() == 0;
+ bool draw_placeholder = text.size() == 1 && text[0].length() == 0;
int visible_rows = get_visible_line_count();
int total_rows = draw_placeholder ? placeholder_wraped_rows.size() - 1 : get_total_visible_line_count();
@@ -6101,7 +6101,7 @@ void TextEdit::_scroll_moved(double p_to_val) {
}
if (v_scroll->is_visible_in_tree()) {
// Set line ofs and wrap ofs.
- bool draw_placeholder = text[0].length() == 0;
+ bool draw_placeholder = text.size() == 1 && text[0].length() == 0;
int v_scroll_i = floor(get_v_scroll());
int sc = 0;
@@ -6116,7 +6116,7 @@ void TextEdit::_scroll_moved(double p_to_val) {
}
}
n_line = MIN(n_line, text.size() - 1);
- int line_wrap_amount = (text[0].length() == 0) ? placeholder_wraped_rows.size() - 1 : get_line_wrap_count(n_line);
+ int line_wrap_amount = draw_placeholder ? placeholder_wraped_rows.size() - 1 : get_line_wrap_count(n_line);
int wi = line_wrap_amount - (sc - v_scroll_i - 1);
wi = CLAMP(wi, 0, line_wrap_amount);
diff --git a/scene/gui/view_panner.cpp b/scene/gui/view_panner.cpp
index 7476887877..71865b4864 100644
--- a/scene/gui/view_panner.cpp
+++ b/scene/gui/view_panner.cpp
@@ -81,7 +81,12 @@ bool ViewPanner::gui_input(const Ref<InputEvent> &p_event, Rect2 p_canvas_rect)
return false;
}
- if (mb->get_button_index() == MouseButton::MIDDLE || (enable_rmb && mb->get_button_index() == MouseButton::RIGHT) || (!simple_panning_enabled && mb->get_button_index() == MouseButton::LEFT && is_panning())) {
+ bool is_drag_event = mb->get_button_index() == MouseButton::MIDDLE ||
+ (enable_rmb && mb->get_button_index() == MouseButton::RIGHT) ||
+ (!simple_panning_enabled && mb->get_button_index() == MouseButton::LEFT && is_panning()) ||
+ (force_drag && mb->get_button_index() == MouseButton::LEFT);
+
+ if (is_drag_event) {
if (mb->is_pressed()) {
is_dragging = true;
} else {
@@ -166,6 +171,10 @@ bool ViewPanner::is_panning() const {
return is_dragging || pan_key_pressed;
}
+void ViewPanner::set_force_drag(bool p_force) {
+ force_drag = p_force;
+}
+
ViewPanner::ViewPanner() {
Array inputs;
inputs.append(InputEventKey::create_reference(Key::SPACE));
diff --git a/scene/gui/view_panner.h b/scene/gui/view_panner.h
index 8423c2a1c0..5b820c5f8f 100644
--- a/scene/gui/view_panner.h
+++ b/scene/gui/view_panner.h
@@ -48,6 +48,8 @@ public:
private:
bool is_dragging = false;
bool pan_key_pressed = false;
+ bool force_drag = false;
+
bool enable_rmb = false;
bool simple_panning_enabled = false;
@@ -70,6 +72,7 @@ public:
void setup(ControlScheme p_scheme, Ref<Shortcut> p_shortcut, bool p_simple_panning);
bool is_panning() const;
+ void set_force_drag(bool p_force);
bool gui_input(const Ref<InputEvent> &p_ev, Rect2 p_canvas_rect = Rect2());
void release_pan_key();
diff --git a/scene/resources/bit_map.cpp b/scene/resources/bit_map.cpp
index 25f169b6a2..c2988c2e8c 100644
--- a/scene/resources/bit_map.cpp
+++ b/scene/resources/bit_map.cpp
@@ -667,11 +667,13 @@ void BitMap::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_true_bit_count"), &BitMap::get_true_bit_count);
ClassDB::bind_method(D_METHOD("get_size"), &BitMap::get_size);
+ ClassDB::bind_method(D_METHOD("resize", "new_size"), &BitMap::resize);
ClassDB::bind_method(D_METHOD("_set_data"), &BitMap::_set_data);
ClassDB::bind_method(D_METHOD("_get_data"), &BitMap::_get_data);
ClassDB::bind_method(D_METHOD("grow_mask", "pixels", "rect"), &BitMap::grow_mask);
+ ClassDB::bind_method(D_METHOD("convert_to_image"), &BitMap::convert_to_image);
ClassDB::bind_method(D_METHOD("opaque_to_polygons", "rect", "epsilon"), &BitMap::_opaque_to_polygons_bind, DEFVAL(2.0));
ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_data", "_get_data");
diff --git a/scene/resources/environment.cpp b/scene/resources/environment.cpp
index 0afe040f33..b13ae9d016 100644
--- a/scene/resources/environment.cpp
+++ b/scene/resources/environment.cpp
@@ -728,6 +728,24 @@ float Environment::get_glow_hdr_luminance_cap() const {
return glow_hdr_luminance_cap;
}
+void Environment::set_glow_map_strength(float p_strength) {
+ glow_map_strength = p_strength;
+ _update_glow();
+}
+
+float Environment::get_glow_map_strength() const {
+ return glow_map_strength;
+}
+
+void Environment::set_glow_map(Ref<Texture> p_glow_map) {
+ glow_map = p_glow_map;
+ _update_glow();
+}
+
+Ref<Texture> Environment::get_glow_map() const {
+ return glow_map;
+}
+
void Environment::_update_glow() {
Vector<float> normalized_levels;
if (glow_normalize_levels) {
@@ -743,6 +761,15 @@ void Environment::_update_glow() {
normalized_levels = glow_levels;
}
+ float _glow_map_strength = 0.0f;
+ RID glow_map_rid;
+ if (glow_map.is_valid()) {
+ glow_map_rid = glow_map->get_rid();
+ _glow_map_strength = glow_map_strength;
+ } else {
+ glow_map_rid = RID();
+ }
+
RS::get_singleton()->environment_set_glow(
environment,
glow_enabled,
@@ -754,7 +781,9 @@ void Environment::_update_glow() {
RS::EnvironmentGlowBlendMode(glow_blend_mode),
glow_hdr_bleed_threshold,
glow_hdr_bleed_scale,
- glow_hdr_luminance_cap);
+ glow_hdr_luminance_cap,
+ _glow_map_strength,
+ glow_map_rid);
}
// Fog
@@ -1332,6 +1361,10 @@ void Environment::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_glow_hdr_bleed_scale"), &Environment::get_glow_hdr_bleed_scale);
ClassDB::bind_method(D_METHOD("set_glow_hdr_luminance_cap", "amount"), &Environment::set_glow_hdr_luminance_cap);
ClassDB::bind_method(D_METHOD("get_glow_hdr_luminance_cap"), &Environment::get_glow_hdr_luminance_cap);
+ ClassDB::bind_method(D_METHOD("set_glow_map_strength", "strength"), &Environment::set_glow_map_strength);
+ ClassDB::bind_method(D_METHOD("get_glow_map_strength"), &Environment::get_glow_map_strength);
+ ClassDB::bind_method(D_METHOD("set_glow_map", "mode"), &Environment::set_glow_map);
+ ClassDB::bind_method(D_METHOD("get_glow_map"), &Environment::get_glow_map);
ADD_GROUP("Glow", "glow_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "glow_enabled"), "set_glow_enabled", "is_glow_enabled");
@@ -1351,6 +1384,8 @@ void Environment::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "glow_hdr_threshold", PROPERTY_HINT_RANGE, "0.0,4.0,0.01"), "set_glow_hdr_bleed_threshold", "get_glow_hdr_bleed_threshold");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "glow_hdr_scale", PROPERTY_HINT_RANGE, "0.0,4.0,0.01"), "set_glow_hdr_bleed_scale", "get_glow_hdr_bleed_scale");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "glow_hdr_luminance_cap", PROPERTY_HINT_RANGE, "0.0,256.0,0.01"), "set_glow_hdr_luminance_cap", "get_glow_hdr_luminance_cap");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "glow_map_strength", PROPERTY_HINT_RANGE, "0.0,1.0,0.01"), "set_glow_map_strength", "get_glow_map_strength");
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "glow_map", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_glow_map", "get_glow_map");
// Fog
diff --git a/scene/resources/environment.h b/scene/resources/environment.h
index 3f05315013..b04723a221 100644
--- a/scene/resources/environment.h
+++ b/scene/resources/environment.h
@@ -170,6 +170,8 @@ private:
float glow_hdr_bleed_threshold = 1.0;
float glow_hdr_bleed_scale = 2.0;
float glow_hdr_luminance_cap = 12.0;
+ float glow_map_strength = 0.8f;
+ Ref<Texture> glow_map;
void _update_glow();
// Fog
@@ -360,6 +362,10 @@ public:
float get_glow_hdr_bleed_scale() const;
void set_glow_hdr_luminance_cap(float p_amount);
float get_glow_hdr_luminance_cap() const;
+ void set_glow_map_strength(float p_strength);
+ float get_glow_map_strength() const;
+ void set_glow_map(Ref<Texture> p_glow_map);
+ Ref<Texture> get_glow_map() const;
// Fog
diff --git a/scene/resources/mesh_library.cpp b/scene/resources/mesh_library.cpp
index 3db839a1d0..5168bf83eb 100644
--- a/scene/resources/mesh_library.cpp
+++ b/scene/resources/mesh_library.cpp
@@ -30,6 +30,8 @@
#include "mesh_library.h"
+#include "box_shape_3d.h"
+
bool MeshLibrary::_set(const StringName &p_name, const Variant &p_value) {
String name = p_name;
if (name.begins_with("item/")) {
@@ -255,12 +257,35 @@ int MeshLibrary::get_last_unused_item_id() const {
}
void MeshLibrary::_set_item_shapes(int p_item, const Array &p_shapes) {
- ERR_FAIL_COND(p_shapes.size() & 1);
+ Array arr_shapes = p_shapes;
+ int size = p_shapes.size();
+ if (size & 1) {
+ ERR_FAIL_COND_MSG(!item_map.has(p_item), "Requested for nonexistent MeshLibrary item '" + itos(p_item) + "'.");
+ int prev_size = item_map[p_item].shapes.size() * 2;
+
+ if (prev_size < size) {
+ // Check if last element is a shape.
+ Ref<Shape3D> shape = arr_shapes[size - 1];
+ if (shape.is_null()) {
+ Ref<BoxShape3D> box_shape;
+ box_shape.instantiate();
+ arr_shapes[size - 1] = box_shape;
+ }
+
+ // Make sure the added element is a Transform3D.
+ arr_shapes.push_back(Transform3D());
+ size++;
+ } else {
+ size--;
+ arr_shapes.resize(size);
+ }
+ }
+
Vector<ShapeData> shapes;
- for (int i = 0; i < p_shapes.size(); i += 2) {
+ for (int i = 0; i < size; i += 2) {
ShapeData sd;
- sd.shape = p_shapes[i + 0];
- sd.local_transform = p_shapes[i + 1];
+ sd.shape = arr_shapes[i + 0];
+ sd.local_transform = arr_shapes[i + 1];
if (sd.shape.is_valid()) {
shapes.push_back(sd);
diff --git a/scene/resources/sky_material.cpp b/scene/resources/sky_material.cpp
index 6ec16f12df..c5d5ba2912 100644
--- a/scene/resources/sky_material.cpp
+++ b/scene/resources/sky_material.cpp
@@ -292,7 +292,6 @@ ProceduralSkyMaterial::ProceduralSkyMaterial() {
}
ProceduralSkyMaterial::~ProceduralSkyMaterial() {
- RS::get_singleton()->material_set_shader(_get_material(), RID());
}
/////////////////////////////////////////
@@ -389,7 +388,6 @@ PanoramaSkyMaterial::PanoramaSkyMaterial() {
}
PanoramaSkyMaterial::~PanoramaSkyMaterial() {
- RS::get_singleton()->material_set_shader(_get_material(), RID());
}
//////////////////////////////////
diff --git a/servers/rendering/rasterizer_dummy.h b/servers/rendering/rasterizer_dummy.h
index 83da8388e4..7032f3fb03 100644
--- a/servers/rendering/rasterizer_dummy.h
+++ b/servers/rendering/rasterizer_dummy.h
@@ -109,7 +109,7 @@ public:
void environment_set_canvas_max_layer(RID p_env, int p_max_layer) override {}
void environment_set_ambient_light(RID p_env, const Color &p_color, RS::EnvironmentAmbientSource p_ambient = RS::ENV_AMBIENT_SOURCE_BG, float p_energy = 1.0, float p_sky_contribution = 0.0, RS::EnvironmentReflectionSource p_reflection_source = RS::ENV_REFLECTION_SOURCE_BG) override {}
- void environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap) override {}
+ void environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, float p_glow_map_strength, RID p_glow_map) override {}
void environment_glow_set_use_bicubic_upscale(bool p_enable) override {}
void environment_glow_set_use_high_quality(bool p_enable) override {}
diff --git a/servers/rendering/renderer_rd/effects_rd.cpp b/servers/rendering/renderer_rd/effects_rd.cpp
index 4ab50782df..25a366aa4b 100644
--- a/servers/rendering/renderer_rd/effects_rd.cpp
+++ b/servers/rendering/renderer_rd/effects_rd.cpp
@@ -115,6 +115,43 @@ RID EffectsRD::_get_uniform_set_from_texture(RID p_texture, bool p_use_mipmaps)
return uniform_set;
}
+RID EffectsRD::_get_uniform_set_from_texture_pair(RID p_texture1, RID p_texture2, bool p_use_mipmaps) {
+ TexturePair tp;
+ tp.texture1 = p_texture1;
+ tp.texture2 = p_texture2;
+
+ if (texture_pair_to_uniform_set_cache.has(tp)) {
+ RID uniform_set = texture_pair_to_uniform_set_cache[tp];
+ if (RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
+ return uniform_set;
+ }
+ }
+
+ Vector<RD::Uniform> uniforms;
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
+ u.binding = 0;
+ u.ids.push_back(p_use_mipmaps ? default_mipmap_sampler : default_sampler);
+ u.ids.push_back(p_texture1);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
+ u.binding = 1;
+ u.ids.push_back(p_use_mipmaps ? default_mipmap_sampler : default_sampler);
+ u.ids.push_back(p_texture2);
+ uniforms.push_back(u);
+ }
+ // anything with the same configuration (one texture in binding 0 for set 0), is good
+ RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, tonemap.shader.version_get_shader(tonemap.shader_version, 0), 2);
+
+ texture_pair_to_uniform_set_cache[tp] = uniform_set;
+
+ return uniform_set;
+}
+
RID EffectsRD::_get_compute_uniform_set_from_texture(RID p_texture, bool p_use_mipmaps) {
if (texture_to_compute_uniform_set_cache.has(p_texture)) {
RID uniform_set = texture_to_compute_uniform_set_cache[p_texture];
@@ -828,6 +865,7 @@ void EffectsRD::tonemapper(RID p_source_color, RID p_dst_framebuffer, const Tone
tonemap.push_constant.use_glow = p_settings.use_glow;
tonemap.push_constant.glow_intensity = p_settings.glow_intensity;
+ tonemap.push_constant.glow_map_strength = p_settings.glow_map_strength;
tonemap.push_constant.glow_levels[0] = p_settings.glow_levels[0]; // clean this up to just pass by pointer or something
tonemap.push_constant.glow_levels[1] = p_settings.glow_levels[1];
tonemap.push_constant.glow_levels[2] = p_settings.glow_levels[2];
@@ -867,7 +905,7 @@ void EffectsRD::tonemapper(RID p_source_color, RID p_dst_framebuffer, const Tone
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, tonemap.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dst_framebuffer), false, RD::get_singleton()->draw_list_get_current_pass()));
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_color), 0);
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_settings.exposure_texture), 1);
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_settings.glow_texture, true), 2);
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture_pair(p_settings.glow_texture, p_settings.glow_map, true), 2);
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_settings.color_correction_texture), 3);
RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
@@ -907,7 +945,7 @@ void EffectsRD::tonemapper(RD::DrawListID p_subpass_draw_list, RID p_source_colo
RD::get_singleton()->draw_list_bind_render_pipeline(p_subpass_draw_list, tonemap.pipelines[mode].get_render_pipeline(RD::INVALID_ID, p_dst_format_id, false, RD::get_singleton()->draw_list_get_current_pass()));
RD::get_singleton()->draw_list_bind_uniform_set(p_subpass_draw_list, _get_uniform_set_for_input(p_source_color), 0);
RD::get_singleton()->draw_list_bind_uniform_set(p_subpass_draw_list, _get_uniform_set_from_texture(p_settings.exposure_texture), 1); // should be set to a default texture, it's ignored
- RD::get_singleton()->draw_list_bind_uniform_set(p_subpass_draw_list, _get_uniform_set_from_texture(p_settings.glow_texture, true), 2); // should be set to a default texture, it's ignored
+ RD::get_singleton()->draw_list_bind_uniform_set(p_subpass_draw_list, _get_uniform_set_from_texture_pair(p_settings.glow_texture, p_settings.glow_map, true), 2); // should be set to a default texture, it's ignored
RD::get_singleton()->draw_list_bind_uniform_set(p_subpass_draw_list, _get_uniform_set_from_texture(p_settings.color_correction_texture), 3);
RD::get_singleton()->draw_list_bind_index_array(p_subpass_draw_list, index_array);
diff --git a/servers/rendering/renderer_rd/effects_rd.h b/servers/rendering/renderer_rd/effects_rd.h
index a3fb4db3df..1a080756a8 100644
--- a/servers/rendering/renderer_rd/effects_rd.h
+++ b/servers/rendering/renderer_rd/effects_rd.h
@@ -274,7 +274,7 @@ private:
uint32_t glow_texture_size[2]; // 8 - 40
float glow_intensity; // 4 - 44
- uint32_t pad3; // 4 - 48
+ float glow_map_strength; // 4 - 48
uint32_t glow_mode; // 4 - 52
float glow_levels[7]; // 28 - 80
@@ -874,6 +874,7 @@ private:
}
};
+ Map<TexturePair, RID> texture_pair_to_uniform_set_cache;
Map<RID, RID> texture_to_compute_uniform_set_cache;
Map<TexturePair, RID> texture_pair_to_compute_uniform_set_cache;
Map<TexturePair, RID> image_pair_to_compute_uniform_set_cache;
@@ -882,6 +883,7 @@ private:
RID _get_uniform_set_from_image(RID p_texture);
RID _get_uniform_set_for_input(RID p_texture);
RID _get_uniform_set_from_texture(RID p_texture, bool p_use_mipmaps = false);
+ RID _get_uniform_set_from_texture_pair(RID p_texture1, RID p_texture2, bool p_use_mipmaps = false);
RID _get_compute_uniform_set_from_texture(RID p_texture, bool p_use_mipmaps = false);
RID _get_compute_uniform_set_from_texture_and_sampler(RID p_texture, RID p_sampler);
RID _get_compute_uniform_set_from_texture_pair(RID p_texture, RID p_texture2, bool p_use_mipmaps = false);
@@ -943,10 +945,12 @@ public:
GlowMode glow_mode = GLOW_MODE_ADD;
float glow_intensity = 1.0;
+ float glow_map_strength = 0.0f;
float glow_levels[7] = { 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0 };
Vector2i glow_texture_size;
bool glow_use_bicubic_upscale = false;
RID glow_texture;
+ RID glow_map;
RS::EnvironmentToneMapper tonemap_mode = RS::ENV_TONE_MAPPER_LINEAR;
float exposure = 1.0;
diff --git a/servers/rendering/renderer_rd/renderer_scene_environment_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_environment_rd.cpp
index 0d0d7513d0..0d9477d850 100644
--- a/servers/rendering/renderer_rd/renderer_scene_environment_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_scene_environment_rd.cpp
@@ -54,7 +54,7 @@ void RendererSceneEnvironmentRD::set_tonemap(RS::EnvironmentToneMapper p_tone_ma
auto_exp_scale = p_auto_exp_scale;
}
-void RendererSceneEnvironmentRD::set_glow(bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap) {
+void RendererSceneEnvironmentRD::set_glow(bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, float p_glow_map_strength, RID p_glow_map) {
ERR_FAIL_COND_MSG(p_levels.size() != 7, "Size of array of glow levels must be 7");
glow_enabled = p_enable;
glow_levels = p_levels;
@@ -66,6 +66,8 @@ void RendererSceneEnvironmentRD::set_glow(bool p_enable, Vector<float> p_levels,
glow_hdr_bleed_threshold = p_hdr_bleed_threshold;
glow_hdr_bleed_scale = p_hdr_bleed_scale;
glow_hdr_luminance_cap = p_hdr_luminance_cap;
+ glow_map_strength = p_glow_map_strength;
+ glow_map = p_glow_map;
}
void RendererSceneEnvironmentRD::set_sdfgi(bool p_enable, int p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) {
diff --git a/servers/rendering/renderer_rd/renderer_scene_environment_rd.h b/servers/rendering/renderer_rd/renderer_scene_environment_rd.h
index 629d224b49..ed26fd467b 100644
--- a/servers/rendering/renderer_rd/renderer_scene_environment_rd.h
+++ b/servers/rendering/renderer_rd/renderer_scene_environment_rd.h
@@ -102,6 +102,8 @@ public:
float glow_hdr_bleed_threshold = 1.0;
float glow_hdr_luminance_cap = 12.0;
float glow_hdr_bleed_scale = 2.0;
+ float glow_map_strength = 0.0f;
+ RID glow_map = RID();
/// SSAO
@@ -154,7 +156,7 @@ public:
void set_ambient_light(const Color &p_color, RS::EnvironmentAmbientSource p_ambient, float p_energy, float p_sky_contribution, RS::EnvironmentReflectionSource p_reflection_source);
void set_tonemap(RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale);
- void set_glow(bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap);
+ void set_glow(bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, float p_glow_map_strength, RID p_glow_map);
void set_sdfgi(bool p_enable, int p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias);
void set_fog(bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_fog_aerial_perspective);
void set_volumetric_fog(bool p_enable, float p_density, const Color &p_scatterin, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject);
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
index deaf613836..7a50fd0e59 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
@@ -289,10 +289,10 @@ void RendererSceneRenderRD::environment_set_tonemap(RID p_env, RS::EnvironmentTo
env->set_tonemap(p_tone_mapper, p_exposure, p_white, p_auto_exposure, p_min_luminance, p_max_luminance, p_auto_exp_speed, p_auto_exp_scale);
}
-void RendererSceneRenderRD::environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap) {
+void RendererSceneRenderRD::environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, float p_glow_map_strength, RID p_glow_map) {
RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
ERR_FAIL_COND(!env);
- env->set_glow(p_enable, p_levels, p_intensity, p_strength, p_mix, p_bloom_threshold, p_blend_mode, p_hdr_bleed_threshold, p_hdr_bleed_scale, p_hdr_luminance_cap);
+ env->set_glow(p_enable, p_levels, p_intensity, p_strength, p_mix, p_bloom_threshold, p_blend_mode, p_hdr_bleed_threshold, p_hdr_bleed_scale, p_hdr_luminance_cap, p_glow_map_strength, p_glow_map);
}
void RendererSceneRenderRD::environment_glow_set_use_bicubic_upscale(bool p_enable) {
@@ -1920,6 +1920,11 @@ void RendererSceneRenderRD::_free_render_buffer_data(RenderBuffers *rb) {
rb->ambient_buffer = RID();
rb->reflection_buffer = RID();
}
+
+ if (rb->gi.voxel_gi_buffer.is_valid()) {
+ RD::get_singleton()->free(rb->gi.voxel_gi_buffer);
+ rb->gi.voxel_gi_buffer = RID();
+ }
}
void RendererSceneRenderRD::_process_sss(RID p_render_buffers, const CameraMatrix &p_camera) {
@@ -2496,8 +2501,17 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
tonemap.glow_texture_size.y = rb->blur[1].mipmaps[0].height;
tonemap.glow_use_bicubic_upscale = glow_bicubic_upscale;
tonemap.glow_texture = rb->blur[1].texture;
+ if (env->glow_map.is_valid()) {
+ tonemap.glow_map_strength = env->glow_map_strength;
+ tonemap.glow_map = storage->texture_get_rd_texture(env->glow_map);
+ } else {
+ tonemap.glow_map_strength = 0.0f;
+ tonemap.glow_map = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE);
+ }
+
} else {
tonemap.glow_texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK);
+ tonemap.glow_map = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE);
}
if (rb->screen_space_aa == RS::VIEWPORT_SCREEN_SPACE_AA_FXAA) {
@@ -2590,6 +2604,7 @@ void RendererSceneRenderRD::_post_process_subpass(RID p_source_texture, RID p_fr
tonemap.use_glow = false;
tonemap.glow_texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK);
+ tonemap.glow_map = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE);
tonemap.use_auto_exposure = false;
tonemap.exposure_texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE);
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.h b/servers/rendering/renderer_rd/renderer_scene_render_rd.h
index 592618ae05..899d2d763d 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_rd.h
+++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.h
@@ -1061,7 +1061,7 @@ public:
virtual bool is_environment(RID p_env) const override;
- virtual void environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap) override;
+ virtual void environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, float p_glow_map_strength, RID p_glow_map) override;
virtual void environment_glow_set_use_bicubic_upscale(bool p_enable) override;
virtual void environment_glow_set_use_high_quality(bool p_enable) override;
diff --git a/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp
index 856ea5e74d..f6f39230f8 100644
--- a/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp
@@ -590,6 +590,7 @@ void RendererSceneSkyRD::Sky::free(RendererStorageRD *p_storage) {
if (material.is_valid()) {
p_storage->free(material);
+ material = RID();
}
}
diff --git a/servers/rendering/renderer_rd/shaders/tonemap.glsl b/servers/rendering/renderer_rd/shaders/tonemap.glsl
index 948c6e1e39..41d41758f4 100644
--- a/servers/rendering/renderer_rd/shaders/tonemap.glsl
+++ b/servers/rendering/renderer_rd/shaders/tonemap.glsl
@@ -45,6 +45,7 @@ layout(set = 0, binding = 0) uniform sampler2D source_color;
layout(set = 1, binding = 0) uniform sampler2D source_auto_exposure;
layout(set = 2, binding = 0) uniform sampler2D source_glow;
+layout(set = 2, binding = 1) uniform sampler2D glow_map;
#ifdef USE_1D_LUT
layout(set = 3, binding = 0) uniform sampler2D source_color_correction;
@@ -63,7 +64,7 @@ layout(push_constant, binding = 1, std430) uniform Params {
uvec2 glow_texture_size;
float glow_intensity;
- uint pad3;
+ float glow_map_strength;
uint glow_mode;
float glow_levels[7];
@@ -405,6 +406,9 @@ void main() {
#ifndef SUBPASS
if (params.use_glow && params.glow_mode == GLOW_MODE_MIX) {
vec3 glow = gather_glow(source_glow, uv_interp) * params.luminance_multiplier;
+ if (params.glow_map_strength > 0.001) {
+ glow = mix(glow, texture(glow_map, uv_interp).rgb * glow, params.glow_map_strength);
+ }
color.rgb = mix(color.rgb, glow, params.glow_intensity);
}
@@ -425,9 +429,11 @@ void main() {
#ifndef SUBPASS
// Glow
-
if (params.use_glow && params.glow_mode != GLOW_MODE_MIX) {
vec3 glow = gather_glow(source_glow, uv_interp) * params.glow_intensity * params.luminance_multiplier;
+ if (params.glow_map_strength > 0.001) {
+ glow = mix(glow, texture(glow_map, uv_interp).rgb * glow, params.glow_map_strength);
+ }
// high dynamic range -> SRGB
glow = apply_tonemapping(glow, params.white);
diff --git a/servers/rendering/renderer_scene.h b/servers/rendering/renderer_scene.h
index 426d22f83e..406d946e12 100644
--- a/servers/rendering/renderer_scene.h
+++ b/servers/rendering/renderer_scene.h
@@ -131,7 +131,7 @@ public:
virtual void environment_set_canvas_max_layer(RID p_env, int p_max_layer) = 0;
virtual void environment_set_ambient_light(RID p_env, const Color &p_color, RS::EnvironmentAmbientSource p_ambient = RS::ENV_AMBIENT_SOURCE_BG, float p_energy = 1.0, float p_sky_contribution = 0.0, RS::EnvironmentReflectionSource p_reflection_source = RS::ENV_REFLECTION_SOURCE_BG) = 0;
- virtual void environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap) = 0;
+ virtual void environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, float p_glow_map_strength, RID p_glow_map) = 0;
virtual void environment_glow_set_use_bicubic_upscale(bool p_enable) = 0;
virtual void environment_glow_set_use_high_quality(bool p_enable) = 0;
diff --git a/servers/rendering/renderer_scene_cull.h b/servers/rendering/renderer_scene_cull.h
index 1e770ef66c..ed0229f0f9 100644
--- a/servers/rendering/renderer_scene_cull.h
+++ b/servers/rendering/renderer_scene_cull.h
@@ -1113,7 +1113,7 @@ public:
PASS6(environment_set_ssil, RID, bool, float, float, float, float)
PASS6(environment_set_ssil_quality, RS::EnvironmentSSILQuality, bool, float, int, float, float)
- PASS11(environment_set_glow, RID, bool, Vector<float>, float, float, float, float, RS::EnvironmentGlowBlendMode, float, float, float)
+ PASS13(environment_set_glow, RID, bool, Vector<float>, float, float, float, float, RS::EnvironmentGlowBlendMode, float, float, float, float, RID)
PASS1(environment_glow_set_use_bicubic_upscale, bool)
PASS1(environment_glow_set_use_high_quality, bool)
diff --git a/servers/rendering/renderer_scene_render.h b/servers/rendering/renderer_scene_render.h
index c34a46d166..3eb90ccc4d 100644
--- a/servers/rendering/renderer_scene_render.h
+++ b/servers/rendering/renderer_scene_render.h
@@ -123,7 +123,7 @@ public:
virtual void environment_set_camera_feed_id(RID p_env, int p_camera_feed_id) = 0;
#endif
- virtual void environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap) = 0;
+ virtual void environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, float p_glow_map_strength, RID p_glow_map) = 0;
virtual void environment_glow_set_use_bicubic_upscale(bool p_enable) = 0;
virtual void environment_glow_set_use_high_quality(bool p_enable) = 0;
diff --git a/servers/rendering/renderer_viewport.cpp b/servers/rendering/renderer_viewport.cpp
index 17a665922f..be96793ec4 100644
--- a/servers/rendering/renderer_viewport.cpp
+++ b/servers/rendering/renderer_viewport.cpp
@@ -549,8 +549,13 @@ void RendererViewport::draw_viewports() {
// get our xr interface in case we need it
Ref<XRInterface> xr_interface;
- if (XRServer::get_singleton() != nullptr) {
- xr_interface = XRServer::get_singleton()->get_primary_interface();
+ XRServer *xr_server = XRServer::get_singleton();
+ if (xr_server != nullptr) {
+ // let our XR server know we're about to render our frames so we can get our frame timing
+ xr_server->pre_render();
+
+ // retrieve the interface responsible for rendering
+ xr_interface = xr_server->get_primary_interface();
}
if (Engine::get_singleton()->is_editor_hint()) {
@@ -582,19 +587,26 @@ void RendererViewport::draw_viewports() {
bool visible = vp->viewport_to_screen_rect != Rect2();
- if (vp->use_xr && xr_interface.is_valid()) {
- visible = true; // XR viewport is always visible regardless of update mode, output is sent to HMD.
-
- // Override our size, make sure it matches our required size and is created as a stereo target
- Size2 xr_size = xr_interface->get_render_target_size();
-
- // Would have been nice if we could call viewport_set_size here,
- // but alas that takes our RID and we now have our pointer,
- // also we only check if view_count changes in render_target_set_size so we need to call that for this to reliably change
- vp->occlusion_buffer_dirty = vp->occlusion_buffer_dirty || (vp->size != xr_size);
- vp->size = xr_size;
- uint32_t view_count = xr_interface->get_view_count();
- RSG::storage->render_target_set_size(vp->render_target, vp->size.x, vp->size.y, view_count);
+ if (vp->use_xr) {
+ if (xr_interface.is_valid()) {
+ // Override our size, make sure it matches our required size and is created as a stereo target
+ Size2 xr_size = xr_interface->get_render_target_size();
+
+ // Would have been nice if we could call viewport_set_size here,
+ // but alas that takes our RID and we now have our pointer,
+ // also we only check if view_count changes in render_target_set_size so we need to call that for this to reliably change
+ vp->occlusion_buffer_dirty = vp->occlusion_buffer_dirty || (vp->size != xr_size);
+ vp->size = xr_size;
+ uint32_t view_count = xr_interface->get_view_count();
+ RSG::storage->render_target_set_size(vp->render_target, vp->size.x, vp->size.y, view_count);
+
+ // Inform xr interface we're about to render its viewport, if this returns false we don't render
+ visible = xr_interface->pre_draw_viewport(vp->render_target);
+ } else {
+ // don't render anything
+ visible = false;
+ vp->size = Size2();
+ }
}
if (vp->update_mode == RS::VIEWPORT_UPDATE_ALWAYS || vp->update_mode == RS::VIEWPORT_UPDATE_ONCE) {
@@ -647,7 +659,7 @@ void RendererViewport::draw_viewports() {
// measure
// commit our eyes
- Vector<BlitToScreen> blits = xr_interface->commit_views(vp->render_target, vp->viewport_to_screen_rect);
+ Vector<BlitToScreen> blits = xr_interface->post_draw_viewport(vp->render_target, vp->viewport_to_screen_rect);
if (vp->viewport_to_screen != DisplayServer::INVALID_WINDOW_ID && blits.size() > 0) {
if (!blit_to_screen_list.has(vp->viewport_to_screen)) {
blit_to_screen_list[vp->viewport_to_screen] = Vector<BlitToScreen>();
@@ -657,9 +669,6 @@ void RendererViewport::draw_viewports() {
blit_to_screen_list[vp->viewport_to_screen].push_back(blits[b]);
}
}
-
- // and for our frame timing, mark when we've finished committing our eyes
- XRServer::get_singleton()->_mark_commit();
} else {
RSG::storage->render_target_set_external_texture(vp->render_target, 0);
diff --git a/servers/rendering/rendering_server_default.cpp b/servers/rendering/rendering_server_default.cpp
index d7e9d210db..d93aad5d7b 100644
--- a/servers/rendering/rendering_server_default.cpp
+++ b/servers/rendering/rendering_server_default.cpp
@@ -93,6 +93,12 @@ void RenderingServerDefault::_draw(bool p_swap_buffers, double frame_step) {
RSG::rasterizer->end_frame(p_swap_buffers);
+ XRServer *xr_server = XRServer::get_singleton();
+ if (xr_server != nullptr) {
+ // let our XR server know we're done so we can get our frame timing
+ xr_server->end_frame();
+ }
+
RSG::canvas->update_visibility_notifiers();
RSG::scene->update_visibility_notifiers();
diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h
index 54fd897a77..6d2c36537b 100644
--- a/servers/rendering/rendering_server_default.h
+++ b/servers/rendering/rendering_server_default.h
@@ -628,7 +628,7 @@ public:
FUNC6(environment_set_ssil, RID, bool, float, float, float, float)
FUNC6(environment_set_ssil_quality, EnvironmentSSILQuality, bool, float, int, float, float)
- FUNC11(environment_set_glow, RID, bool, Vector<float>, float, float, float, float, EnvironmentGlowBlendMode, float, float, float)
+ FUNC13(environment_set_glow, RID, bool, Vector<float>, float, float, float, float, EnvironmentGlowBlendMode, float, float, float, float, RID)
FUNC1(environment_glow_set_use_bicubic_upscale, bool)
FUNC1(environment_glow_set_use_high_quality, bool)
diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp
index f16f66544a..59f9b0c808 100644
--- a/servers/rendering/shader_language.cpp
+++ b/servers/rendering/shader_language.cpp
@@ -7799,7 +7799,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
}
if (uniform) {
- if (uniform_scope == ShaderNode::Uniform::SCOPE_GLOBAL) {
+ if (uniform_scope == ShaderNode::Uniform::SCOPE_GLOBAL && Engine::get_singleton()->is_editor_hint()) { // Type checking for global uniforms is not allowed outside the editor.
//validate global uniform
DataType gvtype = global_var_get_type_func(name);
if (gvtype == TYPE_MAX) {
diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp
index 84e54eab22..584abbc351 100644
--- a/servers/rendering_server.cpp
+++ b/servers/rendering_server.cpp
@@ -2317,7 +2317,7 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("environment_set_bg_energy", "env", "energy"), &RenderingServer::environment_set_bg_energy);
ClassDB::bind_method(D_METHOD("environment_set_canvas_max_layer", "env", "max_layer"), &RenderingServer::environment_set_canvas_max_layer);
ClassDB::bind_method(D_METHOD("environment_set_ambient_light", "env", "color", "ambient", "energy", "sky_contibution", "reflection_source"), &RenderingServer::environment_set_ambient_light, DEFVAL(RS::ENV_AMBIENT_SOURCE_BG), DEFVAL(1.0), DEFVAL(0.0), DEFVAL(RS::ENV_REFLECTION_SOURCE_BG));
- ClassDB::bind_method(D_METHOD("environment_set_glow", "env", "enable", "levels", "intensity", "strength", "mix", "bloom_threshold", "blend_mode", "hdr_bleed_threshold", "hdr_bleed_scale", "hdr_luminance_cap"), &RenderingServer::environment_set_glow);
+ ClassDB::bind_method(D_METHOD("environment_set_glow", "env", "enable", "levels", "intensity", "strength", "mix", "bloom_threshold", "blend_mode", "hdr_bleed_threshold", "hdr_bleed_scale", "hdr_luminance_cap", "glow_map_strength", "glow_map"), &RenderingServer::environment_set_glow);
ClassDB::bind_method(D_METHOD("environment_set_tonemap", "env", "tone_mapper", "exposure", "white", "auto_exposure", "min_luminance", "max_luminance", "auto_exp_speed", "auto_exp_grey"), &RenderingServer::environment_set_tonemap);
ClassDB::bind_method(D_METHOD("environment_set_adjustment", "env", "enable", "brightness", "contrast", "saturation", "use_1d_color_correction", "color_correction"), &RenderingServer::environment_set_adjustment);
ClassDB::bind_method(D_METHOD("environment_set_ssr", "env", "enable", "max_steps", "fade_in", "fade_out", "depth_tolerance"), &RenderingServer::environment_set_ssr);
diff --git a/servers/rendering_server.h b/servers/rendering_server.h
index b067db3d27..472fff1bf1 100644
--- a/servers/rendering_server.h
+++ b/servers/rendering_server.h
@@ -991,7 +991,7 @@ public:
ENV_GLOW_BLEND_MODE_MIX,
};
- virtual void environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap) = 0;
+ virtual void environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, float p_glow_map_strength, RID p_glow_map) = 0;
virtual void environment_glow_set_use_bicubic_upscale(bool p_enable) = 0;
virtual void environment_glow_set_use_high_quality(bool p_enable) = 0;
diff --git a/servers/xr/xr_interface.cpp b/servers/xr/xr_interface.cpp
index 758f2416ec..7ae111b5e7 100644
--- a/servers/xr/xr_interface.cpp
+++ b/servers/xr/xr_interface.cpp
@@ -168,8 +168,5 @@ XRInterface::TrackingStatus XRInterface::get_tracking_status() const {
return XR_UNKNOWN_TRACKING;
}
-void XRInterface::notification(int p_what) {
-}
-
void XRInterface::trigger_haptic_pulse(const String &p_action_name, const StringName &p_tracker_name, double p_frequency, double p_amplitude, double p_duration_sec, double p_delay_sec) {
}
diff --git a/servers/xr/xr_interface.h b/servers/xr/xr_interface.h
index aee98f8fee..6e105ffc26 100644
--- a/servers/xr/xr_interface.h
+++ b/servers/xr/xr_interface.h
@@ -123,10 +123,13 @@ public:
// note, external color/depth/vrs texture support will be added here soon.
- virtual Vector<BlitToScreen> commit_views(RID p_render_target, const Rect2 &p_screen_rect) = 0; /* commit rendered views to the XR interface */
-
virtual void process() = 0;
- virtual void notification(int p_what);
+ virtual void pre_render(){};
+ virtual bool pre_draw_viewport(RID p_render_target) { return true; }; /* inform XR interface we are about to start our viewport draw process */
+ virtual Vector<BlitToScreen> post_draw_viewport(RID p_render_target, const Rect2 &p_screen_rect) = 0; /* inform XR interface we finished our viewport draw process */
+ virtual void end_frame(){};
+
+ virtual void notification(int p_what){};
XRInterface();
~XRInterface();
diff --git a/servers/xr/xr_interface_extension.cpp b/servers/xr/xr_interface_extension.cpp
index 9dae3b162d..18131c1e89 100644
--- a/servers/xr/xr_interface_extension.cpp
+++ b/servers/xr/xr_interface_extension.cpp
@@ -52,9 +52,12 @@ void XRInterfaceExtension::_bind_methods() {
GDVIRTUAL_BIND(_get_transform_for_view, "view", "cam_transform");
GDVIRTUAL_BIND(_get_projection_for_view, "view", "aspect", "z_near", "z_far");
- GDVIRTUAL_BIND(_commit_views, "render_target", "screen_rect");
-
GDVIRTUAL_BIND(_process);
+ GDVIRTUAL_BIND(_pre_render);
+ GDVIRTUAL_BIND(_pre_draw_viewport, "render_target");
+ GDVIRTUAL_BIND(_post_draw_viewport, "render_target", "screen_rect");
+ GDVIRTUAL_BIND(_end_frame);
+
GDVIRTUAL_BIND(_notification, "what");
/** input and output **/
@@ -274,7 +277,7 @@ CameraMatrix XRInterfaceExtension::get_projection_for_view(uint32_t p_view, doub
void XRInterfaceExtension::add_blit(RID p_render_target, Rect2 p_src_rect, Rect2i p_dst_rect, bool p_use_layer, uint32_t p_layer, bool p_apply_lens_distortion, Vector2 p_eye_center, double p_k1, double p_k2, double p_upscale, double p_aspect_ratio) {
BlitToScreen blit;
- ERR_FAIL_COND_MSG(!can_add_blits, "add_blit can only be called from an XR plugin from within _commit_views!");
+ ERR_FAIL_COND_MSG(!can_add_blits, "add_blit can only be called from an XR plugin from within _post_draw_viewport!");
blit.render_target = p_render_target;
blit.src_rect = p_src_rect;
@@ -293,12 +296,31 @@ void XRInterfaceExtension::add_blit(RID p_render_target, Rect2 p_src_rect, Rect2
blits.push_back(blit);
}
-Vector<BlitToScreen> XRInterfaceExtension::commit_views(RID p_render_target, const Rect2 &p_screen_rect) {
+void XRInterfaceExtension::process() {
+ GDVIRTUAL_CALL(_process);
+}
+
+void XRInterfaceExtension::pre_render() {
+ GDVIRTUAL_CALL(_pre_render);
+}
+
+bool XRInterfaceExtension::pre_draw_viewport(RID p_render_target) {
+ bool do_render = true;
+
+ if (GDVIRTUAL_CALL(_pre_draw_viewport, p_render_target, do_render)) {
+ return do_render;
+ } else {
+ // if not implemented we're returning true
+ return true;
+ }
+}
+
+Vector<BlitToScreen> XRInterfaceExtension::post_draw_viewport(RID p_render_target, const Rect2 &p_screen_rect) {
// This is just so our XR plugin can add blits...
blits.clear();
can_add_blits = true;
- if (GDVIRTUAL_CALL(_commit_views, p_render_target, p_screen_rect)) {
+ if (GDVIRTUAL_CALL(_post_draw_viewport, p_render_target, p_screen_rect)) {
return blits;
}
@@ -306,8 +328,8 @@ Vector<BlitToScreen> XRInterfaceExtension::commit_views(RID p_render_target, con
return blits;
}
-void XRInterfaceExtension::process() {
- GDVIRTUAL_CALL(_process);
+void XRInterfaceExtension::end_frame() {
+ GDVIRTUAL_CALL(_end_frame);
}
void XRInterfaceExtension::notification(int p_what) {
diff --git a/servers/xr/xr_interface_extension.h b/servers/xr/xr_interface_extension.h
index e22ec2b872..5a436b9fd0 100644
--- a/servers/xr/xr_interface_extension.h
+++ b/servers/xr/xr_interface_extension.h
@@ -109,13 +109,20 @@ public:
GDVIRTUAL4R(PackedFloat64Array, _get_projection_for_view, uint32_t, double, double, double);
void add_blit(RID p_render_target, Rect2 p_src_rect, Rect2i p_dst_rect, bool p_use_layer = false, uint32_t p_layer = 0, bool p_apply_lens_distortion = false, Vector2 p_eye_center = Vector2(), double p_k1 = 0.0, double p_k2 = 0.0, double p_upscale = 1.0, double p_aspect_ratio = 1.0);
- virtual Vector<BlitToScreen> commit_views(RID p_render_target, const Rect2 &p_screen_rect) override;
- GDVIRTUAL2(_commit_views, RID, const Rect2 &);
virtual void process() override;
+ virtual void pre_render() override;
+ virtual bool pre_draw_viewport(RID p_render_target) override;
+ virtual Vector<BlitToScreen> post_draw_viewport(RID p_render_target, const Rect2 &p_screen_rect) override;
+ virtual void end_frame() override;
virtual void notification(int p_what) override;
GDVIRTUAL0(_process);
+ GDVIRTUAL0(_pre_render);
+ GDVIRTUAL1R(bool, _pre_draw_viewport, RID);
+ GDVIRTUAL2(_post_draw_viewport, RID, const Rect2 &);
+ GDVIRTUAL0(_end_frame);
+
GDVIRTUAL1(_notification, int);
/* access to some internals we need */
diff --git a/servers/xr_server.cpp b/servers/xr_server.cpp
index 69f4c69b53..dbfe76a127 100644
--- a/servers/xr_server.cpp
+++ b/servers/xr_server.cpp
@@ -65,10 +65,6 @@ void XRServer::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "primary_interface"), "set_primary_interface", "get_primary_interface");
- ClassDB::bind_method(D_METHOD("get_last_process_usec"), &XRServer::get_last_process_usec);
- ClassDB::bind_method(D_METHOD("get_last_commit_usec"), &XRServer::get_last_commit_usec);
- ClassDB::bind_method(D_METHOD("get_last_frame_usec"), &XRServer::get_last_frame_usec);
-
BIND_ENUM_CONSTANT(TRACKER_HEAD);
BIND_ENUM_CONSTANT(TRACKER_CONTROLLER);
BIND_ENUM_CONSTANT(TRACKER_BASESTATION);
@@ -351,24 +347,9 @@ PackedStringArray XRServer::get_suggested_pose_names(const StringName &p_tracker
return arr;
}
-uint64_t XRServer::get_last_process_usec() {
- return last_process_usec;
-};
-
-uint64_t XRServer::get_last_commit_usec() {
- return last_commit_usec;
-};
-
-uint64_t XRServer::get_last_frame_usec() {
- return last_frame_usec;
-};
-
void XRServer::_process() {
/* called from renderer_viewport.draw_viewports right before we start drawing our viewports */
- /* mark for our frame timing */
- last_process_usec = OS::get_singleton()->get_ticks_usec();
-
/* process all active interfaces */
for (int i = 0; i < interfaces.size(); i++) {
if (!interfaces[i].is_valid()) {
@@ -379,13 +360,32 @@ void XRServer::_process() {
};
};
-void XRServer::_mark_commit() {
- /* time this */
- last_commit_usec = OS::get_singleton()->get_ticks_usec();
+void XRServer::pre_render() {
+ // called from RendererViewport.draw_viewports right before we start drawing our viewports
+ // note that we can have multiple interfaces active if we have interfaces that purely handle tracking
- /* now store our difference as we may overwrite last_process_usec before this is accessed */
- last_frame_usec = last_commit_usec - last_process_usec;
-};
+ // process all active interfaces
+ for (int i = 0; i < interfaces.size(); i++) {
+ if (!interfaces[i].is_valid()) {
+ // ignore, not a valid reference
+ } else if (interfaces[i]->is_initialized()) {
+ interfaces.write[i]->pre_render();
+ };
+ };
+}
+
+void XRServer::end_frame() {
+ // called from RenderingServerDefault after Vulkan queues have been submitted
+
+ // process all active interfaces
+ for (int i = 0; i < interfaces.size(); i++) {
+ if (!interfaces[i].is_valid()) {
+ // ignore, not a valid reference
+ } else if (interfaces[i]->is_initialized()) {
+ interfaces.write[i]->end_frame();
+ };
+ };
+}
XRServer::XRServer() {
singleton = this;
diff --git a/servers/xr_server.h b/servers/xr_server.h
index a820634bd9..d9188d2de1 100644
--- a/servers/xr_server.h
+++ b/servers/xr_server.h
@@ -84,10 +84,6 @@ private:
Transform3D world_origin; /* our world origin point, maps a location in our virtual world to the origin point in our real world tracking volume */
Transform3D reference_frame; /* our reference frame */
- uint64_t last_process_usec; /* for frame timing, usec when we did our processing */
- uint64_t last_commit_usec; /* for frame timing, usec when we finished committing both eyes */
- uint64_t last_frame_usec; /* time it took between process and committing, we should probably average this over the last x frames */
-
protected:
static XRServer *singleton;
@@ -175,12 +171,16 @@ public:
PackedStringArray get_suggested_pose_names(const StringName &p_tracker_name) const;
// Q: Should we add get_suggested_input_names and get_suggested_haptic_names even though we don't use them for the IDE?
- uint64_t get_last_process_usec();
- uint64_t get_last_commit_usec();
- uint64_t get_last_frame_usec();
-
+ // Process is called before we handle our physics process and game process. This is where our interfaces will update controller data and such.
void _process();
- void _mark_commit();
+
+ // Pre-render is called right before we're rendering our viewports.
+ // This is where interfaces such as OpenVR and OpenXR will update positioning data.
+ // Many of these interfaces will also do a predictive sync which ensures we run at a steady framerate.
+ void pre_render();
+
+ // End-frame is called right after Godot has finished its rendering bits.
+ void end_frame();
XRServer();
~XRServer();