summaryrefslogtreecommitdiff
path: root/scene
diff options
context:
space:
mode:
Diffstat (limited to 'scene')
-rw-r--r--scene/main/canvas_item.cpp35
-rw-r--r--scene/main/canvas_item.h4
-rw-r--r--scene/main/canvas_layer.cpp2
-rw-r--r--scene/multiplayer/scene_cache_interface.cpp122
-rw-r--r--scene/multiplayer/scene_cache_interface.h2
-rw-r--r--scene/multiplayer/scene_replication_interface.cpp3
-rw-r--r--scene/resources/tile_set.cpp4
7 files changed, 96 insertions, 76 deletions
diff --git a/scene/main/canvas_item.cpp b/scene/main/canvas_item.cpp
index 9ad711c596..26b67b763c 100644
--- a/scene/main/canvas_item.cpp
+++ b/scene/main/canvas_item.cpp
@@ -56,19 +56,21 @@ Transform2D CanvasItem::_edit_get_transform() const {
#endif
bool CanvasItem::is_visible_in_tree() const {
- return visible && visible_in_tree;
+ return visible && parent_visible_in_tree;
}
-void CanvasItem::_propagate_visibility_changed(bool p_visible, bool p_was_visible) {
- if (p_visible && first_draw) { //avoid propagating it twice
+void CanvasItem::_propagate_visibility_changed(bool p_visible, bool p_is_source) {
+ if (p_visible && first_draw) { // Avoid propagating it twice.
first_draw = false;
}
- visible_in_tree = p_visible;
+ if (!p_is_source) {
+ parent_visible_in_tree = p_visible;
+ }
notification(NOTIFICATION_VISIBILITY_CHANGED);
if (visible && p_visible) {
update();
- } else if (!p_visible && (visible || p_was_visible)) {
+ } else if (!p_visible && (visible || p_is_source)) {
emit_signal(SceneStringNames::get_singleton()->hidden);
}
_block();
@@ -76,8 +78,12 @@ void CanvasItem::_propagate_visibility_changed(bool p_visible, bool p_was_visibl
for (int i = 0; i < get_child_count(); i++) {
CanvasItem *c = Object::cast_to<CanvasItem>(get_child(i));
- if (c && c->visible) { //should the top_levels stop propagation? i think so but..
- c->_propagate_visibility_changed(p_visible);
+ if (c) { // Should the top_levels stop propagation? I think so, but...
+ if (c->visible) {
+ c->_propagate_visibility_changed(p_visible);
+ } else {
+ c->parent_visible_in_tree = p_visible;
+ }
}
}
@@ -92,11 +98,12 @@ void CanvasItem::set_visible(bool p_visible) {
visible = p_visible;
RenderingServer::get_singleton()->canvas_item_set_visible(canvas_item, p_visible);
- if (!is_inside_tree()) {
+ if (!parent_visible_in_tree) {
+ notification(NOTIFICATION_VISIBILITY_CHANGED);
return;
}
- _propagate_visibility_changed(p_visible, !p_visible);
+ _propagate_visibility_changed(p_visible, true);
}
void CanvasItem::show() {
@@ -264,13 +271,13 @@ void CanvasItem::_notification(int p_what) {
CanvasItem *ci = Object::cast_to<CanvasItem>(parent);
if (ci) {
- visible_in_tree = ci->is_visible_in_tree();
+ parent_visible_in_tree = ci->is_visible_in_tree();
C = ci->children_items.push_back(this);
} else {
CanvasLayer *cl = Object::cast_to<CanvasLayer>(parent);
if (cl) {
- visible_in_tree = cl->is_visible();
+ parent_visible_in_tree = cl->is_visible();
} else {
// Look for a window.
Viewport *viewport = nullptr;
@@ -288,9 +295,9 @@ void CanvasItem::_notification(int p_what) {
window = Object::cast_to<Window>(viewport);
if (window) {
window->connect(SceneStringNames::get_singleton()->visibility_changed, callable_mp(this, &CanvasItem::_window_visibility_changed));
- visible_in_tree = window->is_visible();
+ parent_visible_in_tree = window->is_visible();
} else {
- visible_in_tree = true;
+ parent_visible_in_tree = true;
}
}
}
@@ -333,7 +340,7 @@ void CanvasItem::_notification(int p_what) {
window->disconnect(SceneStringNames::get_singleton()->visibility_changed, callable_mp(this, &CanvasItem::_window_visibility_changed));
}
global_invalid = true;
- visible_in_tree = false;
+ parent_visible_in_tree = false;
} break;
case NOTIFICATION_VISIBILITY_CHANGED: {
diff --git a/scene/main/canvas_item.h b/scene/main/canvas_item.h
index 2a9e7bac3d..c0558b6be2 100644
--- a/scene/main/canvas_item.h
+++ b/scene/main/canvas_item.h
@@ -85,7 +85,7 @@ private:
Window *window = nullptr;
bool first_draw = false;
bool visible = true;
- bool visible_in_tree = false;
+ bool parent_visible_in_tree = false;
bool clip_children = false;
bool pending_update = false;
bool top_level = false;
@@ -108,7 +108,7 @@ private:
void _top_level_raise_self();
- void _propagate_visibility_changed(bool p_visible, bool p_was_visible = false);
+ void _propagate_visibility_changed(bool p_visible, bool p_is_source = false);
void _update_callback();
diff --git a/scene/main/canvas_layer.cpp b/scene/main/canvas_layer.cpp
index 6c627857fa..be24620904 100644
--- a/scene/main/canvas_layer.cpp
+++ b/scene/main/canvas_layer.cpp
@@ -61,7 +61,7 @@ void CanvasLayer::set_visible(bool p_visible) {
if (c->is_visible()) {
c->_propagate_visibility_changed(p_visible);
} else {
- c->notification(CanvasItem::NOTIFICATION_VISIBILITY_CHANGED);
+ c->parent_visible_in_tree = p_visible;
}
}
}
diff --git a/scene/multiplayer/scene_cache_interface.cpp b/scene/multiplayer/scene_cache_interface.cpp
index 2f278ed864..f05dc5a2da 100644
--- a/scene/multiplayer/scene_cache_interface.cpp
+++ b/scene/multiplayer/scene_cache_interface.cpp
@@ -139,74 +139,46 @@ void SceneCacheInterface::process_confirm_path(int p_from, const uint8_t *p_pack
E->get() = true;
}
-bool SceneCacheInterface::_send_confirm_path(Node *p_node, NodePath p_path, PathSentCache *psc, int p_target) {
- bool has_all_peers = true;
- List<int> peers_to_add; // If one is missing, take note to add it.
-
- for (const Set<int>::Element *E = multiplayer->get_connected_peers().front(); E; E = E->next()) {
- if (p_target < 0 && E->get() == -p_target) {
- continue; // Continue, excluded.
- }
-
- if (p_target > 0 && E->get() != p_target) {
- continue; // Continue, not for this peer.
- }
-
- Map<int, bool>::Element *F = psc->confirmed_peers.find(E->get());
-
- if (!F || !F->get()) {
- // Path was not cached, or was cached but is unconfirmed.
- if (!F) {
- // Not cached at all, take note.
- peers_to_add.push_back(E->get());
- }
+Error SceneCacheInterface::_send_confirm_path(Node *p_node, NodePath p_path, PathSentCache *psc, const List<int> &p_peers) {
+ // Encode function name.
+ const CharString path = String(p_path).utf8();
+ const int path_len = encode_cstring(path.get_data(), nullptr);
- has_all_peers = false;
- }
- }
-
- if (peers_to_add.size() > 0) {
- // Those that need to be added, send a message for this.
-
- // Encode function name.
- const CharString path = String(p_path).utf8();
- const int path_len = encode_cstring(path.get_data(), nullptr);
+ // Extract MD5 from rpc methods list.
+ const String methods_md5 = multiplayer->get_rpc_md5(p_node);
+ const int methods_md5_len = 33; // 32 + 1 for the `0` that is added by the encoder.
- // Extract MD5 from rpc methods list.
- const String methods_md5 = multiplayer->get_rpc_md5(p_node);
- const int methods_md5_len = 33; // 32 + 1 for the `0` that is added by the encoder.
-
- Vector<uint8_t> packet;
- packet.resize(1 + 4 + path_len + methods_md5_len);
- int ofs = 0;
+ Vector<uint8_t> packet;
+ packet.resize(1 + 4 + path_len + methods_md5_len);
+ int ofs = 0;
- packet.write[ofs] = MultiplayerAPI::NETWORK_COMMAND_SIMPLIFY_PATH;
- ofs += 1;
+ packet.write[ofs] = MultiplayerAPI::NETWORK_COMMAND_SIMPLIFY_PATH;
+ ofs += 1;
- ofs += encode_cstring(methods_md5.utf8().get_data(), &packet.write[ofs]);
+ ofs += encode_cstring(methods_md5.utf8().get_data(), &packet.write[ofs]);
- ofs += encode_uint32(psc->id, &packet.write[ofs]);
+ ofs += encode_uint32(psc->id, &packet.write[ofs]);
- ofs += encode_cstring(path.get_data(), &packet.write[ofs]);
+ ofs += encode_cstring(path.get_data(), &packet.write[ofs]);
- Ref<MultiplayerPeer> multiplayer_peer = multiplayer->get_multiplayer_peer();
- ERR_FAIL_COND_V(multiplayer_peer.is_null(), false);
+ Ref<MultiplayerPeer> multiplayer_peer = multiplayer->get_multiplayer_peer();
+ ERR_FAIL_COND_V(multiplayer_peer.is_null(), ERR_BUG);
#ifdef DEBUG_ENABLED
- multiplayer->profile_bandwidth("out", packet.size() * peers_to_add.size());
+ multiplayer->profile_bandwidth("out", packet.size() * p_peers.size());
#endif
- for (int &E : peers_to_add) {
- multiplayer_peer->set_target_peer(E); // To all of you.
- multiplayer_peer->set_transfer_channel(0);
- multiplayer_peer->set_transfer_mode(Multiplayer::TRANSFER_MODE_RELIABLE);
- multiplayer_peer->put_packet(packet.ptr(), packet.size());
-
- psc->confirmed_peers.insert(E, false); // Insert into confirmed, but as false since it was not confirmed.
- }
+ Error err = OK;
+ for (int peer_id : p_peers) {
+ multiplayer_peer->set_target_peer(peer_id);
+ multiplayer_peer->set_transfer_channel(0);
+ multiplayer_peer->set_transfer_mode(Multiplayer::TRANSFER_MODE_RELIABLE);
+ err = multiplayer_peer->put_packet(packet.ptr(), packet.size());
+ ERR_FAIL_COND_V(err != OK, err);
+ // Insert into confirmed, but as false since it was not confirmed.
+ psc->confirmed_peers.insert(peer_id, false);
}
-
- return has_all_peers;
+ return err;
}
bool SceneCacheInterface::is_cache_confirmed(NodePath p_path, int p_peer) {
@@ -230,7 +202,43 @@ bool SceneCacheInterface::send_object_cache(Object *p_obj, NodePath p_path, int
}
r_id = psc->id;
- return _send_confirm_path(node, p_path, psc, p_peer_id);
+ bool has_all_peers = true;
+ List<int> peers_to_add; // If one is missing, take note to add it.
+
+ if (p_peer_id > 0) {
+ // Fast single peer check.
+ Map<int, bool>::Element *F = psc->confirmed_peers.find(p_peer_id);
+ if (!F) {
+ peers_to_add.push_back(p_peer_id); // Need to also be notified.
+ has_all_peers = false;
+ } else if (!F->get()) {
+ has_all_peers = false;
+ }
+ } else {
+ // Long and painful.
+ for (const Set<int>::Element *E = multiplayer->get_connected_peers().front(); E; E = E->next()) {
+ if (p_peer_id < 0 && E->get() == -p_peer_id) {
+ continue; // Continue, excluded.
+ }
+ if (p_peer_id > 0 && E->get() != p_peer_id) {
+ continue; // Continue, not for this peer.
+ }
+
+ Map<int, bool>::Element *F = psc->confirmed_peers.find(E->get());
+ if (!F) {
+ peers_to_add.push_back(E->get()); // Need to also be notified.
+ has_all_peers = false;
+ } else if (!F->get()) {
+ has_all_peers = false;
+ }
+ }
+ }
+
+ if (peers_to_add.size()) {
+ _send_confirm_path(node, p_path, psc, peers_to_add);
+ }
+
+ return has_all_peers;
}
Object *SceneCacheInterface::get_cached_object(int p_from, uint32_t p_cache_id) {
diff --git a/scene/multiplayer/scene_cache_interface.h b/scene/multiplayer/scene_cache_interface.h
index 91a53cb948..c709d26b51 100644
--- a/scene/multiplayer/scene_cache_interface.h
+++ b/scene/multiplayer/scene_cache_interface.h
@@ -60,7 +60,7 @@ private:
int last_send_cache_id = 1;
protected:
- bool _send_confirm_path(Node *p_node, NodePath p_path, PathSentCache *psc, int p_target);
+ Error _send_confirm_path(Node *p_node, NodePath p_path, PathSentCache *psc, const List<int> &p_peers);
static MultiplayerCacheInterface *_create(MultiplayerAPI *p_multiplayer);
public:
diff --git a/scene/multiplayer/scene_replication_interface.cpp b/scene/multiplayer/scene_replication_interface.cpp
index 25a704b37e..0764f136e4 100644
--- a/scene/multiplayer/scene_replication_interface.cpp
+++ b/scene/multiplayer/scene_replication_interface.cpp
@@ -350,11 +350,12 @@ void SceneReplicationInterface::_send_sync(int p_peer, uint64_t p_msec) {
}
if (size) {
uint32_t net_id = rep_state->get_net_id(oid);
- if (net_id == 0) {
+ if (net_id == 0 || (net_id & 0x80000000)) {
// First time path based ID.
NodePath rel_path = multiplayer->get_root_path().rel_path_to(sync->get_path());
int path_id = 0;
multiplayer->send_object_cache(sync, rel_path, p_peer, path_id);
+ ERR_CONTINUE_MSG(net_id && net_id != (uint32_t(path_id) | 0x80000000), "This should never happen!");
net_id = path_id;
rep_state->set_net_id(oid, net_id | 0x80000000);
}
diff --git a/scene/resources/tile_set.cpp b/scene/resources/tile_set.cpp
index 1e84947b87..1174117028 100644
--- a/scene/resources/tile_set.cpp
+++ b/scene/resources/tile_set.cpp
@@ -4432,6 +4432,10 @@ void TileSetAtlasSource::_update_padded_texture() {
Ref<Image> src = texture->get_image();
+ if (!src.is_valid()) {
+ return;
+ }
+
Ref<Image> image;
image.instantiate();
image->create(size.x, size.y, false, src->get_format());