Browse Source

Merge pull request #46191 from reduz/refactor-process-mode

Refactor Process Mode
Rémi Verschelde 4 years ago
parent
commit
04cb7e638c

+ 4 - 0
editor/editor_inspector.cpp

@@ -1761,6 +1761,10 @@ void EditorInspector::update_tree() {
 			continue;
 		}
 
+		if (p.name == "script") {
+			category_vbox = nullptr; // script should go into its own category
+		}
+
 		if (p.usage & PROPERTY_USAGE_HIGH_END_GFX && RS::get_singleton()->is_low_end()) {
 			continue; //do not show this property in low end gfx
 		}

+ 1 - 1
editor/plugins/gpu_particles_2d_editor_plugin.cpp

@@ -81,7 +81,7 @@ void GPUParticles2DEditorPlugin::_menu_callback(int p_idx) {
 			cpu_particles->set_name(particles->get_name());
 			cpu_particles->set_transform(particles->get_transform());
 			cpu_particles->set_visible(particles->is_visible());
-			cpu_particles->set_pause_mode(particles->get_pause_mode());
+			cpu_particles->set_process_mode(particles->get_process_mode());
 			cpu_particles->set_z_index(particles->get_z_index());
 
 			UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();

+ 1 - 1
editor/plugins/gpu_particles_3d_editor_plugin.cpp

@@ -263,7 +263,7 @@ void GPUParticles3DEditor::_menu_option(int p_option) {
 			cpu_particles->set_name(node->get_name());
 			cpu_particles->set_transform(node->get_transform());
 			cpu_particles->set_visible(node->is_visible());
-			cpu_particles->set_pause_mode(node->get_pause_mode());
+			cpu_particles->set_process_mode(node->get_process_mode());
 
 			UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
 			ur->create_action(TTR("Convert to CPUParticles3D"));

+ 9 - 0
editor/scene_tree_editor.cpp

@@ -236,6 +236,8 @@ bool SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent, bool p_scroll
 		item->set_text(0, node_name);
 		item->set_selectable(0, marked_selectable);
 		item->set_custom_color(0, get_theme_color("accent_color", "Editor"));
+	} else if (!p_node->can_process()) {
+		item->set_custom_color(0, get_theme_color("disabled_font_color", "Editor"));
 	} else if (!marked_selectable && !marked_children_selectable) {
 		Node *node = p_node;
 		while (node) {
@@ -585,6 +587,11 @@ void SceneTreeEditor::_test_update_tree() {
 	tree_dirty = true;
 }
 
+void SceneTreeEditor::_tree_process_mode_changed() {
+	MessageQueue::get_singleton()->push_call(this, "_update_tree");
+	tree_dirty = true;
+}
+
 void SceneTreeEditor::_tree_changed() {
 	if (EditorNode::get_singleton()->is_exiting()) {
 		return; //speed up exit
@@ -655,6 +662,7 @@ void SceneTreeEditor::_notification(int p_what) {
 	switch (p_what) {
 		case NOTIFICATION_ENTER_TREE: {
 			get_tree()->connect("tree_changed", callable_mp(this, &SceneTreeEditor::_tree_changed));
+			get_tree()->connect("tree_process_mode_changed", callable_mp(this, &SceneTreeEditor::_tree_process_mode_changed));
 			get_tree()->connect("node_removed", callable_mp(this, &SceneTreeEditor::_node_removed));
 			get_tree()->connect("node_renamed", callable_mp(this, &SceneTreeEditor::_node_renamed));
 			get_tree()->connect("node_configuration_warning_changed", callable_mp(this, &SceneTreeEditor::_warning_changed));
@@ -665,6 +673,7 @@ void SceneTreeEditor::_notification(int p_what) {
 		} break;
 		case NOTIFICATION_EXIT_TREE: {
 			get_tree()->disconnect("tree_changed", callable_mp(this, &SceneTreeEditor::_tree_changed));
+			get_tree()->disconnect("tree_process_mode_changed", callable_mp(this, &SceneTreeEditor::_tree_process_mode_changed));
 			get_tree()->disconnect("node_removed", callable_mp(this, &SceneTreeEditor::_node_removed));
 			get_tree()->disconnect("node_renamed", callable_mp(this, &SceneTreeEditor::_node_renamed));
 			tree->disconnect("item_collapsed", callable_mp(this, &SceneTreeEditor::_cell_collapsed));

+ 1 - 0
editor/scene_tree_editor.h

@@ -75,6 +75,7 @@ class SceneTreeEditor : public Control {
 	void _test_update_tree();
 	void _update_tree(bool p_scroll_to_selected = false);
 	void _tree_changed();
+	void _tree_process_mode_changed();
 	void _node_removed(Node *p_node);
 	void _node_renamed(Node *p_node);
 

+ 13 - 13
scene/2d/camera_2d.cpp

@@ -63,11 +63,11 @@ void Camera2D::_update_scroll() {
 	};
 }
 
-void Camera2D::_update_process_mode() {
+void Camera2D::_update_process_callback() {
 	if (Engine::get_singleton()->is_editor_hint()) {
 		set_process_internal(false);
 		set_physics_process_internal(false);
-	} else if (process_mode == CAMERA2D_PROCESS_IDLE) {
+	} else if (process_callback == CAMERA2D_PROCESS_IDLE) {
 		set_process_internal(true);
 		set_physics_process_internal(false);
 	} else {
@@ -157,7 +157,7 @@ Transform2D Camera2D::get_camera_transform() {
 		}
 
 		if (smoothing_enabled && !Engine::get_singleton()->is_editor_hint()) {
-			float c = smoothing * (process_mode == CAMERA2D_PROCESS_PHYSICS ? get_physics_process_delta_time() : get_process_delta_time());
+			float c = smoothing * (process_callback == CAMERA2D_PROCESS_PHYSICS ? get_physics_process_delta_time() : get_process_delta_time());
 			smoothed_camera_pos = ((camera_pos - smoothed_camera_pos) * c) + smoothed_camera_pos;
 			ret_camera_pos = smoothed_camera_pos;
 			//camera_pos=camera_pos*(1.0-smoothing)+new_camera_pos*smoothing;
@@ -247,7 +247,7 @@ void Camera2D::_notification(int p_what) {
 			add_to_group(group_name);
 			add_to_group(canvas_group_name);
 
-			_update_process_mode();
+			_update_process_callback();
 			_update_scroll();
 			first = true;
 
@@ -375,17 +375,17 @@ bool Camera2D::is_rotating() const {
 	return rotating;
 }
 
-void Camera2D::set_process_mode(Camera2DProcessMode p_mode) {
-	if (process_mode == p_mode) {
+void Camera2D::set_process_callback(Camera2DProcessCallback p_mode) {
+	if (process_callback == p_mode) {
 		return;
 	}
 
-	process_mode = p_mode;
-	_update_process_mode();
+	process_callback = p_mode;
+	_update_process_callback();
 }
 
-Camera2D::Camera2DProcessMode Camera2D::get_process_mode() const {
-	return process_mode;
+Camera2D::Camera2DProcessCallback Camera2D::get_process_callback() const {
+	return process_callback;
 }
 
 void Camera2D::_make_current(Object *p_which) {
@@ -651,8 +651,8 @@ void Camera2D::_bind_methods() {
 
 	ClassDB::bind_method(D_METHOD("_update_scroll"), &Camera2D::_update_scroll);
 
-	ClassDB::bind_method(D_METHOD("set_process_mode", "mode"), &Camera2D::set_process_mode);
-	ClassDB::bind_method(D_METHOD("get_process_mode"), &Camera2D::get_process_mode);
+	ClassDB::bind_method(D_METHOD("set_process_callback", "mode"), &Camera2D::set_process_callback);
+	ClassDB::bind_method(D_METHOD("get_process_callback"), &Camera2D::get_process_callback);
 
 	ClassDB::bind_method(D_METHOD("_set_current", "current"), &Camera2D::_set_current);
 	ClassDB::bind_method(D_METHOD("is_current"), &Camera2D::is_current);
@@ -714,7 +714,7 @@ void Camera2D::_bind_methods() {
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "current"), "_set_current", "is_current");
 	ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "zoom"), "set_zoom", "get_zoom");
 	ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "custom_viewport", PROPERTY_HINT_RESOURCE_TYPE, "Viewport", 0), "set_custom_viewport", "get_custom_viewport");
-	ADD_PROPERTY(PropertyInfo(Variant::INT, "process_mode", PROPERTY_HINT_ENUM, "Physics,Idle"), "set_process_mode", "get_process_mode");
+	ADD_PROPERTY(PropertyInfo(Variant::INT, "process_callback", PROPERTY_HINT_ENUM, "Physics,Idle"), "set_process_callback", "get_process_callback");
 
 	ADD_GROUP("Limit", "limit_");
 	ADD_PROPERTYI(PropertyInfo(Variant::INT, "limit_left"), "set_limit", "get_limit", SIDE_LEFT);

+ 6 - 6
scene/2d/camera_2d.h

@@ -43,7 +43,7 @@ public:
 		ANCHOR_MODE_DRAG_CENTER
 	};
 
-	enum Camera2DProcessMode {
+	enum Camera2DProcessCallback {
 		CAMERA2D_PROCESS_PHYSICS,
 		CAMERA2D_PROCESS_IDLE
 	};
@@ -79,7 +79,7 @@ protected:
 	bool drag_vertical_offset_changed = false;
 
 	Point2 camera_screen_center;
-	void _update_process_mode();
+	void _update_process_callback();
 	void _update_scroll();
 
 	void _make_current(Object *p_which);
@@ -91,7 +91,7 @@ protected:
 	bool limit_drawing_enabled = false;
 	bool margin_drawing_enabled = false;
 
-	Camera2DProcessMode process_mode = CAMERA2D_PROCESS_IDLE;
+	Camera2DProcessCallback process_callback = CAMERA2D_PROCESS_IDLE;
 
 	Size2 _get_camera_screen_size() const;
 
@@ -137,8 +137,8 @@ public:
 	void set_follow_smoothing(float p_speed);
 	float get_follow_smoothing() const;
 
-	void set_process_mode(Camera2DProcessMode p_mode);
-	Camera2DProcessMode get_process_mode() const;
+	void set_process_callback(Camera2DProcessCallback p_mode);
+	Camera2DProcessCallback get_process_callback() const;
 
 	void make_current();
 	void clear_current();
@@ -170,6 +170,6 @@ public:
 };
 
 VARIANT_ENUM_CAST(Camera2D::AnchorMode);
-VARIANT_ENUM_CAST(Camera2D::Camera2DProcessMode);
+VARIANT_ENUM_CAST(Camera2D::Camera2DProcessCallback);
 
 #endif // CAMERA_2D_H

+ 10 - 10
scene/3d/camera_3d.cpp

@@ -673,17 +673,17 @@ float ClippedCamera3D::get_margin() const {
 	return margin;
 }
 
-void ClippedCamera3D::set_process_mode(ProcessMode p_mode) {
-	if (process_mode == p_mode) {
+void ClippedCamera3D::set_process_callback(ClipProcessCallback p_mode) {
+	if (process_callback == p_mode) {
 		return;
 	}
-	process_mode = p_mode;
-	set_process_internal(process_mode == CLIP_PROCESS_IDLE);
-	set_physics_process_internal(process_mode == CLIP_PROCESS_PHYSICS);
+	process_callback = p_mode;
+	set_process_internal(process_callback == CLIP_PROCESS_IDLE);
+	set_physics_process_internal(process_callback == CLIP_PROCESS_PHYSICS);
 }
 
-ClippedCamera3D::ProcessMode ClippedCamera3D::get_process_mode() const {
-	return process_mode;
+ClippedCamera3D::ClipProcessCallback ClippedCamera3D::get_process_callback() const {
+	return process_callback;
 }
 
 Transform ClippedCamera3D::get_camera_transform() const {
@@ -828,8 +828,8 @@ void ClippedCamera3D::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("set_margin", "margin"), &ClippedCamera3D::set_margin);
 	ClassDB::bind_method(D_METHOD("get_margin"), &ClippedCamera3D::get_margin);
 
-	ClassDB::bind_method(D_METHOD("set_process_mode", "process_mode"), &ClippedCamera3D::set_process_mode);
-	ClassDB::bind_method(D_METHOD("get_process_mode"), &ClippedCamera3D::get_process_mode);
+	ClassDB::bind_method(D_METHOD("set_process_callback", "process_callback"), &ClippedCamera3D::set_process_callback);
+	ClassDB::bind_method(D_METHOD("get_process_callback"), &ClippedCamera3D::get_process_callback);
 
 	ClassDB::bind_method(D_METHOD("set_collision_mask", "mask"), &ClippedCamera3D::set_collision_mask);
 	ClassDB::bind_method(D_METHOD("get_collision_mask"), &ClippedCamera3D::get_collision_mask);
@@ -854,7 +854,7 @@ void ClippedCamera3D::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("clear_exceptions"), &ClippedCamera3D::clear_exceptions);
 
 	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "margin", PROPERTY_HINT_RANGE, "0,32,0.01"), "set_margin", "get_margin");
-	ADD_PROPERTY(PropertyInfo(Variant::INT, "process_mode", PROPERTY_HINT_ENUM, "Physics,Idle"), "set_process_mode", "get_process_mode");
+	ADD_PROPERTY(PropertyInfo(Variant::INT, "process_callback", PROPERTY_HINT_ENUM, "Physics,Idle"), "set_process_callback", "get_process_callback");
 	ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_mask", "get_collision_mask");
 
 	ADD_GROUP("Clip To", "clip_to");

+ 5 - 5
scene/3d/camera_3d.h

@@ -186,13 +186,13 @@ class ClippedCamera3D : public Camera3D {
 	GDCLASS(ClippedCamera3D, Camera3D);
 
 public:
-	enum ProcessMode {
+	enum ClipProcessCallback {
 		CLIP_PROCESS_PHYSICS,
 		CLIP_PROCESS_IDLE,
 	};
 
 private:
-	ProcessMode process_mode = CLIP_PROCESS_PHYSICS;
+	ClipProcessCallback process_callback = CLIP_PROCESS_PHYSICS;
 	RID pyramid_shape;
 	float margin = 0.0;
 	float clip_offset = 0.0;
@@ -219,8 +219,8 @@ public:
 	void set_margin(float p_margin);
 	float get_margin() const;
 
-	void set_process_mode(ProcessMode p_mode);
-	ProcessMode get_process_mode() const;
+	void set_process_callback(ClipProcessCallback p_mode);
+	ClipProcessCallback get_process_callback() const;
 
 	void set_collision_mask(uint32_t p_mask);
 	uint32_t get_collision_mask() const;
@@ -240,5 +240,5 @@ public:
 	~ClippedCamera3D();
 };
 
-VARIANT_ENUM_CAST(ClippedCamera3D::ProcessMode);
+VARIANT_ENUM_CAST(ClippedCamera3D::ClipProcessCallback);
 #endif

+ 11 - 11
scene/animation/animation_player.cpp

@@ -206,7 +206,7 @@ void AnimationPlayer::_notification(int p_what) {
 			}
 		} break;
 		case NOTIFICATION_INTERNAL_PROCESS: {
-			if (animation_process_mode == ANIMATION_PROCESS_PHYSICS) {
+			if (process_callback == ANIMATION_PROCESS_PHYSICS) {
 				break;
 			}
 
@@ -215,7 +215,7 @@ void AnimationPlayer::_notification(int p_what) {
 			}
 		} break;
 		case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
-			if (animation_process_mode == ANIMATION_PROCESS_IDLE) {
+			if (process_callback == ANIMATION_PROCESS_IDLE) {
 				break;
 			}
 
@@ -1403,8 +1403,8 @@ bool AnimationPlayer::is_reset_on_save_enabled() const {
 	return reset_on_save;
 }
 
-void AnimationPlayer::set_animation_process_mode(AnimationProcessMode p_mode) {
-	if (animation_process_mode == p_mode) {
+void AnimationPlayer::set_process_callback(AnimationProcessCallback p_mode) {
+	if (process_callback == p_mode) {
 		return;
 	}
 
@@ -1412,14 +1412,14 @@ void AnimationPlayer::set_animation_process_mode(AnimationProcessMode p_mode) {
 	if (pr) {
 		_set_process(false);
 	}
-	animation_process_mode = p_mode;
+	process_callback = p_mode;
 	if (pr) {
 		_set_process(true);
 	}
 }
 
-AnimationPlayer::AnimationProcessMode AnimationPlayer::get_animation_process_mode() const {
-	return animation_process_mode;
+AnimationPlayer::AnimationProcessCallback AnimationPlayer::get_process_callback() const {
+	return process_callback;
 }
 
 void AnimationPlayer::set_method_call_mode(AnimationMethodCallMode p_mode) {
@@ -1435,7 +1435,7 @@ void AnimationPlayer::_set_process(bool p_process, bool p_force) {
 		return;
 	}
 
-	switch (animation_process_mode) {
+	switch (process_callback) {
 		case ANIMATION_PROCESS_PHYSICS:
 			set_physics_process_internal(p_process && active);
 			break;
@@ -1637,8 +1637,8 @@ void AnimationPlayer::_bind_methods() {
 
 	ClassDB::bind_method(D_METHOD("clear_caches"), &AnimationPlayer::clear_caches);
 
-	ClassDB::bind_method(D_METHOD("set_animation_process_mode", "mode"), &AnimationPlayer::set_animation_process_mode);
-	ClassDB::bind_method(D_METHOD("get_animation_process_mode"), &AnimationPlayer::get_animation_process_mode);
+	ClassDB::bind_method(D_METHOD("set_process_callback", "mode"), &AnimationPlayer::set_process_callback);
+	ClassDB::bind_method(D_METHOD("get_process_callback"), &AnimationPlayer::get_process_callback);
 
 	ClassDB::bind_method(D_METHOD("set_method_call_mode", "mode"), &AnimationPlayer::set_method_call_mode);
 	ClassDB::bind_method(D_METHOD("get_method_call_mode"), &AnimationPlayer::get_method_call_mode);
@@ -1658,7 +1658,7 @@ void AnimationPlayer::_bind_methods() {
 	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "current_animation_position", PROPERTY_HINT_NONE, "", 0), "", "get_current_animation_position");
 
 	ADD_GROUP("Playback Options", "playback_");
-	ADD_PROPERTY(PropertyInfo(Variant::INT, "playback_process_mode", PROPERTY_HINT_ENUM, "Physics,Idle,Manual"), "set_animation_process_mode", "get_animation_process_mode");
+	ADD_PROPERTY(PropertyInfo(Variant::INT, "playback_process_mode", PROPERTY_HINT_ENUM, "Physics,Idle,Manual"), "set_process_callback", "get_process_callback");
 	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "playback_default_blend_time", PROPERTY_HINT_RANGE, "0,4096,0.01"), "set_default_blend_time", "get_default_blend_time");
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "playback_active", PROPERTY_HINT_NONE, "", 0), "set_active", "is_active");
 	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "playback_speed", PROPERTY_HINT_RANGE, "-64,64,0.01"), "set_speed_scale", "get_speed_scale");

+ 5 - 5
scene/animation/animation_player.h

@@ -64,7 +64,7 @@ class AnimationPlayer : public Node {
 	OBJ_CATEGORY("Animation Nodes");
 
 public:
-	enum AnimationProcessMode {
+	enum AnimationProcessCallback {
 		ANIMATION_PROCESS_PHYSICS,
 		ANIMATION_PROCESS_IDLE,
 		ANIMATION_PROCESS_MANUAL,
@@ -206,7 +206,7 @@ private:
 
 	String autoplay;
 	bool reset_on_save = true;
-	AnimationProcessMode animation_process_mode = ANIMATION_PROCESS_IDLE;
+	AnimationProcessCallback process_callback = ANIMATION_PROCESS_IDLE;
 	AnimationMethodCallMode method_call_mode = ANIMATION_METHOD_CALL_DEFERRED;
 	bool processing = false;
 	bool active = true;
@@ -298,8 +298,8 @@ public:
 	void set_reset_on_save_enabled(bool p_enabled);
 	bool is_reset_on_save_enabled() const;
 
-	void set_animation_process_mode(AnimationProcessMode p_mode);
-	AnimationProcessMode get_animation_process_mode() const;
+	void set_process_callback(AnimationProcessCallback p_mode);
+	AnimationProcessCallback get_process_callback() const;
 
 	void set_method_call_mode(AnimationMethodCallMode p_mode);
 	AnimationMethodCallMode get_method_call_mode() const;
@@ -328,7 +328,7 @@ public:
 	~AnimationPlayer();
 };
 
-VARIANT_ENUM_CAST(AnimationPlayer::AnimationProcessMode);
+VARIANT_ENUM_CAST(AnimationPlayer::AnimationProcessCallback);
 VARIANT_ENUM_CAST(AnimationPlayer::AnimationMethodCallMode);
 
 #endif

+ 11 - 11
scene/animation/animation_tree.cpp

@@ -473,7 +473,7 @@ void AnimationTree::set_active(bool p_active) {
 	active = p_active;
 	started = active;
 
-	if (process_mode == ANIMATION_PROCESS_IDLE) {
+	if (process_callback == ANIMATION_PROCESS_IDLE) {
 		set_process_internal(active);
 	} else {
 		set_physics_process_internal(active);
@@ -494,8 +494,8 @@ bool AnimationTree::is_active() const {
 	return active;
 }
 
-void AnimationTree::set_process_mode(AnimationProcessMode p_mode) {
-	if (process_mode == p_mode) {
+void AnimationTree::set_process_callback(AnimationProcessCallback p_mode) {
+	if (process_callback == p_mode) {
 		return;
 	}
 
@@ -504,15 +504,15 @@ void AnimationTree::set_process_mode(AnimationProcessMode p_mode) {
 		set_active(false);
 	}
 
-	process_mode = p_mode;
+	process_callback = p_mode;
 
 	if (was_active) {
 		set_active(true);
 	}
 }
 
-AnimationTree::AnimationProcessMode AnimationTree::get_process_mode() const {
-	return process_mode;
+AnimationTree::AnimationProcessCallback AnimationTree::get_process_callback() const {
+	return process_callback;
 }
 
 void AnimationTree::_node_removed(Node *p_node) {
@@ -1234,11 +1234,11 @@ void AnimationTree::advance(float p_time) {
 }
 
 void AnimationTree::_notification(int p_what) {
-	if (active && p_what == NOTIFICATION_INTERNAL_PHYSICS_PROCESS && process_mode == ANIMATION_PROCESS_PHYSICS) {
+	if (active && p_what == NOTIFICATION_INTERNAL_PHYSICS_PROCESS && process_callback == ANIMATION_PROCESS_PHYSICS) {
 		_process_graph(get_physics_process_delta_time());
 	}
 
-	if (active && p_what == NOTIFICATION_INTERNAL_PROCESS && process_mode == ANIMATION_PROCESS_IDLE) {
+	if (active && p_what == NOTIFICATION_INTERNAL_PROCESS && process_callback == ANIMATION_PROCESS_IDLE) {
 		_process_graph(get_process_delta_time());
 	}
 
@@ -1471,8 +1471,8 @@ void AnimationTree::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("set_tree_root", "root"), &AnimationTree::set_tree_root);
 	ClassDB::bind_method(D_METHOD("get_tree_root"), &AnimationTree::get_tree_root);
 
-	ClassDB::bind_method(D_METHOD("set_process_mode", "mode"), &AnimationTree::set_process_mode);
-	ClassDB::bind_method(D_METHOD("get_process_mode"), &AnimationTree::get_process_mode);
+	ClassDB::bind_method(D_METHOD("set_process_callback", "mode"), &AnimationTree::set_process_callback);
+	ClassDB::bind_method(D_METHOD("get_process_callback"), &AnimationTree::get_process_callback);
 
 	ClassDB::bind_method(D_METHOD("set_animation_player", "root"), &AnimationTree::set_animation_player);
 	ClassDB::bind_method(D_METHOD("get_animation_player"), &AnimationTree::get_animation_player);
@@ -1491,7 +1491,7 @@ void AnimationTree::_bind_methods() {
 	ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "tree_root", PROPERTY_HINT_RESOURCE_TYPE, "AnimationRootNode"), "set_tree_root", "get_tree_root");
 	ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "anim_player", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "AnimationPlayer"), "set_animation_player", "get_animation_player");
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "active"), "set_active", "is_active");
-	ADD_PROPERTY(PropertyInfo(Variant::INT, "process_mode", PROPERTY_HINT_ENUM, "Physics,Idle,Manual"), "set_process_mode", "get_process_mode");
+	ADD_PROPERTY(PropertyInfo(Variant::INT, "process_callback", PROPERTY_HINT_ENUM, "Physics,Idle,Manual"), "set_process_callback", "get_process_callback");
 	ADD_GROUP("Root Motion", "root_motion_");
 	ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "root_motion_track"), "set_root_motion_track", "get_root_motion_track");
 

+ 5 - 5
scene/animation/animation_tree.h

@@ -163,7 +163,7 @@ class AnimationTree : public Node {
 	GDCLASS(AnimationTree, Node);
 
 public:
-	enum AnimationProcessMode {
+	enum AnimationProcessCallback {
 		ANIMATION_PROCESS_PHYSICS,
 		ANIMATION_PROCESS_IDLE,
 		ANIMATION_PROCESS_MANUAL,
@@ -238,7 +238,7 @@ private:
 
 	Ref<AnimationNode> root;
 
-	AnimationProcessMode process_mode = ANIMATION_PROCESS_IDLE;
+	AnimationProcessCallback process_callback = ANIMATION_PROCESS_IDLE;
 	bool active = false;
 	NodePath animation_player;
 
@@ -294,8 +294,8 @@ public:
 	void set_active(bool p_active);
 	bool is_active() const;
 
-	void set_process_mode(AnimationProcessMode p_mode);
-	AnimationProcessMode get_process_mode() const;
+	void set_process_callback(AnimationProcessCallback p_mode);
+	AnimationProcessCallback get_process_callback() const;
 
 	void set_animation_player(const NodePath &p_player);
 	NodePath get_animation_player() const;
@@ -320,6 +320,6 @@ public:
 	~AnimationTree();
 };
 
-VARIANT_ENUM_CAST(AnimationTree::AnimationProcessMode)
+VARIANT_ENUM_CAST(AnimationTree::AnimationProcessCallback)
 
 #endif // ANIMATION_GRAPH_PLAYER_H

+ 2 - 2
scene/animation/root_motion_view.cpp

@@ -89,12 +89,12 @@ void RootMotionView::_notification(int p_what) {
 
 			AnimationTree *tree = Object::cast_to<AnimationTree>(node);
 			if (tree && tree->is_active() && tree->get_root_motion_track() != NodePath()) {
-				if (is_processing_internal() && tree->get_process_mode() == AnimationTree::ANIMATION_PROCESS_PHYSICS) {
+				if (is_processing_internal() && tree->get_process_callback() == AnimationTree::ANIMATION_PROCESS_PHYSICS) {
 					set_process_internal(false);
 					set_physics_process_internal(true);
 				}
 
-				if (is_physics_processing_internal() && tree->get_process_mode() == AnimationTree::ANIMATION_PROCESS_IDLE) {
+				if (is_physics_processing_internal() && tree->get_process_callback() == AnimationTree::ANIMATION_PROCESS_IDLE) {
 					set_process_internal(true);
 					set_physics_process_internal(false);
 				}

+ 103 - 61
scene/main/node.cpp

@@ -46,7 +46,7 @@
 
 #include <stdint.h>
 
-VARIANT_ENUM_CAST(Node::PauseMode);
+VARIANT_ENUM_CAST(Node::ProcessMode);
 
 int Node::orphan_node_count = 0;
 
@@ -69,14 +69,14 @@ void Node::_notification(int p_notification) {
 			ERR_FAIL_COND(!get_viewport());
 			ERR_FAIL_COND(!get_tree());
 
-			if (data.pause_mode == PAUSE_MODE_INHERIT) {
+			if (data.process_mode == PROCESS_MODE_INHERIT) {
 				if (data.parent) {
-					data.pause_owner = data.parent->data.pause_owner;
+					data.process_owner = data.parent->data.process_owner;
 				} else {
-					data.pause_owner = nullptr;
+					data.process_owner = nullptr;
 				}
 			} else {
-				data.pause_owner = this;
+				data.process_owner = this;
 			}
 
 			if (data.input) {
@@ -110,7 +110,7 @@ void Node::_notification(int p_notification) {
 				remove_from_group("_vp_unhandled_key_input" + itos(get_viewport()->get_instance_id()));
 			}
 
-			data.pause_owner = nullptr;
+			data.process_owner = nullptr;
 			if (data.path_cache) {
 				memdelete(data.path_cache);
 				data.path_cache = nullptr;
@@ -391,44 +391,81 @@ bool Node::is_physics_processing_internal() const {
 	return data.physics_process_internal;
 }
 
-void Node::set_pause_mode(PauseMode p_mode) {
-	if (data.pause_mode == p_mode) {
+void Node::set_process_mode(ProcessMode p_mode) {
+	if (data.process_mode == p_mode) {
 		return;
 	}
 
-	bool prev_inherits = data.pause_mode == PAUSE_MODE_INHERIT;
-	data.pause_mode = p_mode;
 	if (!is_inside_tree()) {
-		return; //pointless
-	}
-	if ((data.pause_mode == PAUSE_MODE_INHERIT) == prev_inherits) {
-		return; ///nothing changed
+		data.process_mode = p_mode;
+		return;
 	}
 
-	Node *owner = nullptr;
+	bool prev_can_process = can_process();
+
+	data.process_mode = p_mode;
 
-	if (data.pause_mode == PAUSE_MODE_INHERIT) {
+	if (data.process_mode == PROCESS_MODE_INHERIT) {
 		if (data.parent) {
-			owner = data.parent->data.pause_owner;
+			data.process_owner = data.parent->data.owner;
+		} else {
+			data.process_owner = nullptr;
 		}
 	} else {
-		owner = this;
+		data.process_owner = this;
+	}
+
+	bool next_can_process = can_process();
+
+	int pause_notification = 0;
+
+	if (prev_can_process && !next_can_process) {
+		pause_notification = NOTIFICATION_PAUSED;
+	} else if (!prev_can_process && next_can_process) {
+		pause_notification = NOTIFICATION_UNPAUSED;
+	}
+
+	_propagate_process_owner(data.process_owner, pause_notification);
+#ifdef TOOLS_ENABLED
+	// This is required for the editor to update the visibility of disabled nodes
+	// Its very expensive during runtime to change, so editor-only
+	if (Engine::get_singleton()->is_editor_hint()) {
+		get_tree()->emit_signal("tree_process_mode_changed");
 	}
+#endif
+}
+
+void Node::_propagate_pause_notification(bool p_enable) {
+	bool prev_can_process = _can_process(!p_enable);
+	bool next_can_process = _can_process(p_enable);
 
-	_propagate_pause_owner(owner);
+	if (prev_can_process && !next_can_process) {
+		notification(NOTIFICATION_PAUSED);
+	} else if (!prev_can_process && next_can_process) {
+		notification(NOTIFICATION_UNPAUSED);
+	}
+
+	for (int i = 0; i < data.children.size(); i++) {
+		data.children[i]->_propagate_pause_notification(p_enable);
+	}
 }
 
-Node::PauseMode Node::get_pause_mode() const {
-	return data.pause_mode;
+Node::ProcessMode Node::get_process_mode() const {
+	return data.process_mode;
 }
 
-void Node::_propagate_pause_owner(Node *p_owner) {
-	if (this != p_owner && data.pause_mode != PAUSE_MODE_INHERIT) {
-		return;
+void Node::_propagate_process_owner(Node *p_owner, int p_notification) {
+	data.process_owner = p_owner;
+
+	if (p_notification != 0) {
+		notification(p_notification);
 	}
-	data.pause_owner = p_owner;
+
 	for (int i = 0; i < data.children.size(); i++) {
-		data.children[i]->_propagate_pause_owner(p_owner);
+		Node *c = data.children[i];
+		if (c->data.process_mode == PROCESS_MODE_INHERIT) {
+			c->_propagate_process_owner(p_owner, p_notification);
+		}
 	}
 }
 
@@ -805,30 +842,33 @@ bool Node::can_process_notification(int p_what) const {
 
 bool Node::can_process() const {
 	ERR_FAIL_COND_V(!is_inside_tree(), false);
+	return _can_process(get_tree()->is_paused());
+}
 
-	if (get_tree()->is_paused()) {
-		if (data.pause_mode == PAUSE_MODE_STOP) {
-			return false;
-		}
-		if (data.pause_mode == PAUSE_MODE_PROCESS) {
-			return true;
-		}
-		if (data.pause_mode == PAUSE_MODE_INHERIT) {
-			if (!data.pause_owner) {
-				return false; //clearly no pause owner by default
-			}
+bool Node::_can_process(bool p_paused) const {
+	ProcessMode process_mode;
 
-			if (data.pause_owner->data.pause_mode == PAUSE_MODE_PROCESS) {
-				return true;
-			}
-
-			if (data.pause_owner->data.pause_mode == PAUSE_MODE_STOP) {
-				return false;
-			}
+	if (data.process_mode == PROCESS_MODE_INHERIT) {
+		if (!data.process_owner) {
+			process_mode = PROCESS_MODE_PAUSABLE;
+		} else {
+			process_mode = data.process_owner->data.process_mode;
 		}
+	} else {
+		process_mode = data.process_mode;
 	}
 
-	return true;
+	if (process_mode == PROCESS_MODE_DISABLED) {
+		return false;
+	} else if (process_mode == PROCESS_MODE_ALWAYS) {
+		return true;
+	}
+
+	if (p_paused) {
+		return process_mode == PROCESS_MODE_WHEN_PAUSED;
+	} else {
+		return process_mode == PROCESS_MODE_PAUSABLE;
+	}
 }
 
 float Node::get_physics_process_delta_time() const {
@@ -1898,15 +1938,11 @@ String Node::get_filename() const {
 }
 
 void Node::set_editor_description(const String &p_editor_description) {
-	set_meta("_editor_description_", p_editor_description);
+	data.editor_description = p_editor_description;
 }
 
 String Node::get_editor_description() const {
-	if (has_meta("_editor_description_")) {
-		return get_meta("_editor_description_");
-	} else {
-		return "";
-	}
+	return data.editor_description;
 }
 
 void Node::set_editable_instance(Node *p_node, bool p_editable) {
@@ -2783,8 +2819,8 @@ void Node::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("is_processing_unhandled_input"), &Node::is_processing_unhandled_input);
 	ClassDB::bind_method(D_METHOD("set_process_unhandled_key_input", "enable"), &Node::set_process_unhandled_key_input);
 	ClassDB::bind_method(D_METHOD("is_processing_unhandled_key_input"), &Node::is_processing_unhandled_key_input);
-	ClassDB::bind_method(D_METHOD("set_pause_mode", "mode"), &Node::set_pause_mode);
-	ClassDB::bind_method(D_METHOD("get_pause_mode"), &Node::get_pause_mode);
+	ClassDB::bind_method(D_METHOD("set_process_mode", "mode"), &Node::set_process_mode);
+	ClassDB::bind_method(D_METHOD("get_process_mode"), &Node::get_process_mode);
 	ClassDB::bind_method(D_METHOD("can_process"), &Node::can_process);
 	ClassDB::bind_method(D_METHOD("print_stray_nodes"), &Node::_print_stray_nodes);
 
@@ -2822,12 +2858,12 @@ void Node::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("rpc_config", "method", "mode"), &Node::rpc_config);
 	ClassDB::bind_method(D_METHOD("rset_config", "property", "mode"), &Node::rset_config);
 
-	ClassDB::bind_method(D_METHOD("_set_editor_description", "editor_description"), &Node::set_editor_description);
-	ClassDB::bind_method(D_METHOD("_get_editor_description"), &Node::get_editor_description);
-	ADD_PROPERTY(PropertyInfo(Variant::STRING, "editor_description", PROPERTY_HINT_MULTILINE_TEXT, "", PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_editor_description", "_get_editor_description");
+	ClassDB::bind_method(D_METHOD("set_editor_description", "editor_description"), &Node::set_editor_description);
+	ClassDB::bind_method(D_METHOD("get_editor_description"), &Node::get_editor_description);
 
 	ClassDB::bind_method(D_METHOD("_set_import_path", "import_path"), &Node::set_import_path);
 	ClassDB::bind_method(D_METHOD("_get_import_path"), &Node::get_import_path);
+
 	ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "_import_path", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_import_path", "_get_import_path");
 
 	{
@@ -2891,9 +2927,11 @@ void Node::_bind_methods() {
 	BIND_CONSTANT(NOTIFICATION_APPLICATION_FOCUS_OUT);
 	BIND_CONSTANT(NOTIFICATION_TEXT_SERVER_CHANGED);
 
-	BIND_ENUM_CONSTANT(PAUSE_MODE_INHERIT);
-	BIND_ENUM_CONSTANT(PAUSE_MODE_STOP);
-	BIND_ENUM_CONSTANT(PAUSE_MODE_PROCESS);
+	BIND_ENUM_CONSTANT(PROCESS_MODE_INHERIT);
+	BIND_ENUM_CONSTANT(PROCESS_MODE_PAUSABLE);
+	BIND_ENUM_CONSTANT(PROCESS_MODE_WHEN_PAUSED);
+	BIND_ENUM_CONSTANT(PROCESS_MODE_ALWAYS);
+	BIND_ENUM_CONSTANT(PROCESS_MODE_DISABLED);
 
 	BIND_ENUM_CONSTANT(DUPLICATE_SIGNALS);
 	BIND_ENUM_CONSTANT(DUPLICATE_GROUPS);
@@ -2906,15 +2944,19 @@ void Node::_bind_methods() {
 	ADD_SIGNAL(MethodInfo("tree_exiting"));
 	ADD_SIGNAL(MethodInfo("tree_exited"));
 
-	ADD_PROPERTY(PropertyInfo(Variant::INT, "pause_mode", PROPERTY_HINT_ENUM, "Inherit,Stop,Process"), "set_pause_mode", "get_pause_mode");
-
 	ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "name", PROPERTY_HINT_NONE, "", 0), "set_name", "get_name");
 	ADD_PROPERTY(PropertyInfo(Variant::STRING, "filename", PROPERTY_HINT_NONE, "", 0), "set_filename", "get_filename");
 	ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "owner", PROPERTY_HINT_RESOURCE_TYPE, "Node", 0), "set_owner", "get_owner");
 	ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "multiplayer", PROPERTY_HINT_RESOURCE_TYPE, "MultiplayerAPI", 0), "", "get_multiplayer");
 	ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "custom_multiplayer", PROPERTY_HINT_RESOURCE_TYPE, "MultiplayerAPI", 0), "set_custom_multiplayer", "get_custom_multiplayer");
+
+	ADD_GROUP("Process", "process_");
+	ADD_PROPERTY(PropertyInfo(Variant::INT, "process_mode", PROPERTY_HINT_ENUM, "Inherit,Pausable,WhenPaused,Always,Disabled"), "set_process_mode", "get_process_mode");
 	ADD_PROPERTY(PropertyInfo(Variant::INT, "process_priority"), "set_process_priority", "get_process_priority");
 
+	ADD_GROUP("Editor Description", "editor_");
+	ADD_PROPERTY(PropertyInfo(Variant::STRING, "editor_description", PROPERTY_HINT_MULTILINE_TEXT, "", PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_INTERNAL), "set_editor_description", "get_editor_description");
+
 	BIND_VMETHOD(MethodInfo("_process", PropertyInfo(Variant::FLOAT, "delta")));
 	BIND_VMETHOD(MethodInfo("_physics_process", PropertyInfo(Variant::FLOAT, "delta")));
 	BIND_VMETHOD(MethodInfo("_enter_tree"));

+ 15 - 9
scene/main/node.h

@@ -46,10 +46,12 @@ class Node : public Object {
 	OBJ_CATEGORY("Nodes");
 
 public:
-	enum PauseMode {
-		PAUSE_MODE_INHERIT,
-		PAUSE_MODE_STOP,
-		PAUSE_MODE_PROCESS
+	enum ProcessMode {
+		PROCESS_MODE_INHERIT, // same as parent node
+		PROCESS_MODE_PAUSABLE, // process only if not paused
+		PROCESS_MODE_WHEN_PAUSED, // process only if paused
+		PROCESS_MODE_ALWAYS, // process always
+		PROCESS_MODE_DISABLED, // never process
 	};
 
 	enum DuplicateFlags {
@@ -102,6 +104,7 @@ private:
 #ifdef TOOLS_ENABLED
 		NodePath import_path; // Path used when imported, used by scene editors to keep tracking.
 #endif
+		String editor_description;
 
 		Viewport *viewport = nullptr;
 
@@ -109,8 +112,8 @@ private:
 		List<Node *>::Element *OW = nullptr; // Owned element.
 		List<Node *> owned;
 
-		PauseMode pause_mode = PAUSE_MODE_INHERIT;
-		Node *pause_owner = nullptr;
+		ProcessMode process_mode = PROCESS_MODE_INHERIT;
+		Node *process_owner = nullptr;
 
 		int network_master = 1; // Server by default.
 		Vector<NetData> rpc_methods;
@@ -166,7 +169,7 @@ private:
 	void _propagate_after_exit_tree();
 	void _propagate_validate_owner();
 	void _print_stray_nodes();
-	void _propagate_pause_owner(Node *p_owner);
+	void _propagate_process_owner(Node *p_owner, int p_notification);
 	Array _get_node_and_resource(const NodePath &p_path);
 
 	void _duplicate_signals(const Node *p_original, Node *p_copy) const;
@@ -184,6 +187,9 @@ private:
 	friend class SceneTree;
 
 	void _set_tree(SceneTree *p_tree);
+	void _propagate_pause_notification(bool p_enable);
+
+	_FORCE_INLINE_ bool _can_process(bool p_paused) const;
 
 #ifdef TOOLS_ENABLED
 	friend class SceneTreeEditor;
@@ -381,8 +387,8 @@ public:
 
 	void replace_by(Node *p_node, bool p_keep_data = false);
 
-	void set_pause_mode(PauseMode p_mode);
-	PauseMode get_pause_mode() const;
+	void set_process_mode(ProcessMode p_mode);
+	ProcessMode get_process_mode() const;
 	bool can_process() const;
 	bool can_process_notification(int p_what) const;
 

+ 2 - 1
scene/main/scene_tree.cpp

@@ -767,7 +767,7 @@ void SceneTree::set_pause(bool p_enabled) {
 	PhysicsServer3D::get_singleton()->set_active(!p_enabled);
 	PhysicsServer2D::get_singleton()->set_active(!p_enabled);
 	if (get_root()) {
-		get_root()->propagate_notification(p_enabled ? Node::NOTIFICATION_PAUSED : Node::NOTIFICATION_UNPAUSED);
+		get_root()->_propagate_pause_notification(p_enabled);
 	}
 }
 
@@ -1254,6 +1254,7 @@ void SceneTree::_bind_methods() {
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "multiplayer_poll"), "set_multiplayer_poll_enabled", "is_multiplayer_poll_enabled");
 
 	ADD_SIGNAL(MethodInfo("tree_changed"));
+	ADD_SIGNAL(MethodInfo("tree_process_mode_changed")); //editor only signal, but due to API hash it cant be removed in run-time
 	ADD_SIGNAL(MethodInfo("node_added", PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Node")));
 	ADD_SIGNAL(MethodInfo("node_removed", PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Node")));
 	ADD_SIGNAL(MethodInfo("node_renamed", PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Node")));