|
@@ -48,46 +48,29 @@ bool VisibilityNotifier2D::_edit_use_rect() const {
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
-void VisibilityNotifier2D::_enter_viewport(Viewport *p_viewport) {
|
|
|
- ERR_FAIL_COND(viewports.has(p_viewport));
|
|
|
- viewports.insert(p_viewport);
|
|
|
-
|
|
|
- if (is_inside_tree() && Engine::get_singleton()->is_editor_hint()) {
|
|
|
+void VisibilityNotifier2D::_visibility_enter() {
|
|
|
+ if (!is_inside_tree() || Engine::get_singleton()->is_editor_hint()) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- if (viewports.size() == 1) {
|
|
|
- emit_signal(SceneStringNames::get_singleton()->screen_entered);
|
|
|
-
|
|
|
- _screen_enter();
|
|
|
- }
|
|
|
- emit_signal(SceneStringNames::get_singleton()->viewport_entered, p_viewport);
|
|
|
+ on_screen = true;
|
|
|
+ emit_signal(SceneStringNames::get_singleton()->screen_entered);
|
|
|
+ _screen_enter();
|
|
|
}
|
|
|
-
|
|
|
-void VisibilityNotifier2D::_exit_viewport(Viewport *p_viewport) {
|
|
|
- ERR_FAIL_COND(!viewports.has(p_viewport));
|
|
|
- viewports.erase(p_viewport);
|
|
|
-
|
|
|
- if (is_inside_tree() && Engine::get_singleton()->is_editor_hint()) {
|
|
|
+void VisibilityNotifier2D::_visibility_exit() {
|
|
|
+ if (!is_inside_tree() || Engine::get_singleton()->is_editor_hint()) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- emit_signal(SceneStringNames::get_singleton()->viewport_exited, p_viewport);
|
|
|
- if (viewports.size() == 0) {
|
|
|
- emit_signal(SceneStringNames::get_singleton()->screen_exited);
|
|
|
-
|
|
|
- _screen_exit();
|
|
|
- }
|
|
|
+ on_screen = false;
|
|
|
+ emit_signal(SceneStringNames::get_singleton()->screen_exited);
|
|
|
+ _screen_exit();
|
|
|
}
|
|
|
|
|
|
void VisibilityNotifier2D::set_rect(const Rect2 &p_rect) {
|
|
|
rect = p_rect;
|
|
|
if (is_inside_tree()) {
|
|
|
- get_world_2d()->_update_notifier(this, get_global_transform().xform(rect));
|
|
|
- if (Engine::get_singleton()->is_editor_hint()) {
|
|
|
- update();
|
|
|
- item_rect_changed();
|
|
|
- }
|
|
|
+ RS::get_singleton()->canvas_item_set_visibility_notifier(get_canvas_item(), true, rect, callable_mp(this, &VisibilityNotifier2D::_visibility_enter), callable_mp(this, &VisibilityNotifier2D::_visibility_exit));
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -99,11 +82,8 @@ void VisibilityNotifier2D::_notification(int p_what) {
|
|
|
switch (p_what) {
|
|
|
case NOTIFICATION_ENTER_TREE: {
|
|
|
//get_world_2d()->
|
|
|
- get_world_2d()->_register_notifier(this, get_global_transform().xform(rect));
|
|
|
- } break;
|
|
|
- case NOTIFICATION_TRANSFORM_CHANGED: {
|
|
|
- //get_world_2d()->
|
|
|
- get_world_2d()->_update_notifier(this, get_global_transform().xform(rect));
|
|
|
+ on_screen = false;
|
|
|
+ RS::get_singleton()->canvas_item_set_visibility_notifier(get_canvas_item(), true, rect, callable_mp(this, &VisibilityNotifier2D::_visibility_enter), callable_mp(this, &VisibilityNotifier2D::_visibility_exit));
|
|
|
} break;
|
|
|
case NOTIFICATION_DRAW: {
|
|
|
if (Engine::get_singleton()->is_editor_hint()) {
|
|
@@ -111,13 +91,14 @@ void VisibilityNotifier2D::_notification(int p_what) {
|
|
|
}
|
|
|
} break;
|
|
|
case NOTIFICATION_EXIT_TREE: {
|
|
|
- get_world_2d()->_remove_notifier(this);
|
|
|
+ on_screen = false;
|
|
|
+ RS::get_singleton()->canvas_item_set_visibility_notifier(get_canvas_item(), false, Rect2(), Callable(), Callable());
|
|
|
} break;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
bool VisibilityNotifier2D::is_on_screen() const {
|
|
|
- return viewports.size() > 0;
|
|
|
+ return on_screen;
|
|
|
}
|
|
|
|
|
|
void VisibilityNotifier2D::_bind_methods() {
|
|
@@ -127,235 +108,106 @@ void VisibilityNotifier2D::_bind_methods() {
|
|
|
|
|
|
ADD_PROPERTY(PropertyInfo(Variant::RECT2, "rect"), "set_rect", "get_rect");
|
|
|
|
|
|
- ADD_SIGNAL(MethodInfo("viewport_entered", PropertyInfo(Variant::OBJECT, "viewport", PROPERTY_HINT_RESOURCE_TYPE, "Viewport")));
|
|
|
- ADD_SIGNAL(MethodInfo("viewport_exited", PropertyInfo(Variant::OBJECT, "viewport", PROPERTY_HINT_RESOURCE_TYPE, "Viewport")));
|
|
|
ADD_SIGNAL(MethodInfo("screen_entered"));
|
|
|
ADD_SIGNAL(MethodInfo("screen_exited"));
|
|
|
}
|
|
|
|
|
|
VisibilityNotifier2D::VisibilityNotifier2D() {
|
|
|
rect = Rect2(-10, -10, 20, 20);
|
|
|
- set_notify_transform(true);
|
|
|
}
|
|
|
|
|
|
//////////////////////////////////////
|
|
|
|
|
|
void VisibilityEnabler2D::_screen_enter() {
|
|
|
- for (Map<Node *, Variant>::Element *E = nodes.front(); E; E = E->next()) {
|
|
|
- _change_node_state(E->key(), true);
|
|
|
- }
|
|
|
-
|
|
|
- if (enabler[ENABLER_PARENT_PHYSICS_PROCESS] && get_parent()) {
|
|
|
- get_parent()->set_physics_process(true);
|
|
|
- }
|
|
|
- if (enabler[ENABLER_PARENT_PROCESS] && get_parent()) {
|
|
|
- get_parent()->set_process(true);
|
|
|
- }
|
|
|
-
|
|
|
- visible = true;
|
|
|
+ _update_enable_mode(true);
|
|
|
}
|
|
|
|
|
|
void VisibilityEnabler2D::_screen_exit() {
|
|
|
- for (Map<Node *, Variant>::Element *E = nodes.front(); E; E = E->next()) {
|
|
|
- _change_node_state(E->key(), false);
|
|
|
- }
|
|
|
-
|
|
|
- if (enabler[ENABLER_PARENT_PHYSICS_PROCESS] && get_parent()) {
|
|
|
- get_parent()->set_physics_process(false);
|
|
|
- }
|
|
|
- if (enabler[ENABLER_PARENT_PROCESS] && get_parent()) {
|
|
|
- get_parent()->set_process(false);
|
|
|
- }
|
|
|
-
|
|
|
- visible = false;
|
|
|
+ _update_enable_mode(false);
|
|
|
}
|
|
|
|
|
|
-void VisibilityEnabler2D::_find_nodes(Node *p_node) {
|
|
|
- bool add = false;
|
|
|
- Variant meta;
|
|
|
-
|
|
|
- {
|
|
|
- RigidBody2D *rb2d = Object::cast_to<RigidBody2D>(p_node);
|
|
|
- if (rb2d && ((rb2d->get_mode() == RigidBody2D::MODE_DYNAMIC || rb2d->get_mode() == RigidBody2D::MODE_DYNAMIC_LOCKED))) {
|
|
|
- add = true;
|
|
|
- meta = rb2d->get_mode();
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- {
|
|
|
- AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(p_node);
|
|
|
- if (ap) {
|
|
|
- add = true;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- {
|
|
|
- AnimatedSprite2D *as = Object::cast_to<AnimatedSprite2D>(p_node);
|
|
|
- if (as) {
|
|
|
- add = true;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- {
|
|
|
- GPUParticles2D *ps = Object::cast_to<GPUParticles2D>(p_node);
|
|
|
- if (ps) {
|
|
|
- add = true;
|
|
|
- }
|
|
|
+void VisibilityEnabler2D::set_enable_mode(EnableMode p_mode) {
|
|
|
+ enable_mode = p_mode;
|
|
|
+ if (is_inside_tree()) {
|
|
|
+ _update_enable_mode(is_on_screen());
|
|
|
}
|
|
|
+}
|
|
|
+VisibilityEnabler2D::EnableMode VisibilityEnabler2D::get_enable_mode() {
|
|
|
+ return enable_mode;
|
|
|
+}
|
|
|
|
|
|
- if (add) {
|
|
|
- p_node->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &VisibilityEnabler2D::_node_removed), varray(p_node), CONNECT_ONESHOT);
|
|
|
- nodes[p_node] = meta;
|
|
|
- _change_node_state(p_node, false);
|
|
|
+void VisibilityEnabler2D::set_enable_node_path(NodePath p_path) {
|
|
|
+ if (enable_node_path == p_path) {
|
|
|
+ return;
|
|
|
}
|
|
|
-
|
|
|
- for (int i = 0; i < p_node->get_child_count(); i++) {
|
|
|
- Node *c = p_node->get_child(i);
|
|
|
- if (c->get_filename() != String()) {
|
|
|
- continue; //skip, instance
|
|
|
+ enable_node_path = p_path;
|
|
|
+ if (is_inside_tree()) {
|
|
|
+ node_id = ObjectID();
|
|
|
+ Node *node = get_node(enable_node_path);
|
|
|
+ if (node) {
|
|
|
+ node_id = node->get_instance_id();
|
|
|
+ _update_enable_mode(is_on_screen());
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+NodePath VisibilityEnabler2D::get_enable_node_path() {
|
|
|
+ return enable_node_path;
|
|
|
+}
|
|
|
+
|
|
|
+void VisibilityEnabler2D::_update_enable_mode(bool p_enable) {
|
|
|
+ Node *node = static_cast<Node *>(ObjectDB::get_instance(node_id));
|
|
|
+ if (node) {
|
|
|
+ if (p_enable) {
|
|
|
+ switch (enable_mode) {
|
|
|
+ case ENABLE_MODE_INHERIT: {
|
|
|
+ node->set_process_mode(PROCESS_MODE_INHERIT);
|
|
|
+ } break;
|
|
|
+ case ENABLE_MODE_ALWAYS: {
|
|
|
+ node->set_process_mode(PROCESS_MODE_ALWAYS);
|
|
|
+ } break;
|
|
|
+ case ENABLE_MODE_WHEN_PAUSED: {
|
|
|
+ node->set_process_mode(PROCESS_MODE_WHEN_PAUSED);
|
|
|
+ } break;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ node->set_process_mode(PROCESS_MODE_DISABLED);
|
|
|
}
|
|
|
-
|
|
|
- _find_nodes(c);
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
void VisibilityEnabler2D::_notification(int p_what) {
|
|
|
if (p_what == NOTIFICATION_ENTER_TREE) {
|
|
|
if (Engine::get_singleton()->is_editor_hint()) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- Node *from = this;
|
|
|
- //find where current scene starts
|
|
|
- while (from->get_parent() && from->get_filename() == String()) {
|
|
|
- from = from->get_parent();
|
|
|
- }
|
|
|
-
|
|
|
- _find_nodes(from);
|
|
|
-
|
|
|
- // We need to defer the call of set_process and set_physics_process,
|
|
|
- // otherwise they are overwritten inside NOTIFICATION_READY.
|
|
|
- // We can't use call_deferred, because it happens after a physics frame.
|
|
|
- // The ready signal works as it's emitted immediately after NOTIFICATION_READY.
|
|
|
-
|
|
|
- if (enabler[ENABLER_PARENT_PHYSICS_PROCESS] && get_parent()) {
|
|
|
- get_parent()->connect(SceneStringNames::get_singleton()->ready,
|
|
|
- callable_mp(get_parent(), &Node::set_physics_process), varray(false), CONNECT_ONESHOT);
|
|
|
- }
|
|
|
- if (enabler[ENABLER_PARENT_PROCESS] && get_parent()) {
|
|
|
- get_parent()->connect(SceneStringNames::get_singleton()->ready,
|
|
|
- callable_mp(get_parent(), &Node::set_process), varray(false), CONNECT_ONESHOT);
|
|
|
+ node_id = ObjectID();
|
|
|
+ Node *node = get_node(enable_node_path);
|
|
|
+ if (node) {
|
|
|
+ node_id = node->get_instance_id();
|
|
|
+ node->set_process_mode(PROCESS_MODE_DISABLED);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if (p_what == NOTIFICATION_EXIT_TREE) {
|
|
|
- if (Engine::get_singleton()->is_editor_hint()) {
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- for (Map<Node *, Variant>::Element *E = nodes.front(); E; E = E->next()) {
|
|
|
- if (!visible) {
|
|
|
- _change_node_state(E->key(), true);
|
|
|
- }
|
|
|
- E->key()->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &VisibilityEnabler2D::_node_removed));
|
|
|
- }
|
|
|
-
|
|
|
- nodes.clear();
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-void VisibilityEnabler2D::_change_node_state(Node *p_node, bool p_enabled) {
|
|
|
- ERR_FAIL_COND(!nodes.has(p_node));
|
|
|
-
|
|
|
- if (enabler[ENABLER_FREEZE_BODIES]) {
|
|
|
- RigidBody2D *rb = Object::cast_to<RigidBody2D>(p_node);
|
|
|
- if (rb) {
|
|
|
- rb->set_sleeping(!p_enabled);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (enabler[ENABLER_PAUSE_ANIMATIONS]) {
|
|
|
- AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(p_node);
|
|
|
-
|
|
|
- if (ap) {
|
|
|
- ap->set_active(p_enabled);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (enabler[ENABLER_PAUSE_ANIMATED_SPRITES]) {
|
|
|
- AnimatedSprite2D *as = Object::cast_to<AnimatedSprite2D>(p_node);
|
|
|
-
|
|
|
- if (as) {
|
|
|
- if (p_enabled) {
|
|
|
- as->play();
|
|
|
- } else {
|
|
|
- as->stop();
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (enabler[ENABLER_PAUSE_PARTICLES]) {
|
|
|
- GPUParticles2D *ps = Object::cast_to<GPUParticles2D>(p_node);
|
|
|
-
|
|
|
- if (ps) {
|
|
|
- ps->set_emitting(p_enabled);
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-void VisibilityEnabler2D::_node_removed(Node *p_node) {
|
|
|
- if (!visible) {
|
|
|
- _change_node_state(p_node, true);
|
|
|
+ node_id = ObjectID();
|
|
|
}
|
|
|
- nodes.erase(p_node);
|
|
|
-}
|
|
|
-
|
|
|
-TypedArray<String> VisibilityEnabler2D::get_configuration_warnings() const {
|
|
|
- TypedArray<String> warnings = Node::get_configuration_warnings();
|
|
|
-
|
|
|
-#ifdef TOOLS_ENABLED
|
|
|
- if (is_inside_tree() && get_parent() && (get_parent()->get_filename() == String() && get_parent() != get_tree()->get_edited_scene_root())) {
|
|
|
- warnings.push_back(TTR("VisibilityEnabler2D works best when used with the edited scene root directly as parent."));
|
|
|
- }
|
|
|
-#endif
|
|
|
- return warnings;
|
|
|
}
|
|
|
|
|
|
void VisibilityEnabler2D::_bind_methods() {
|
|
|
- ClassDB::bind_method(D_METHOD("set_enabler", "enabler", "enabled"), &VisibilityEnabler2D::set_enabler);
|
|
|
- ClassDB::bind_method(D_METHOD("is_enabler_enabled", "enabler"), &VisibilityEnabler2D::is_enabler_enabled);
|
|
|
- ClassDB::bind_method(D_METHOD("_node_removed"), &VisibilityEnabler2D::_node_removed);
|
|
|
+ ClassDB::bind_method(D_METHOD("set_enable_mode", "mode"), &VisibilityEnabler2D::set_enable_mode);
|
|
|
+ ClassDB::bind_method(D_METHOD("get_enable_mode"), &VisibilityEnabler2D::get_enable_mode);
|
|
|
|
|
|
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "pause_animations"), "set_enabler", "is_enabler_enabled", ENABLER_PAUSE_ANIMATIONS);
|
|
|
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "freeze_bodies"), "set_enabler", "is_enabler_enabled", ENABLER_FREEZE_BODIES);
|
|
|
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "pause_particles"), "set_enabler", "is_enabler_enabled", ENABLER_PAUSE_PARTICLES);
|
|
|
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "pause_animated_sprites"), "set_enabler", "is_enabler_enabled", ENABLER_PAUSE_ANIMATED_SPRITES);
|
|
|
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "process_parent"), "set_enabler", "is_enabler_enabled", ENABLER_PARENT_PROCESS);
|
|
|
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "physics_process_parent"), "set_enabler", "is_enabler_enabled", ENABLER_PARENT_PHYSICS_PROCESS);
|
|
|
+ ClassDB::bind_method(D_METHOD("set_enable_node_path", "path"), &VisibilityEnabler2D::set_enable_node_path);
|
|
|
+ ClassDB::bind_method(D_METHOD("get_enable_node_path"), &VisibilityEnabler2D::get_enable_node_path);
|
|
|
|
|
|
- BIND_ENUM_CONSTANT(ENABLER_PAUSE_ANIMATIONS);
|
|
|
- BIND_ENUM_CONSTANT(ENABLER_FREEZE_BODIES);
|
|
|
- BIND_ENUM_CONSTANT(ENABLER_PAUSE_PARTICLES);
|
|
|
- BIND_ENUM_CONSTANT(ENABLER_PARENT_PROCESS);
|
|
|
- BIND_ENUM_CONSTANT(ENABLER_PARENT_PHYSICS_PROCESS);
|
|
|
- BIND_ENUM_CONSTANT(ENABLER_PAUSE_ANIMATED_SPRITES);
|
|
|
- BIND_ENUM_CONSTANT(ENABLER_MAX);
|
|
|
-}
|
|
|
+ ADD_GROUP("Enabling", "enable_");
|
|
|
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "enable_mode", PROPERTY_HINT_ENUM, "Inherit,Always,WhenPaused"), "set_enable_mode", "get_enable_mode");
|
|
|
+ ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "enable_node_path"), "set_enable_node_path", "get_enable_node_path");
|
|
|
|
|
|
-void VisibilityEnabler2D::set_enabler(Enabler p_enabler, bool p_enable) {
|
|
|
- ERR_FAIL_INDEX(p_enabler, ENABLER_MAX);
|
|
|
- enabler[p_enabler] = p_enable;
|
|
|
-}
|
|
|
-
|
|
|
-bool VisibilityEnabler2D::is_enabler_enabled(Enabler p_enabler) const {
|
|
|
- ERR_FAIL_INDEX_V(p_enabler, ENABLER_MAX, false);
|
|
|
- return enabler[p_enabler];
|
|
|
+ BIND_ENUM_CONSTANT(ENABLE_MODE_INHERIT);
|
|
|
+ BIND_ENUM_CONSTANT(ENABLE_MODE_ALWAYS);
|
|
|
+ BIND_ENUM_CONSTANT(ENABLE_MODE_WHEN_PAUSED);
|
|
|
}
|
|
|
|
|
|
VisibilityEnabler2D::VisibilityEnabler2D() {
|
|
|
- for (int i = 0; i < ENABLER_MAX; i++) {
|
|
|
- enabler[i] = true;
|
|
|
- }
|
|
|
- enabler[ENABLER_PARENT_PROCESS] = false;
|
|
|
- enabler[ENABLER_PARENT_PHYSICS_PROCESS] = false;
|
|
|
}
|