Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion doc/classes/RenderingServer.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4360,8 +4360,9 @@
<param index="0" name="viewport" type="RID" />
<param index="1" name="width" type="int" />
<param index="2" name="height" type="int" />
<param index="3" name="view_count" type="int" default="1" />
<description>
Sets the viewport's width and height in pixels.
Sets the viewport's [param width] and [param height] in pixels. Optionally the [param view_count] can be set to increase the number of view layers for stereo rendering.
</description>
</method>
<method name="viewport_set_snap_2d_transforms_to_pixel">
Expand Down
3 changes: 3 additions & 0 deletions doc/classes/SubViewport.xml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@
<member name="size_2d_override_stretch" type="bool" setter="set_size_2d_override_stretch" getter="is_size_2d_override_stretch_enabled" default="false">
If [code]true[/code], the 2D size override affects stretch as well.
</member>
<member name="view_count" type="int" setter="set_view_count" getter="get_view_count" default="1">
The number of view layers we are rendering to. Set this to [code]2[/code] to enable stereo rendering.
</member>
</members>
<constants>
<constant name="CLEAR_MODE_ALWAYS" value="0" enum="ClearMode">
Expand Down
9 changes: 9 additions & 0 deletions misc/extension_api_validation/4.6-stable/GH-115799.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
GH-115799
---------
Validate extension JSON: Error: Field 'classes/RenderingServer/methods/viewport_set_size/arguments': size changed value in new API, from 3 to 4.

Optional argument added. Compatibility method registered.

Validate extension JSON: Error: Field 'classes/Viewport/methods/is_using_xr': is_const changed value in new API, from false to true.

Changed to const. Compatibility method registered.
45 changes: 45 additions & 0 deletions scene/main/viewport.compat.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/**************************************************************************/
/* viewport.compat.inc */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/

#ifndef DISABLE_DEPRECATED

#ifndef XR_DISABLED
bool Viewport::_is_using_xr_115799() {
return is_using_xr();
}
#endif

void Viewport::_bind_compatibility_methods() {
#ifndef XR_DISABLED
ClassDB::bind_compatibility_method(D_METHOD("is_using_xr"), &Viewport::_is_using_xr_115799);
#endif
}

#endif
132 changes: 90 additions & 42 deletions scene/main/viewport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
/**************************************************************************/

#include "viewport.h"
#include "viewport.compat.inc"

#include "core/config/project_settings.h"
#include "core/debugger/engine_debugger.h"
Expand Down Expand Up @@ -683,6 +684,17 @@ void Viewport::_notification(int p_what) {
_update_viewport_path();
} break;

#ifndef XR_DISABLED
case NOTIFICATION_INTERNAL_PROCESS: {
// Note: internal process should only be enabled if use_xr is true,
// but we check anyway to be future proof.
// This is currently a polling approach.
if (use_xr) {
_check_xr_size();
}
} break;
#endif // XR_DISABLED

#if !defined(PHYSICS_2D_DISABLED) || !defined(PHYSICS_3D_DISABLED)
case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
if (!get_tree()) {
Expand Down Expand Up @@ -1080,7 +1092,7 @@ void Viewport::set_use_oversampling(bool p_oversampling) {
return;
}
use_font_oversampling = p_oversampling;
_set_size(_get_size(), _get_size_2d_override(), _is_size_allocated());
_set_size(_get_size(), _get_view_count(), _get_size_2d_override(), _is_size_allocated());
}

bool Viewport::is_using_oversampling() const {
Expand All @@ -1094,15 +1106,15 @@ void Viewport::set_oversampling_override(float p_oversampling) {
return;
}
font_oversampling_override = p_oversampling;
_set_size(_get_size(), _get_size_2d_override(), _is_size_allocated());
_set_size(_get_size(), _get_view_count(), _get_size_2d_override(), _is_size_allocated());
}

float Viewport::get_oversampling_override() const {
ERR_READ_THREAD_GUARD_V(0.0);
return font_oversampling_override;
}

