mirror of
				https://github.com/godotengine/godot.git
				synced 2025-10-31 13:41:03 +00:00 
			
		
		
		
	Merge pull request #107038 from bruvzg/emb_scr
Add support for taking embedded window screenshots.
This commit is contained in:
		
						commit
						042ad3a62f
					
				
					 10 changed files with 185 additions and 14 deletions
				
			
		|  | @ -96,6 +96,7 @@ | ||||||
| #include "editor/editor_property_name_processor.h" | #include "editor/editor_property_name_processor.h" | ||||||
| #include "editor/editor_resource_picker.h" | #include "editor/editor_resource_picker.h" | ||||||
| #include "editor/editor_resource_preview.h" | #include "editor/editor_resource_preview.h" | ||||||
|  | #include "editor/editor_run.h" | ||||||
| #include "editor/editor_script.h" | #include "editor/editor_script.h" | ||||||
| #include "editor/editor_settings.h" | #include "editor/editor_settings.h" | ||||||
| #include "editor/editor_settings_dialog.h" | #include "editor/editor_settings_dialog.h" | ||||||
|  | @ -3419,14 +3420,39 @@ void EditorNode::_request_screenshot() { | ||||||
| 
 | 
 | ||||||
| void EditorNode::_screenshot(bool p_use_utc) { | void EditorNode::_screenshot(bool p_use_utc) { | ||||||
| 	String name = "editor_screenshot_" + Time::get_singleton()->get_datetime_string_from_system(p_use_utc).remove_char(':') + ".png"; | 	String name = "editor_screenshot_" + Time::get_singleton()->get_datetime_string_from_system(p_use_utc).remove_char(':') + ".png"; | ||||||
| 	NodePath path = String("user://") + name; | 	String path = String("user://") + name; | ||||||
| 	_save_screenshot(path); | 
 | ||||||
| 	if (EDITOR_GET("interface/editor/automatically_open_screenshots")) { | 	if (!EditorRun::request_screenshot(callable_mp(this, &EditorNode::_save_screenshot_with_embedded_process).bind(path))) { | ||||||
| 		OS::get_singleton()->shell_show_in_file_manager(ProjectSettings::get_singleton()->globalize_path(path), true); | 		_save_screenshot(path); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EditorNode::_save_screenshot(NodePath p_path) { | void EditorNode::_save_screenshot_with_embedded_process(int64_t p_w, int64_t p_h, const String &p_emb_path, const Rect2i &p_rect, const String &p_path) { | ||||||
|  | 	Control *main_screen_control = editor_main_screen->get_control(); | ||||||
|  | 	ERR_FAIL_NULL_MSG(main_screen_control, "Cannot get the editor main screen control."); | ||||||
|  | 	Viewport *viewport = main_screen_control->get_viewport(); | ||||||
|  | 	ERR_FAIL_NULL_MSG(viewport, "Cannot get a viewport from the editor main screen."); | ||||||
|  | 	Ref<ViewportTexture> texture = viewport->get_texture(); | ||||||
|  | 	ERR_FAIL_COND_MSG(texture.is_null(), "Cannot get a viewport texture from the editor main screen."); | ||||||
|  | 	Ref<Image> img = texture->get_image(); | ||||||
|  | 	ERR_FAIL_COND_MSG(img.is_null(), "Cannot get an image from a viewport texture of the editor main screen."); | ||||||
|  | 	img->convert(Image::FORMAT_RGBA8); | ||||||
|  | 	ERR_FAIL_COND(p_emb_path.is_empty()); | ||||||
|  | 	Ref<Image> overlay = Image::load_from_file(p_emb_path); | ||||||
|  | 	DirAccess::remove_absolute(p_emb_path); | ||||||
|  | 	ERR_FAIL_COND_MSG(overlay.is_null(), "Cannot get an image from a embedded process."); | ||||||
|  | 	overlay->convert(Image::FORMAT_RGBA8); | ||||||
|  | 	overlay->resize(p_rect.size.x, p_rect.size.y); | ||||||
|  | 	img->blend_rect(overlay, Rect2i(0, 0, p_w, p_h), p_rect.position); | ||||||
|  | 	Error error = img->save_png(p_path); | ||||||
|  | 	ERR_FAIL_COND_MSG(error != OK, "Cannot save screenshot to file '" + p_path + "'."); | ||||||
|  | 
 | ||||||
|  | 	if (EDITOR_GET("interface/editor/automatically_open_screenshots")) { | ||||||
|  | 		OS::get_singleton()->shell_show_in_file_manager(ProjectSettings::get_singleton()->globalize_path(p_path), true); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void EditorNode::_save_screenshot(const String &p_path) { | ||||||
| 	Control *main_screen_control = editor_main_screen->get_control(); | 	Control *main_screen_control = editor_main_screen->get_control(); | ||||||
| 	ERR_FAIL_NULL_MSG(main_screen_control, "Cannot get the editor main screen control."); | 	ERR_FAIL_NULL_MSG(main_screen_control, "Cannot get the editor main screen control."); | ||||||
| 	Viewport *viewport = main_screen_control->get_viewport(); | 	Viewport *viewport = main_screen_control->get_viewport(); | ||||||
|  | @ -3437,6 +3463,10 @@ void EditorNode::_save_screenshot(NodePath p_path) { | ||||||
| 	ERR_FAIL_COND_MSG(img.is_null(), "Cannot get an image from a viewport texture of the editor main screen."); | 	ERR_FAIL_COND_MSG(img.is_null(), "Cannot get an image from a viewport texture of the editor main screen."); | ||||||
| 	Error error = img->save_png(p_path); | 	Error error = img->save_png(p_path); | ||||||
| 	ERR_FAIL_COND_MSG(error != OK, "Cannot save screenshot to file '" + p_path + "'."); | 	ERR_FAIL_COND_MSG(error != OK, "Cannot save screenshot to file '" + p_path + "'."); | ||||||
|  | 
 | ||||||
|  | 	if (EDITOR_GET("interface/editor/automatically_open_screenshots")) { | ||||||
|  | 		OS::get_singleton()->shell_show_in_file_manager(ProjectSettings::get_singleton()->globalize_path(p_path), true); | ||||||
|  | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EditorNode::_check_system_theme_changed() { | void EditorNode::_check_system_theme_changed() { | ||||||
|  |  | ||||||
|  | @ -548,7 +548,8 @@ private: | ||||||
| 
 | 
 | ||||||
| 	void _request_screenshot(); | 	void _request_screenshot(); | ||||||
| 	void _screenshot(bool p_use_utc = false); | 	void _screenshot(bool p_use_utc = false); | ||||||
| 	void _save_screenshot(NodePath p_path); | 	void _save_screenshot(const String &p_path); | ||||||
|  | 	void _save_screenshot_with_embedded_process(int64_t p_w, int64_t p_h, const String &p_emb_path, const Rect2i &p_rect, const String &p_path); | ||||||
| 
 | 
 | ||||||
| 	void _check_system_theme_changed(); | 	void _check_system_theme_changed(); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -189,6 +189,14 @@ Error EditorRun::run(const String &p_scene, const String &p_write_movie, const V | ||||||
| 	return OK; | 	return OK; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | bool EditorRun::request_screenshot(const Callable &p_callback) { | ||||||
|  | 	if (instance_rq_screenshot_callback) { | ||||||
|  | 		return instance_rq_screenshot_callback(p_callback); | ||||||
|  | 	} else { | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
| bool EditorRun::has_child_process(OS::ProcessID p_pid) const { | bool EditorRun::has_child_process(OS::ProcessID p_pid) const { | ||||||
| 	for (const OS::ProcessID &E : pids) { | 	for (const OS::ProcessID &E : pids) { | ||||||
| 		if (E == p_pid) { | 		if (E == p_pid) { | ||||||
|  |  | ||||||
|  | @ -33,6 +33,7 @@ | ||||||
| #include "core/os/os.h" | #include "core/os/os.h" | ||||||
| 
 | 
 | ||||||
| typedef void (*EditorRunInstanceStarting)(int p_index, List<String> &r_arguments); | typedef void (*EditorRunInstanceStarting)(int p_index, List<String> &r_arguments); | ||||||
|  | typedef bool (*EditorRunInstanceRequestScreenshot)(const Callable &p_callback); | ||||||
| 
 | 
 | ||||||
| class EditorRun { | class EditorRun { | ||||||
| public: | public: | ||||||
|  | @ -58,6 +59,7 @@ private: | ||||||
| 
 | 
 | ||||||
| public: | public: | ||||||
| 	inline static EditorRunInstanceStarting instance_starting_callback = nullptr; | 	inline static EditorRunInstanceStarting instance_starting_callback = nullptr; | ||||||
|  | 	inline static EditorRunInstanceRequestScreenshot instance_rq_screenshot_callback = nullptr; | ||||||
| 
 | 
 | ||||||
| 	Status get_status() const; | 	Status get_status() const; | ||||||
| 	String get_running_scene() const; | 	String get_running_scene() const; | ||||||
|  | @ -71,6 +73,8 @@ public: | ||||||
| 	int get_child_process_count() const { return pids.size(); } | 	int get_child_process_count() const { return pids.size(); } | ||||||
| 	OS::ProcessID get_current_process() const; | 	OS::ProcessID get_current_process() const; | ||||||
| 
 | 
 | ||||||
|  | 	static bool request_screenshot(const Callable &p_callback); | ||||||
|  | 
 | ||||||
| 	static WindowPlacement get_window_placement(); | 	static WindowPlacement get_window_placement(); | ||||||
| 
 | 
 | ||||||
| 	EditorRun(); | 	EditorRun(); | ||||||
|  |  | ||||||
|  | @ -32,6 +32,7 @@ | ||||||
| 
 | 
 | ||||||
| #include "core/config/project_settings.h" | #include "core/config/project_settings.h" | ||||||
| #include "core/debugger/debugger_marshalls.h" | #include "core/debugger/debugger_marshalls.h" | ||||||
|  | #include "core/debugger/engine_debugger.h" | ||||||
| #include "core/string/translation_server.h" | #include "core/string/translation_server.h" | ||||||
| #include "editor/debugger/editor_debugger_node.h" | #include "editor/debugger/editor_debugger_node.h" | ||||||
| #include "editor/debugger/script_editor_debugger.h" | #include "editor/debugger/script_editor_debugger.h" | ||||||
|  | @ -225,6 +226,61 @@ void GameViewDebugger::_bind_methods() { | ||||||
| 	ADD_SIGNAL(MethodInfo("session_stopped")); | 	ADD_SIGNAL(MethodInfo("session_stopped")); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | bool GameViewDebugger::add_screenshot_callback(const Callable &p_callaback, const Rect2i &p_rect) { | ||||||
|  | 	bool found = false; | ||||||
|  | 	for (Ref<EditorDebuggerSession> &I : sessions) { | ||||||
|  | 		if (I->is_active()) { | ||||||
|  | 			ScreenshotCB sd; | ||||||
|  | 			sd.cb = p_callaback; | ||||||
|  | 			sd.rect = p_rect; | ||||||
|  | 			screenshot_callbacks[scr_rq_id] = sd; | ||||||
|  | 
 | ||||||
|  | 			Array arr; | ||||||
|  | 			arr.append(scr_rq_id); | ||||||
|  | 			I->send_message("scene:rq_screenshot", arr); | ||||||
|  | 			scr_rq_id++; | ||||||
|  | 			found = true; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return found; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool GameViewDebugger::_msg_get_screenshot(const Array &p_args) { | ||||||
|  | 	ERR_FAIL_COND_V_MSG(p_args.size() != 4, false, "get_screenshot: invalid number of arguments"); | ||||||
|  | 
 | ||||||
|  | 	int64_t id = p_args[0]; | ||||||
|  | 	int64_t w = p_args[1]; | ||||||
|  | 	int64_t h = p_args[2]; | ||||||
|  | 	const String &path = p_args[3]; | ||||||
|  | 
 | ||||||
|  | 	if (screenshot_callbacks.has(id)) { | ||||||
|  | 		if (screenshot_callbacks[id].cb.is_valid()) { | ||||||
|  | 			screenshot_callbacks[id].cb.call(w, h, path, screenshot_callbacks[id].rect); | ||||||
|  | 		} | ||||||
|  | 		screenshot_callbacks.erase(id); | ||||||
|  | 	} | ||||||
|  | 	return true; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool GameViewDebugger::capture(const String &p_message, const Array &p_data, int p_session) { | ||||||
|  | 	Ref<EditorDebuggerSession> session = get_session(p_session); | ||||||
|  | 	ERR_FAIL_COND_V(session.is_null(), true); | ||||||
|  | 
 | ||||||
|  | 	if (p_message == "game_view:get_screenshot") { | ||||||
|  | 		return _msg_get_screenshot(p_data); | ||||||
|  | 	} else { | ||||||
|  | 		// Any other messages with this prefix should be ignored.
 | ||||||
|  | 		WARN_PRINT("GameViewDebugger unknown message: " + p_message); | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return true; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool GameViewDebugger::has_capture(const String &p_capture) const { | ||||||
|  | 	return p_capture == "game_view"; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| GameViewDebugger::GameViewDebugger() { | GameViewDebugger::GameViewDebugger() { | ||||||
| 	EditorFeatureProfileManager::get_singleton()->connect("current_feature_profile_changed", callable_mp(this, &GameViewDebugger::_feature_profile_changed)); | 	EditorFeatureProfileManager::get_singleton()->connect("current_feature_profile_changed", callable_mp(this, &GameViewDebugger::_feature_profile_changed)); | ||||||
| 
 | 
 | ||||||
|  | @ -287,6 +343,23 @@ void GameView::_instance_starting(int p_idx, List<String> &r_arguments) { | ||||||
| 	_update_arguments_for_instance(p_idx, r_arguments); | 	_update_arguments_for_instance(p_idx, r_arguments); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | bool GameView::_instance_rq_screenshot_static(const Callable &p_callback) { | ||||||
|  | 	ERR_FAIL_NULL_V(singleton, false); | ||||||
|  | 	return singleton->_instance_rq_screenshot(p_callback); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool GameView::_instance_rq_screenshot(const Callable &p_callback) { | ||||||
|  | 	if (debugger.is_null() || window_wrapper->get_window_enabled() || !embedded_process || !embedded_process->is_embedding_completed()) { | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  | 	Rect2 r = embedded_process->get_adjusted_embedded_window_rect(embedded_process->get_rect()); | ||||||
|  | 	r.position += embedded_process->get_global_position(); | ||||||
|  | #ifndef MACOS_ENABLED | ||||||
|  | 	r.position -= embedded_process->get_window()->get_position(); | ||||||
|  | #endif | ||||||
|  | 	return debugger->add_screenshot_callback(p_callback, r); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void GameView::_show_update_window_wrapper() { | void GameView::_show_update_window_wrapper() { | ||||||
| 	EditorRun::WindowPlacement placement = EditorRun::get_window_placement(); | 	EditorRun::WindowPlacement placement = EditorRun::get_window_placement(); | ||||||
| 	Point2 position = floating_window_rect.position; | 	Point2 position = floating_window_rect.position; | ||||||
|  | @ -756,6 +829,7 @@ void GameView::_notification(int p_what) { | ||||||
| 				EditorRunBar::get_singleton()->connect("play_pressed", callable_mp(this, &GameView::_play_pressed)); | 				EditorRunBar::get_singleton()->connect("play_pressed", callable_mp(this, &GameView::_play_pressed)); | ||||||
| 				EditorRunBar::get_singleton()->connect("stop_pressed", callable_mp(this, &GameView::_stop_pressed)); | 				EditorRunBar::get_singleton()->connect("stop_pressed", callable_mp(this, &GameView::_stop_pressed)); | ||||||
| 				EditorRun::instance_starting_callback = _instance_starting_static; | 				EditorRun::instance_starting_callback = _instance_starting_static; | ||||||
|  | 				EditorRun::instance_rq_screenshot_callback = _instance_rq_screenshot_static; | ||||||
| 
 | 
 | ||||||
| 				// Listen for project settings changes to update the window size and aspect ratio.
 | 				// Listen for project settings changes to update the window size and aspect ratio.
 | ||||||
| 				ProjectSettings::get_singleton()->connect("settings_changed", callable_mp(this, &GameView::_editor_or_project_settings_changed)); | 				ProjectSettings::get_singleton()->connect("settings_changed", callable_mp(this, &GameView::_editor_or_project_settings_changed)); | ||||||
|  |  | ||||||
|  | @ -60,10 +60,25 @@ private: | ||||||
| 
 | 
 | ||||||
| 	void _feature_profile_changed(); | 	void _feature_profile_changed(); | ||||||
| 
 | 
 | ||||||
|  | 	struct ScreenshotCB { | ||||||
|  | 		Callable cb; | ||||||
|  | 		Rect2i rect; | ||||||
|  | 	}; | ||||||
|  | 
 | ||||||
|  | 	int64_t scr_rq_id = 0; | ||||||
|  | 	HashMap<uint64_t, ScreenshotCB> screenshot_callbacks; | ||||||
|  | 
 | ||||||
|  | 	bool _msg_get_screenshot(const Array &p_args); | ||||||
|  | 
 | ||||||
| protected: | protected: | ||||||
| 	static void _bind_methods(); | 	static void _bind_methods(); | ||||||
| 
 | 
 | ||||||
| public: | public: | ||||||
|  | 	virtual bool capture(const String &p_message, const Array &p_data, int p_session) override; | ||||||
|  | 	virtual bool has_capture(const String &p_capture) const override; | ||||||
|  | 
 | ||||||
|  | 	bool add_screenshot_callback(const Callable &p_callaback, const Rect2i &p_rect); | ||||||
|  | 
 | ||||||
| 	void set_suspend(bool p_enabled); | 	void set_suspend(bool p_enabled); | ||||||
| 	void next_frame(); | 	void next_frame(); | ||||||
| 
 | 
 | ||||||
|  | @ -173,6 +188,8 @@ class GameView : public VBoxContainer { | ||||||
| 	void _play_pressed(); | 	void _play_pressed(); | ||||||
| 	static void _instance_starting_static(int p_idx, List<String> &r_arguments); | 	static void _instance_starting_static(int p_idx, List<String> &r_arguments); | ||||||
| 	void _instance_starting(int p_idx, List<String> &r_arguments); | 	void _instance_starting(int p_idx, List<String> &r_arguments); | ||||||
|  | 	static bool _instance_rq_screenshot_static(const Callable &p_callback); | ||||||
|  | 	bool _instance_rq_screenshot(const Callable &p_callback); | ||||||
| 	void _stop_pressed(); | 	void _stop_pressed(); | ||||||
| 	void _embedding_completed(); | 	void _embedding_completed(); | ||||||
| 	void _embedding_failed(); | 	void _embedding_failed(); | ||||||
|  |  | ||||||
|  | @ -60,7 +60,6 @@ class GameViewDebuggerMacOS : public GameViewDebugger { | ||||||
| 
 | 
 | ||||||
| public: | public: | ||||||
| 	virtual bool capture(const String &p_message, const Array &p_data, int p_session) override; | 	virtual bool capture(const String &p_message, const Array &p_data, int p_session) override; | ||||||
| 	virtual bool has_capture(const String &p_capture) const override; |  | ||||||
| 
 | 
 | ||||||
| 	GameViewDebuggerMacOS(EmbeddedProcessMacOS *p_embedded_process); | 	GameViewDebuggerMacOS(EmbeddedProcessMacOS *p_embedded_process); | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | @ -109,10 +109,6 @@ void GameViewDebuggerMacOS::_init_capture_message_handlers() { | ||||||
| 	parse_message_handlers["game_view:joy_stop"] = &GameViewDebuggerMacOS::_msg_joy_stop; | 	parse_message_handlers["game_view:joy_stop"] = &GameViewDebuggerMacOS::_msg_joy_stop; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool GameViewDebuggerMacOS::has_capture(const String &p_capture) const { |  | ||||||
| 	return p_capture == "game_view"; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool GameViewDebuggerMacOS::capture(const String &p_message, const Array &p_data, int p_session) { | bool GameViewDebuggerMacOS::capture(const String &p_message, const Array &p_data, int p_session) { | ||||||
| 	Ref<EditorDebuggerSession> session = get_session(p_session); | 	Ref<EditorDebuggerSession> session = get_session(p_session); | ||||||
| 	ERR_FAIL_COND_V(session.is_null(), true); | 	ERR_FAIL_COND_V(session.is_null(), true); | ||||||
|  | @ -121,9 +117,7 @@ bool GameViewDebuggerMacOS::capture(const String &p_message, const Array &p_data | ||||||
| 	if (fn_ptr) { | 	if (fn_ptr) { | ||||||
| 		return (this->**fn_ptr)(p_data); | 		return (this->**fn_ptr)(p_data); | ||||||
| 	} else { | 	} else { | ||||||
| 		// Any other messages with this prefix should be ignored. | 		return GameViewDebugger::capture(p_message, p_data, p_session); | ||||||
| 		WARN_PRINT("GameViewDebuggerMacOS unknown message: " + p_message); |  | ||||||
| 		return ERR_SKIP; |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	return true; | 	return true; | ||||||
|  |  | ||||||
|  | @ -32,9 +32,11 @@ | ||||||
| 
 | 
 | ||||||
| #include "core/debugger/debugger_marshalls.h" | #include "core/debugger/debugger_marshalls.h" | ||||||
| #include "core/debugger/engine_debugger.h" | #include "core/debugger/engine_debugger.h" | ||||||
|  | #include "core/io/dir_access.h" | ||||||
| #include "core/io/marshalls.h" | #include "core/io/marshalls.h" | ||||||
| #include "core/math/math_fieldwise.h" | #include "core/math/math_fieldwise.h" | ||||||
| #include "core/object/script_language.h" | #include "core/object/script_language.h" | ||||||
|  | #include "core/os/time.h" | ||||||
| #include "core/templates/local_vector.h" | #include "core/templates/local_vector.h" | ||||||
| #include "scene/gui/popup_menu.h" | #include "scene/gui/popup_menu.h" | ||||||
| #include "scene/main/canvas_layer.h" | #include "scene/main/canvas_layer.h" | ||||||
|  | @ -423,6 +425,46 @@ Error SceneDebugger::_msg_runtime_node_select_reset_camera_3d(const Array &p_arg | ||||||
| 
 | 
 | ||||||
| // endregion
 | // endregion
 | ||||||
| 
 | 
 | ||||||
|  | // region Embedded process screenshot.
 | ||||||
|  | 
 | ||||||
|  | Error SceneDebugger::_msg_rq_screenshot(const Array &p_args) { | ||||||
|  | 	ERR_FAIL_COND_V(p_args.is_empty(), ERR_INVALID_DATA); | ||||||
|  | 
 | ||||||
|  | 	Viewport *viewport = SceneTree::get_singleton()->get_root(); | ||||||
|  | 	ERR_FAIL_NULL_V_MSG(viewport, ERR_UNCONFIGURED, "Cannot get a viewport from the main screen."); | ||||||
|  | 	Ref<ViewportTexture> texture = viewport->get_texture(); | ||||||
|  | 	ERR_FAIL_COND_V_MSG(texture.is_null(), ERR_UNCONFIGURED, "Cannot get a viewport texture from the main screen."); | ||||||
|  | 	Ref<Image> img = texture->get_image(); | ||||||
|  | 	ERR_FAIL_COND_V_MSG(img.is_null(), ERR_UNCONFIGURED, "Cannot get an image from a viewport texture of the main screen."); | ||||||
|  | 	img->clear_mipmaps(); | ||||||
|  | 
 | ||||||
|  | 	const String TEMP_DIR = OS::get_singleton()->get_temp_path(); | ||||||
|  | 	uint32_t suffix_i = 0; | ||||||
|  | 	String path; | ||||||
|  | 	while (true) { | ||||||
|  | 		String datetime = Time::get_singleton()->get_datetime_string_from_system().remove_chars("-T:"); | ||||||
|  | 		datetime += itos(Time::get_singleton()->get_ticks_usec()); | ||||||
|  | 		String suffix = datetime + (suffix_i > 0 ? itos(suffix_i) : ""); | ||||||
|  | 		path = TEMP_DIR.path_join("scr-" + suffix + ".png"); | ||||||
|  | 		if (!DirAccess::exists(path)) { | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 		suffix_i += 1; | ||||||
|  | 	} | ||||||
|  | 	img->save_png(path); | ||||||
|  | 
 | ||||||
|  | 	Array arr; | ||||||
|  | 	arr.append(p_args[0]); | ||||||
|  | 	arr.append(img->get_width()); | ||||||
|  | 	arr.append(img->get_height()); | ||||||
|  | 	arr.append(path); | ||||||
|  | 	EngineDebugger::get_singleton()->send_message("game_view:get_screenshot", arr); | ||||||
|  | 
 | ||||||
|  | 	return OK; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // endregion
 | ||||||
|  | 
 | ||||||
| HashMap<String, SceneDebugger::ParseMessageFunc> SceneDebugger::message_handlers; | HashMap<String, SceneDebugger::ParseMessageFunc> SceneDebugger::message_handlers; | ||||||
| 
 | 
 | ||||||
| Error SceneDebugger::parse_message(void *p_user, const String &p_msg, const Array &p_args, bool &r_captured) { | Error SceneDebugger::parse_message(void *p_user, const String &p_msg, const Array &p_args, bool &r_captured) { | ||||||
|  | @ -490,6 +532,7 @@ void SceneDebugger::_init_message_handlers() { | ||||||
| #ifndef _3D_DISABLED | #ifndef _3D_DISABLED | ||||||
| 	message_handlers["runtime_node_select_reset_camera_3d"] = _msg_runtime_node_select_reset_camera_3d; | 	message_handlers["runtime_node_select_reset_camera_3d"] = _msg_runtime_node_select_reset_camera_3d; | ||||||
| #endif | #endif | ||||||
|  | 	message_handlers["rq_screenshot"] = _msg_rq_screenshot; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void SceneDebugger::_save_node(ObjectID id, const String &p_path) { | void SceneDebugger::_save_node(ObjectID id, const String &p_path) { | ||||||
|  |  | ||||||
|  | @ -119,6 +119,7 @@ private: | ||||||
| #ifndef _3D_DISABLED | #ifndef _3D_DISABLED | ||||||
| 	static Error _msg_runtime_node_select_reset_camera_3d(const Array &p_args); | 	static Error _msg_runtime_node_select_reset_camera_3d(const Array &p_args); | ||||||
| #endif | #endif | ||||||
|  | 	static Error _msg_rq_screenshot(const Array &p_args); | ||||||
| 
 | 
 | ||||||
| public: | public: | ||||||
| 	static Error parse_message(void *p_user, const String &p_msg, const Array &p_args, bool &r_captured); | 	static Error parse_message(void *p_user, const String &p_msg, const Array &p_args, bool &r_captured); | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Rémi Verschelde
						Rémi Verschelde