Merge pull request #57489 from akien-mga/3.4-cherrypicks
This commit is contained in:
commit
caaa648e86
@ -8,8 +8,8 @@
|
||||
See also [AudioStreamGenerator] for procedurally generating sounds.
|
||||
</description>
|
||||
<tutorials>
|
||||
<link title="https://godotengine.org/asset-library/asset/528">Audio Spectrum Demo</link>
|
||||
<link title="https://godotengine.org/article/godot-32-will-get-new-audio-features">Godot 3.2 will get new audio features</link>
|
||||
<link title="Audio Spectrum Demo">https://godotengine.org/asset-library/asset/528</link>
|
||||
<link title="Godot 3.2 will get new audio features">https://godotengine.org/article/godot-32-will-get-new-audio-features</link>
|
||||
</tutorials>
|
||||
<methods>
|
||||
</methods>
|
||||
|
@ -10,7 +10,7 @@
|
||||
</description>
|
||||
<tutorials>
|
||||
<link title="Audio Generator Demo">https://godotengine.org/asset-library/asset/526</link>
|
||||
<link title="https://godotengine.org/article/godot-32-will-get-new-audio-features">Godot 3.2 will get new audio features</link>
|
||||
<link title="Godot 3.2 will get new audio features">https://godotengine.org/article/godot-32-will-get-new-audio-features</link>
|
||||
</tutorials>
|
||||
<methods>
|
||||
</methods>
|
||||
|
@ -8,7 +8,7 @@
|
||||
</description>
|
||||
<tutorials>
|
||||
<link title="Audio Generator Demo">https://godotengine.org/asset-library/asset/526</link>
|
||||
<link title="https://godotengine.org/article/godot-32-will-get-new-audio-features">Godot 3.2 will get new audio features</link>
|
||||
<link title="Godot 3.2 will get new audio features">https://godotengine.org/article/godot-32-will-get-new-audio-features</link>
|
||||
</tutorials>
|
||||
<methods>
|
||||
<method name="can_push_buffer" qualifiers="const">
|
||||
|
@ -47,6 +47,7 @@
|
||||
</member>
|
||||
<member name="max_distance" type="float" setter="set_max_distance" getter="get_max_distance" default="0.0">
|
||||
The maximum distance away from the [ReflectionProbe] an object can be before it is culled. Decrease this to improve performance, especially when using the [constant UPDATE_ALWAYS] [member update_mode].
|
||||
[b]Note:[/b] The maximum reflection distance is always at least equal to the [member extents]. This means that decreasing [member max_distance] will not always cull objects from reflections, especially if the reflection probe's [member extents] are already large.
|
||||
</member>
|
||||
<member name="origin_offset" type="Vector3" setter="set_origin_offset" getter="get_origin_offset" default="Vector3( 0, 0, 0 )">
|
||||
Sets the origin offset to be used when this [ReflectionProbe] is in [member box_projection] mode. This can be set to a non-zero value to ensure a reflection fits a rectangle-shaped room, while reducing the amount of objects that "get in the way" of the reflection.
|
||||
|
@ -77,7 +77,7 @@ void SkeletonEditor::create_physical_skeleton() {
|
||||
if (!bones_infos[parent].physical_bone) {
|
||||
bones_infos.write[parent].physical_bone = create_physical_bone(parent, bone_id, bones_infos);
|
||||
|
||||
ur->create_action(TTR("Create physical bones"));
|
||||
ur->create_action(TTR("Create physical bones"), UndoRedo::MERGE_ALL);
|
||||
ur->add_do_method(skeleton, "add_child", bones_infos[parent].physical_bone);
|
||||
ur->add_do_reference(bones_infos[parent].physical_bone);
|
||||
ur->add_undo_method(skeleton, "remove_child", bones_infos[parent].physical_bone);
|
||||
|
@ -164,11 +164,12 @@ const char *godot_so_name = "libgodot_android.so";
|
||||
void *mono_dl_handle = NULL;
|
||||
void *godot_dl_handle = NULL;
|
||||
|
||||
void *try_dlopen(const String &p_so_path, int p_flags) {
|
||||
void *_try_dlopen_file_path(const String &p_so_path, int p_flags) {
|
||||
if (!FileAccess::exists(p_so_path)) {
|
||||
if (OS::get_singleton()->is_stdout_verbose())
|
||||
if (OS::get_singleton()->is_stdout_verbose()) {
|
||||
OS::get_singleton()->print("Cannot find shared library: '%s'\n", p_so_path.utf8().get_data());
|
||||
return NULL;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int lflags = gd_mono_convert_dl_flags(p_flags);
|
||||
@ -176,13 +177,48 @@ void *try_dlopen(const String &p_so_path, int p_flags) {
|
||||
void *handle = dlopen(p_so_path.utf8().get_data(), lflags);
|
||||
|
||||
if (!handle) {
|
||||
if (OS::get_singleton()->is_stdout_verbose())
|
||||
if (OS::get_singleton()->is_stdout_verbose()) {
|
||||
OS::get_singleton()->print("Failed to open shared library: '%s'. Error: '%s'\n", p_so_path.utf8().get_data(), dlerror());
|
||||
return NULL;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (OS::get_singleton()->is_stdout_verbose())
|
||||
if (OS::get_singleton()->is_stdout_verbose()) {
|
||||
OS::get_singleton()->print("Successfully loaded shared library: '%s'\n", p_so_path.utf8().get_data());
|
||||
}
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
void *try_dlopen(const String &p_so_path, int p_flags) {
|
||||
void *handle = _try_dlopen_file_path(p_so_path, p_flags);
|
||||
|
||||
if (handle) {
|
||||
return handle;
|
||||
}
|
||||
|
||||
// Try only with the file name, without specifying the location.
|
||||
// This is needed when installing from Android App Bundles, as the native
|
||||
// libraries are not extracted. They are loaded directly from the APK.
|
||||
// See: https://stackoverflow.com/a/56551499
|
||||
// If we pass only the file name to dlopen without the location, it should
|
||||
// search the native libraries in all locations, including inside the apk.
|
||||
|
||||
String so_name = p_so_path.get_file();
|
||||
|
||||
int lflags = gd_mono_convert_dl_flags(p_flags);
|
||||
|
||||
handle = dlopen(so_name.utf8().get_data(), lflags);
|
||||
if (!handle) {
|
||||
if (OS::get_singleton()->is_stdout_verbose()) {
|
||||
OS::get_singleton()->print("Failed to open shared library: '%s'. Error: '%s'\n", so_name.utf8().get_data(), dlerror());
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (OS::get_singleton()->is_stdout_verbose()) {
|
||||
OS::get_singleton()->print("Successfully loaded shared library: '%s'\n", so_name.utf8().get_data());
|
||||
}
|
||||
|
||||
return handle;
|
||||
}
|
||||
@ -196,6 +232,7 @@ void *gd_mono_android_dlopen(const char *p_name, int p_flags, char **r_err, void
|
||||
String so_path = path::join(app_native_lib_dir, mono_so_name);
|
||||
|
||||
mono_dl_handle = try_dlopen(so_path, p_flags);
|
||||
ERR_FAIL_COND_V_MSG(!mono_dl_handle, nullptr, "Failed to load Mono native library from path");
|
||||
}
|
||||
|
||||
return mono_dl_handle;
|
||||
@ -371,7 +408,7 @@ void initialize() {
|
||||
String so_path = path::join(app_native_lib_dir, godot_so_name);
|
||||
|
||||
godot_dl_handle = try_dlopen(so_path, gd_mono_convert_dl_flags(MONO_DL_LAZY));
|
||||
ERR_FAIL_COND(!godot_dl_handle);
|
||||
ERR_FAIL_COND_MSG(!godot_dl_handle, "Failed to load Godot native library");
|
||||
}
|
||||
|
||||
void cleanup() {
|
||||
|
@ -185,8 +185,8 @@ void AudioStreamOGGVorbis::set_data(const PoolVector<uint8_t> &p_data) {
|
||||
w.release();
|
||||
alloc_try *= 2;
|
||||
} else {
|
||||
ERR_FAIL_COND(alloc_try == MAX_TEST_MEM);
|
||||
ERR_FAIL_COND(ogg_stream == nullptr);
|
||||
ERR_FAIL_COND_MSG(alloc_try == MAX_TEST_MEM, "Failed allocating memory for OGG Vorbis stream.");
|
||||
ERR_FAIL_COND_MSG(!ogg_stream, "OGG Vorbis decoding failed. Check that your data is a valid OGG Vorbis audio stream.");
|
||||
|
||||
stb_vorbis_info info = stb_vorbis_get_info(ogg_stream);
|
||||
|
||||
|
@ -91,7 +91,7 @@ Error ResourceImporterOGGVorbis::import(const String &p_source_file, const Strin
|
||||
ogg_stream.instance();
|
||||
|
||||
ogg_stream->set_data(data);
|
||||
ERR_FAIL_COND_V(!ogg_stream->get_data().size(), ERR_FILE_CORRUPT);
|
||||
ERR_FAIL_COND_V_MSG(!ogg_stream->get_data().size(), ERR_FILE_CORRUPT, "Couldn't import file as AudioStreamOGGVorbis: " + p_source_file);
|
||||
ogg_stream->set_loop(loop);
|
||||
ogg_stream->set_loop_offset(loop_offset);
|
||||
|
||||
|
@ -987,14 +987,14 @@ void EditorExportPlatformAndroid::_fix_manifest(const Ref<EditorExportPreset> &p
|
||||
|
||||
if (tname == "meta-data" && attrname == "name" && value == "xr_mode_metadata_name") {
|
||||
// Update the meta-data 'android:name' attribute based on the selected XR mode.
|
||||
if (xr_mode_index == XR_MODE_OVR || xr_mode_index == XR_MODE_OPENXR) {
|
||||
if (xr_mode_index == XR_MODE_OVR) {
|
||||
string_table.write[attr_value] = "com.samsung.android.vr.application.mode";
|
||||
}
|
||||
}
|
||||
|
||||
if (tname == "meta-data" && attrname == "value" && value == "xr_mode_metadata_value") {
|
||||
// Update the meta-data 'android:value' attribute based on the selected XR mode.
|
||||
if (xr_mode_index == XR_MODE_OVR || xr_mode_index == XR_MODE_OPENXR) {
|
||||
if (xr_mode_index == XR_MODE_OVR) {
|
||||
string_table.write[attr_value] = "vr_only";
|
||||
}
|
||||
}
|
||||
|
@ -287,7 +287,9 @@ String _get_application_tag(const Ref<EditorExportPreset> &p_preset, bool p_has_
|
||||
bool_to_string(p_has_storage_permission));
|
||||
|
||||
if (uses_xr) {
|
||||
if (xr_mode_index == XR_MODE_OVR) {
|
||||
manifest_application_text += " <meta-data tools:node=\"replace\" android:name=\"com.samsung.android.vr.application.mode\" android:value=\"vr_only\" />\n";
|
||||
}
|
||||
|
||||
bool hand_tracking_enabled = (int)(p_preset->get("xr_features/hand_tracking")) > XR_HAND_TRACKING_NONE;
|
||||
if (hand_tracking_enabled) {
|
||||
@ -297,6 +299,8 @@ String _get_application_tag(const Ref<EditorExportPreset> &p_preset, bool p_has_
|
||||
" <meta-data tools:node=\"replace\" android:name=\"com.oculus.handtracking.frequency\" android:value=\"%s\" />\n",
|
||||
hand_tracking_frequency);
|
||||
}
|
||||
} else {
|
||||
manifest_application_text += " <meta-data tools:node=\"remove\" android:name=\"com.oculus.supportedDevices\" />\n";
|
||||
}
|
||||
manifest_application_text += _get_activity_tag(p_preset);
|
||||
manifest_application_text += " </application>\n";
|
||||
|
@ -50,6 +50,12 @@
|
||||
android:name="xr_hand_tracking_metadata_name"
|
||||
android:value="xr_hand_tracking_metadata_value"/>
|
||||
|
||||
<!-- Supported Meta devices -->
|
||||
<!-- This is removed by the exporter if the xr mode is not VR. -->
|
||||
<meta-data
|
||||
android:name="com.oculus.supportedDevices"
|
||||
android:value="all" />
|
||||
|
||||
<activity
|
||||
android:name=".GodotApp"
|
||||
android:label="@string/godot_project_name_string"
|
||||
|
@ -225,33 +225,34 @@ const InternalConfig = function (initConfig) { // eslint-disable-line no-unused-
|
||||
*/
|
||||
Config.prototype.update = function (opts) {
|
||||
const config = opts || {};
|
||||
function parse(key, def) {
|
||||
const me = this;
|
||||
function parse(key) {
|
||||
if (typeof (config[key]) === 'undefined') {
|
||||
return def;
|
||||
return me[key];
|
||||
}
|
||||
return config[key];
|
||||
}
|
||||
// Module config
|
||||
this.unloadAfterInit = parse('unloadAfterInit', this.unloadAfterInit);
|
||||
this.onPrintError = parse('onPrintError', this.onPrintError);
|
||||
this.onPrint = parse('onPrint', this.onPrint);
|
||||
this.onProgress = parse('onProgress', this.onProgress);
|
||||
this.unloadAfterInit = parse('unloadAfterInit');
|
||||
this.onPrintError = parse('onPrintError');
|
||||
this.onPrint = parse('onPrint');
|
||||
this.onProgress = parse('onProgress');
|
||||
|
||||
// Godot config
|
||||
this.canvas = parse('canvas', this.canvas);
|
||||
this.executable = parse('executable', this.executable);
|
||||
this.mainPack = parse('mainPack', this.mainPack);
|
||||
this.locale = parse('locale', this.locale);
|
||||
this.canvasResizePolicy = parse('canvasResizePolicy', this.canvasResizePolicy);
|
||||
this.persistentPaths = parse('persistentPaths', this.persistentPaths);
|
||||
this.persistentDrops = parse('persistentDrops', this.persistentDrops);
|
||||
this.experimentalVK = parse('experimentalVK', this.experimentalVK);
|
||||
this.focusCanvas = parse('focusCanvas', this.focusCanvas);
|
||||
this.gdnativeLibs = parse('gdnativeLibs', this.gdnativeLibs);
|
||||
this.fileSizes = parse('fileSizes', this.fileSizes);
|
||||
this.args = parse('args', this.args);
|
||||
this.onExecute = parse('onExecute', this.onExecute);
|
||||
this.onExit = parse('onExit', this.onExit);
|
||||
this.canvas = parse('canvas');
|
||||
this.executable = parse('executable');
|
||||
this.mainPack = parse('mainPack');
|
||||
this.locale = parse('locale');
|
||||
this.canvasResizePolicy = parse('canvasResizePolicy');
|
||||
this.persistentPaths = parse('persistentPaths');
|
||||
this.persistentDrops = parse('persistentDrops');
|
||||
this.experimentalVK = parse('experimentalVK');
|
||||
this.focusCanvas = parse('focusCanvas');
|
||||
this.gdnativeLibs = parse('gdnativeLibs');
|
||||
this.fileSizes = parse('fileSizes');
|
||||
this.args = parse('args');
|
||||
this.onExecute = parse('onExecute');
|
||||
this.onExit = parse('onExit');
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -87,7 +87,7 @@ const GodotInputGamepads = {
|
||||
},
|
||||
|
||||
init: function (onchange) {
|
||||
GodotEventListeners.samples = [];
|
||||
GodotInputGamepads.samples = [];
|
||||
function add(pad) {
|
||||
const guid = GodotInputGamepads.get_guid(pad);
|
||||
const c_id = GodotRuntime.allocString(pad.id);
|
||||
|
@ -140,6 +140,11 @@ __declspec(dllexport) int widechar_main(int argc, wchar_t **argv) {
|
||||
|
||||
setlocale(LC_CTYPE, "");
|
||||
|
||||
#ifndef TOOLS_ENABLED
|
||||
// Workaround to prevent LTCG (MSVC LTO) from removing "pck" section
|
||||
char *dummy_guard = dummy;
|
||||
#endif
|
||||
|
||||
char **argv_utf8 = new char *[argc];
|
||||
|
||||
for (int i = 0; i < argc; ++i) {
|
||||
|
@ -170,7 +170,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() : 0;
|
||||
|
||||
shapes[id] = sd;
|
||||
|
||||
@ -283,7 +283,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) {
|
||||
|
@ -45,7 +45,7 @@ class CollisionObject2D : public Node2D {
|
||||
bool pickable;
|
||||
|
||||
struct ShapeData {
|
||||
Object *owner;
|
||||
ObjectID owner_id;
|
||||
Transform2D xform;
|
||||
struct Shape {
|
||||
Ref<Shape2D> shape;
|
||||
@ -61,7 +61,7 @@ class CollisionObject2D : public Node2D {
|
||||
disabled = false;
|
||||
one_way_collision = false;
|
||||
one_way_collision_margin = 0;
|
||||
owner = nullptr;
|
||||
owner_id = 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -363,7 +363,7 @@ uint32_t CollisionObject::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() : 0;
|
||||
|
||||
shapes[id] = sd;
|
||||
|
||||
@ -442,7 +442,7 @@ Transform CollisionObject::shape_owner_get_transform(uint32_t p_owner) const {
|
||||
Object *CollisionObject::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 CollisionObject::shape_owner_add_shape(uint32_t p_owner, const Ref<Shape> &p_shape) {
|
||||
|
@ -45,7 +45,7 @@ class CollisionObject : public Spatial {
|
||||
RID rid;
|
||||
|
||||
struct ShapeData {
|
||||
Object *owner;
|
||||
ObjectID owner_id;
|
||||
Transform xform;
|
||||
struct ShapeBase {
|
||||
RID debug_shape;
|
||||
@ -58,7 +58,7 @@ class CollisionObject : public Spatial {
|
||||
|
||||
ShapeData() {
|
||||
disabled = false;
|
||||
owner = nullptr;
|
||||
owner_id = 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -168,6 +168,12 @@ void TextureButton::_notification(int p_what) {
|
||||
|
||||
Point2 ofs;
|
||||
Size2 size;
|
||||
bool draw_focus = (has_focus() && focused.is_valid());
|
||||
|
||||
// If no other texture is valid, try using focused texture.
|
||||
if (!texdraw.is_valid() && draw_focus) {
|
||||
texdraw = focused;
|
||||
}
|
||||
|
||||
if (texdraw.is_valid()) {
|
||||
size = texdraw->get_size();
|
||||
@ -224,7 +230,9 @@ void TextureButton::_notification(int p_what) {
|
||||
size.width *= hflip ? -1.0f : 1.0f;
|
||||
size.height *= vflip ? -1.0f : 1.0f;
|
||||
|
||||
if (_tile) {
|
||||
if (texdraw == focused) {
|
||||
// Do nothing, we only needed to calculate the rectangle.
|
||||
} else if (_tile) {
|
||||
draw_texture_rect(texdraw, Rect2(ofs, size), _tile);
|
||||
} else {
|
||||
draw_texture_rect_region(texdraw, Rect2(ofs, size), _texture_region);
|
||||
@ -233,7 +241,7 @@ void TextureButton::_notification(int p_what) {
|
||||
_position_rect = Rect2();
|
||||
}
|
||||
|
||||
if (has_focus() && focused.is_valid()) {
|
||||
if (draw_focus) {
|
||||
draw_texture_rect(focused, Rect2(ofs, size), false);
|
||||
};
|
||||
} break;
|
||||
|
@ -109,7 +109,7 @@ void PortalGameplayMonitor::unload(PortalRenderer &p_portal_renderer) {
|
||||
for (int n = 0; n < _active_room_ids_prev->size(); n++) {
|
||||
int room_id = (*_active_room_ids_prev)[n];
|
||||
VSRoom &room = p_portal_renderer.get_room(room_id);
|
||||
room.last_gameplay_tick_hit = 0;
|
||||
room.last_room_tick_hit = 0;
|
||||
|
||||
VisualServerCallbacks::Message msg;
|
||||
msg.object_id = room._godot_instance_ID;
|
||||
@ -121,7 +121,7 @@ void PortalGameplayMonitor::unload(PortalRenderer &p_portal_renderer) {
|
||||
for (int n = 0; n < _active_roomgroup_ids_prev->size(); n++) {
|
||||
int roomgroup_id = (*_active_roomgroup_ids_prev)[n];
|
||||
VSRoomGroup &roomgroup = p_portal_renderer.get_roomgroup(roomgroup_id);
|
||||
roomgroup.last_gameplay_tick_hit = 0;
|
||||
roomgroup.last_room_tick_hit = 0;
|
||||
|
||||
VisualServerCallbacks::Message msg;
|
||||
msg.object_id = roomgroup._godot_instance_ID;
|
||||
@ -133,7 +133,7 @@ void PortalGameplayMonitor::unload(PortalRenderer &p_portal_renderer) {
|
||||
for (int n = 0; n < _active_sghost_ids_prev->size(); n++) {
|
||||
int id = (*_active_sghost_ids_prev)[n];
|
||||
VSStaticGhost &ghost = p_portal_renderer.get_static_ghost(id);
|
||||
ghost.last_gameplay_tick_hit = 0;
|
||||
ghost.last_room_tick_hit = 0;
|
||||
|
||||
VisualServerCallbacks::Message msg;
|
||||
msg.object_id = ghost.object_id;
|
||||
@ -185,6 +185,9 @@ void PortalGameplayMonitor::update_gameplay(PortalRenderer &p_portal_renderer, c
|
||||
// if there is no change in the source room IDs, then we can optimize out a lot of the checks
|
||||
// (anything not to do with roamers)
|
||||
bool source_rooms_changed = _source_rooms_changed(p_source_room_ids, p_num_source_rooms);
|
||||
if (source_rooms_changed) {
|
||||
_room_tick++;
|
||||
}
|
||||
|
||||
// lock output
|
||||
VisualServerCallbacks *callbacks = VSG::scene->get_callbacks();
|
||||
@ -249,7 +252,7 @@ void PortalGameplayMonitor::update_gameplay(PortalRenderer &p_portal_renderer, c
|
||||
const VSRoom &room = p_portal_renderer.get_room(room_id);
|
||||
|
||||
// gone out of view
|
||||
if (room.last_gameplay_tick_hit != _gameplay_tick) {
|
||||
if (room.last_room_tick_hit != _room_tick) {
|
||||
VisualServerCallbacks::Message msg;
|
||||
msg.object_id = room._godot_instance_ID;
|
||||
msg.type = _exit_callback_type;
|
||||
@ -264,7 +267,7 @@ void PortalGameplayMonitor::update_gameplay(PortalRenderer &p_portal_renderer, c
|
||||
const VSRoomGroup &roomgroup = p_portal_renderer.get_roomgroup(roomgroup_id);
|
||||
|
||||
// gone out of view
|
||||
if (roomgroup.last_gameplay_tick_hit != _gameplay_tick) {
|
||||
if (roomgroup.last_room_tick_hit != _room_tick) {
|
||||
VisualServerCallbacks::Message msg;
|
||||
msg.object_id = roomgroup._godot_instance_ID;
|
||||
msg.type = _exit_callback_type;
|
||||
@ -279,7 +282,7 @@ void PortalGameplayMonitor::update_gameplay(PortalRenderer &p_portal_renderer, c
|
||||
VSStaticGhost &ghost = p_portal_renderer.get_static_ghost(id);
|
||||
|
||||
// gone out of view
|
||||
if (ghost.last_gameplay_tick_hit != _gameplay_tick) {
|
||||
if (ghost.last_room_tick_hit != _room_tick) {
|
||||
VisualServerCallbacks::Message msg;
|
||||
msg.object_id = ghost.object_id;
|
||||
msg.type = VisualServerCallbacks::CALLBACK_NOTIFICATION_EXIT_GAMEPLAY;
|
||||
@ -293,7 +296,7 @@ void PortalGameplayMonitor::update_gameplay(PortalRenderer &p_portal_renderer, c
|
||||
callbacks->unlock();
|
||||
|
||||
// swap the current and previous lists
|
||||
_swap();
|
||||
_swap(source_rooms_changed);
|
||||
}
|
||||
|
||||
void PortalGameplayMonitor::_update_gameplay_room(PortalRenderer &p_portal_renderer, int p_room_id, bool p_source_rooms_changed) {
|
||||
@ -367,14 +370,14 @@ void PortalGameplayMonitor::_update_gameplay_room(PortalRenderer &p_portal_rende
|
||||
// later tests only relevant if a room has just come into play
|
||||
bool room_came_into_play = false;
|
||||
|
||||
if (room.last_gameplay_tick_hit != _gameplay_tick) {
|
||||
if (room.last_room_tick_hit != _room_tick) {
|
||||
room_came_into_play = true;
|
||||
|
||||
// add the room to the active list
|
||||
_active_room_ids_curr->push_back(p_room_id);
|
||||
|
||||
// if wasn't present in the tick before, add the notification to enter
|
||||
if (room.last_gameplay_tick_hit != (_gameplay_tick - 1)) {
|
||||
if (room.last_room_tick_hit != (_room_tick - 1)) {
|
||||
VisualServerCallbacks::Message msg;
|
||||
msg.object_id = room._godot_instance_ID;
|
||||
msg.type = _enter_callback_type;
|
||||
@ -383,7 +386,7 @@ void PortalGameplayMonitor::_update_gameplay_room(PortalRenderer &p_portal_rende
|
||||
}
|
||||
|
||||
// mark as done
|
||||
room.last_gameplay_tick_hit = _gameplay_tick;
|
||||
room.last_room_tick_hit = _room_tick;
|
||||
}
|
||||
|
||||
// no need to do later tests
|
||||
@ -398,12 +401,12 @@ void PortalGameplayMonitor::_update_gameplay_room(PortalRenderer &p_portal_rende
|
||||
|
||||
VSRoomGroup &roomgroup = p_portal_renderer.get_roomgroup(roomgroup_id);
|
||||
|
||||
if (roomgroup.last_gameplay_tick_hit != _gameplay_tick) {
|
||||
if (roomgroup.last_room_tick_hit != _room_tick) {
|
||||
// add the room to the active list
|
||||
_active_roomgroup_ids_curr->push_back(roomgroup_id);
|
||||
|
||||
// if wasn't present in the tick before, add the notification to enter
|
||||
if (roomgroup.last_gameplay_tick_hit != (_gameplay_tick - 1)) {
|
||||
if (roomgroup.last_room_tick_hit != (_room_tick - 1)) {
|
||||
VisualServerCallbacks::Message msg;
|
||||
msg.object_id = roomgroup._godot_instance_ID;
|
||||
msg.type = _enter_callback_type;
|
||||
@ -412,7 +415,7 @@ void PortalGameplayMonitor::_update_gameplay_room(PortalRenderer &p_portal_rende
|
||||
}
|
||||
|
||||
// mark as done
|
||||
roomgroup.last_gameplay_tick_hit = _gameplay_tick;
|
||||
roomgroup.last_room_tick_hit = _room_tick;
|
||||
}
|
||||
} // for through roomgroups
|
||||
|
||||
@ -425,14 +428,14 @@ void PortalGameplayMonitor::_update_gameplay_room(PortalRenderer &p_portal_rende
|
||||
VSStaticGhost &ghost = p_portal_renderer.get_static_ghost(id);
|
||||
|
||||
// done already?
|
||||
if (ghost.last_gameplay_tick_hit == _gameplay_tick)
|
||||
if (ghost.last_room_tick_hit == _room_tick)
|
||||
continue;
|
||||
|
||||
// add to the active list
|
||||
_active_sghost_ids_curr->push_back(id);
|
||||
|
||||
// if wasn't present in the tick before, add the notification to enter
|
||||
if (ghost.last_gameplay_tick_hit != (_gameplay_tick - 1)) {
|
||||
if (ghost.last_room_tick_hit != (_room_tick - 1)) {
|
||||
VisualServerCallbacks::Message msg;
|
||||
msg.object_id = ghost.object_id;
|
||||
msg.type = VisualServerCallbacks::CALLBACK_NOTIFICATION_ENTER_GAMEPLAY;
|
||||
@ -441,11 +444,11 @@ void PortalGameplayMonitor::_update_gameplay_room(PortalRenderer &p_portal_rende
|
||||
}
|
||||
|
||||
// mark as done
|
||||
ghost.last_gameplay_tick_hit = _gameplay_tick;
|
||||
ghost.last_room_tick_hit = _room_tick;
|
||||
}
|
||||
}
|
||||
|
||||
void PortalGameplayMonitor::_swap() {
|
||||
void PortalGameplayMonitor::_swap(bool p_source_rooms_changed) {
|
||||
LocalVector<uint32_t, int32_t> *temp = _active_moving_pool_ids_curr;
|
||||
_active_moving_pool_ids_curr = _active_moving_pool_ids_prev;
|
||||
_active_moving_pool_ids_prev = temp;
|
||||
@ -456,6 +459,7 @@ void PortalGameplayMonitor::_swap() {
|
||||
_active_rghost_pool_ids_prev = temp;
|
||||
_active_rghost_pool_ids_curr->clear();
|
||||
|
||||
if (p_source_rooms_changed) {
|
||||
temp = _active_room_ids_curr;
|
||||
_active_room_ids_curr = _active_room_ids_prev;
|
||||
_active_room_ids_prev = temp;
|
||||
@ -470,4 +474,5 @@ void PortalGameplayMonitor::_swap() {
|
||||
_active_sghost_ids_curr = _active_sghost_ids_prev;
|
||||
_active_sghost_ids_prev = temp;
|
||||
_active_sghost_ids_curr->clear();
|
||||
}
|
||||
}
|
||||
|
@ -52,10 +52,17 @@ public:
|
||||
private:
|
||||
void _update_gameplay_room(PortalRenderer &p_portal_renderer, int p_room_id, bool p_source_rooms_changed);
|
||||
bool _source_rooms_changed(const int *p_source_room_ids, int p_num_source_rooms);
|
||||
void _swap();
|
||||
void _swap(bool p_source_rooms_changed);
|
||||
|
||||
// gameplay ticks happen every physics tick
|
||||
uint32_t _gameplay_tick = 1;
|
||||
|
||||
// Room ticks only happen when the rooms the cameras are within change.
|
||||
// This is an optimization. This tick needs to be maintained separately from _gameplay_tick
|
||||
// because testing against the previous tick is used to determine whether to send enter or exit
|
||||
// gameplay notifications, and this must be synchronized differently for rooms, roomgroups and static ghosts.
|
||||
uint32_t _room_tick = 1;
|
||||
|
||||
// we need two version, current and previous
|
||||
LocalVector<uint32_t, int32_t> _active_moving_pool_ids[2];
|
||||
LocalVector<uint32_t, int32_t> *_active_moving_pool_ids_curr;
|
||||
|
@ -68,7 +68,7 @@ struct VSStaticGhost {
|
||||
ObjectID object_id;
|
||||
|
||||
uint32_t last_tick_hit = 0;
|
||||
uint32_t last_gameplay_tick_hit = 0;
|
||||
uint32_t last_room_tick_hit = 0;
|
||||
};
|
||||
|
||||
class PortalRenderer {
|
||||
|
@ -227,7 +227,7 @@ struct VSRoomGroup {
|
||||
}
|
||||
|
||||
// used for calculating gameplay notifications
|
||||
uint32_t last_gameplay_tick_hit = 0;
|
||||
uint32_t last_room_tick_hit = 0;
|
||||
|
||||
ObjectID _godot_instance_ID = 0;
|
||||
|
||||
@ -257,7 +257,7 @@ struct VSRoom {
|
||||
_secondary_pvs_size = 0;
|
||||
_priority = 0;
|
||||
_contains_internal_rooms = false;
|
||||
last_gameplay_tick_hit = 0;
|
||||
last_room_tick_hit = 0;
|
||||
}
|
||||
|
||||
void cleanup_after_conversion() {
|
||||
@ -354,7 +354,7 @@ struct VSRoom {
|
||||
uint16_t _secondary_pvs_size = 0;
|
||||
|
||||
// used for calculating gameplay notifications
|
||||
uint32_t last_gameplay_tick_hit = 0;
|
||||
uint32_t last_room_tick_hit = 0;
|
||||
|
||||
// convex hull of the room, either determined by geometry or manual bound
|
||||
LocalVector<Plane, int32_t> _planes;
|
||||
|
Loading…
Reference in New Issue
Block a user