bool Viewport::_set_size(const Size2i &p_size, const Size2 &p_size_2d_override, bool p_allocated) {
bool Viewport::_set_size(const Size2i &p_size, const int p_view_count, const Size2 &p_size_2d_override, bool p_allocated) {
Transform2D stretch_transform_new = Transform2D();
float new_font_oversampling = 1.0;
if (is_size_2d_override_stretch_enabled() && p_size_2d_override.width > 0 && p_size_2d_override.height > 0) {
Expand All @@ -1123,7 +1135,7 @@ bool Viewport::_set_size(const Size2i &p_size, const Size2 &p_size_2d_override,
}

Size2i new_size = p_size.maxi(2);
if (size == new_size && size_allocated == p_allocated && stretch_transform == stretch_transform_new && p_size_2d_override == size_2d_override && new_font_oversampling == font_oversampling) {
if (size == new_size && view_count == p_view_count && size_allocated == p_allocated && stretch_transform == stretch_transform_new && p_size_2d_override == size_2d_override && new_font_oversampling == font_oversampling) {
return false;
}

Expand All @@ -1136,24 +1148,17 @@ bool Viewport::_set_size(const Size2i &p_size, const Size2 &p_size_2d_override,
}

size = new_size;
view_count = p_view_count;
size_allocated = p_allocated;
size_2d_override = p_size_2d_override;
stretch_transform = stretch_transform_new;
font_oversampling = new_font_oversampling;

#ifndef XR_DISABLED
if (!use_xr) {
#endif

if (p_allocated) {
RS::get_singleton()->viewport_set_size(viewport, size.width, size.height);
} else {
RS::get_singleton()->viewport_set_size(viewport, 0, 0);
}

#ifndef XR_DISABLED
} // if (!use_xr)
#endif
if (p_allocated) {
RS::get_singleton()->viewport_set_size(viewport, size.width, size.height, view_count);
} else {
RS::get_singleton()->viewport_set_size(viewport, 0, 0, 0);
}

_update_global_transform();
update_configuration_warnings();
Expand All @@ -1179,27 +1184,37 @@ bool Viewport::_set_size(const Size2i &p_size, const Size2 &p_size_2d_override,
return true;
}

Size2i Viewport::_get_size() const {
void Viewport::_check_xr_size() {
#ifndef XR_DISABLED
if (use_xr) {
if (XRServer::get_singleton() != nullptr) {
Ref<XRInterface> xr_interface = XRServer::get_singleton()->get_primary_interface();
if (xr_interface.is_valid() && xr_interface->is_initialized()) {
Size2 xr_size = xr_interface->get_render_target_size();
return (Size2i)xr_size;
}
// If our viewport has the use_xr flag set, our size and layout is managed by the XRServer.
if (use_xr && XRServer::get_singleton() != nullptr) {
Ref<XRInterface> xr_interface = XRServer::get_singleton()->get_primary_interface();
if (xr_interface.is_valid() && xr_interface->is_initialized()) {
Size2 xr_size = xr_interface->get_render_target_size();
int xr_view_count = xr_interface->get_view_count();

_set_size((Size2i)xr_size, xr_view_count, Size2i(0, 0), true);
} else {
// Set to default and prevent rendering for now (unless in editor, so we get a preview).
bool is_editor = Engine::get_singleton()->is_editor_hint();
_set_size(is_editor ? Size2i(512, 512) : Size2i(0, 0), is_editor ? 1 : 0, Size2i(0, 0), false);
}
return Size2i();
}
#endif // XR_DISABLED
}

Size2i Viewport::_get_size() const {
return size;
}

Size2 Viewport::_get_size_2d_override() const {
return size_2d_override;
}

int Viewport::_get_view_count() const {
return view_count;
}

bool Viewport::_is_size_allocated() const {
return size_allocated;
}
Expand Down Expand Up @@ -4831,27 +4846,37 @@ void Viewport::_propagate_exit_world_3d(Node *p_node) {
#ifndef XR_DISABLED
void Viewport::set_use_xr(bool p_use_xr) {
ERR_MAIN_THREAD_GUARD;

if (use_xr != p_use_xr) {
use_xr = p_use_xr;

RS::get_singleton()->viewport_set_use_xr(viewport, use_xr);

if (!use_xr) {
// Set viewport to previous size when exiting XR.
if (size_allocated) {
RS::get_singleton()->viewport_set_size(viewport, size.width, size.height);
} else {
RS::get_singleton()->viewport_set_size(viewport, 0, 0);
}
#ifndef XR_DISABLED
if (use_xr) {
// Note: use_xr is ONLY used for the primary XR viewport.
// Any additional (sub)viewports for composition layers and
// other purposes should not have use_xr set.
_check_xr_size();

// Enable internal process as we need to check for recommended size changes each frame
// (though size changes should only happen sporadically).
set_process_internal(true);
} else
#endif // XR_DISABLED
{
// No longer check for recommended size changes in internal process.
set_process_internal(false);

// Reset render target override textures.
RID rt = RS::get_singleton()->viewport_get_render_target(viewport);
RSG::texture_storage->render_target_set_override(rt, RID(), RID(), RID(), RID());
}

notify_property_list_changed();
}
}

bool Viewport::is_using_xr() {
bool Viewport::is_using_xr() const {
ERR_READ_THREAD_GUARD_V(false);
return use_xr;
}
Expand Down Expand Up @@ -5415,17 +5440,17 @@ Viewport::~Viewport() {

void SubViewport::set_size(const Size2i &p_size) {
ERR_MAIN_THREAD_GUARD;
_internal_set_size(p_size);
_internal_set_size(p_size, _get_view_count());
}

void SubViewport::set_size_force(const Size2i &p_size) {
ERR_MAIN_THREAD_GUARD;
// Use only for setting the size from the parent SubViewportContainer with enabled stretch mode.
// Don't expose function to scripting.
_internal_set_size(p_size, true);
_internal_set_size(p_size, _get_view_count(), true);
}

void SubViewport::_internal_set_size(const Size2i &p_size, bool p_force) {
void SubViewport::_internal_set_size(const Size2i &p_size, const int p_view_count, bool p_force) {
SubViewportContainer *c = Object::cast_to<SubViewportContainer>(get_parent());
if (!p_force && c && c->is_stretch_enabled()) {
#ifdef DEBUG_ENABLED
Expand All @@ -5434,7 +5459,7 @@ void SubViewport::_internal_set_size(const Size2i &p_size, bool p_force) {
return;
}

_set_size(p_size, _get_size_2d_override(), true);
_set_size(p_size, p_view_count, _get_size_2d_override(), true);

if (c) {
c->update_minimum_size();
Expand All @@ -5447,9 +5472,22 @@ Size2i SubViewport::get_size() const {
return _get_size();
}

void SubViewport::set_view_count(const int p_view_count) {
ERR_MAIN_THREAD_GUARD;

// Q: add `, _get_size_2d_override(), true` ?
_internal_set_size(_get_size(), p_view_count);
}

int SubViewport::get_view_count() const {
ERR_READ_THREAD_GUARD_V(1);

return _get_view_count();
}

void SubViewport::set_size_2d_override(const Size2i &p_size) {
ERR_MAIN_THREAD_GUARD;
_set_size(_get_size(), p_size, true);
_set_size(_get_size(), _get_view_count(), p_size, true);
}

Size2i SubViewport::get_size_2d_override() const {
Expand All @@ -5467,7 +5505,7 @@ void SubViewport::set_size_2d_override_stretch(bool p_enable) {
}

size_2d_override_stretch = p_enable;
_set_size(_get_size(), _get_size_2d_override(), true);
_set_size(_get_size(), _get_view_count(), _get_size_2d_override(), true);
}

bool SubViewport::is_size_2d_override_stretch_enabled() const {
Expand Down Expand Up @@ -5573,6 +5611,9 @@ void SubViewport::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_size_2d_override_stretch", "enable"), &SubViewport::set_size_2d_override_stretch);
ClassDB::bind_method(D_METHOD("is_size_2d_override_stretch_enabled"), &SubViewport::is_size_2d_override_stretch_enabled);

ClassDB::bind_method(D_METHOD("set_view_count", "view_count"), &SubViewport::set_view_count);
ClassDB::bind_method(D_METHOD("get_view_count"), &SubViewport::get_view_count);

ClassDB::bind_method(D_METHOD("set_update_mode", "mode"), &SubViewport::set_update_mode);
ClassDB::bind_method(D_METHOD("get_update_mode"), &SubViewport::get_update_mode);

Expand All @@ -5582,6 +5623,7 @@ void SubViewport::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "size", PROPERTY_HINT_NONE, "suffix:px"), "set_size", "get_size");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "size_2d_override", PROPERTY_HINT_NONE, "suffix:px"), "set_size_2d_override", "get_size_2d_override");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "size_2d_override_stretch"), "set_size_2d_override_stretch", "is_size_2d_override_stretch_enabled");
ADD_PROPERTY(PropertyInfo(Variant::INT, "view_count"), "set_view_count", "get_view_count");
ADD_GROUP("Render Target", "render_target_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "render_target_clear_mode", PROPERTY_HINT_ENUM, "Always,Never,Next Frame"), "set_clear_mode", "get_clear_mode");
ADD_PROPERTY(PropertyInfo(Variant::INT, "render_target_update_mode", PROPERTY_HINT_ENUM, "Disabled,Once,When Visible,When Parent Visible,Always"), "set_update_mode", "get_update_mode");
Expand All @@ -5601,7 +5643,13 @@ void SubViewport::_validate_property(PropertyInfo &p_property) const {
if (!Engine::get_singleton()->is_editor_hint()) {
return;
}
#ifndef XR_DISABLED
if (is_using_xr() && (p_property.name == "size" || p_property.name == "size_2d_override" || p_property.name == "size_2d_override_stretch" || p_property.name == "view_count")) {
p_property.usage = PROPERTY_USAGE_NONE; // Managed by XR
} else if (p_property.name == "size") {
#else
if (p_property.name == "size") {
#endif
SubViewportContainer *parent_svc = Object::cast_to<SubViewportContainer>(get_parent());
if (parent_svc && parent_svc->is_stretch_enabled()) {
p_property.usage = PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_READ_ONLY;
Expand All @@ -5612,7 +5660,7 @@ void SubViewport::_validate_property(PropertyInfo &p_property) const {
}

SubViewport::SubViewport() {
RS::get_singleton()->viewport_set_size(get_viewport_rid(), get_size().width, get_size().height);
RS::get_singleton()->viewport_set_size(get_viewport_rid(), get_size().width, get_size().height, get_view_count());
}

/////////////////////////////////
Expand Down
Loading
Loading