@@ -8,6 +8,7 @@ extends "res://addons/SetupPlugin/Scripts/Dock/DevToolsTabLayout.gd"
88
99const PROJECT_ROOT_PATH : String = "res://"
1010const ANTI_ALIASING_PATH_3D : String = "rendering/anti_aliasing/quality/msaa_3d"
11+ const SOLUTION_FILE_NAME : String = "Template.sln"
1112const DevToolsUidCleanupScript = preload ("DevToolsUidCleanup.gd" )
1213const EditorSceneActionsScript = preload ("EditorSceneActions.gd" )
1314const NullableProjectSettingsScript = preload ("NullableProjectSettings.gd" )
@@ -58,7 +59,7 @@ func _project_root() -> String:
5859func _register_events () -> void :
5960 if _events_registered :
6061 return
61- for pair in [[_cleanup_uids_button , _on_cleanup_uids_pressed ], [_nullable_button , _on_nullable_pressed ], [_remove_empty_folders_button , _on_remove_empty_folders_pressed ], [_close_all_scene_tabs_button , _on_close_all_scene_tabs_pressed ], [_restart_editor_button , _on_restart_editor_pressed ], [_expand_to_level_button , _on_expand_to_level_pressed ], [_fully_expand_button , _on_fully_expand_pressed ], [_fully_collapse_button , _on_fully_collapse_pressed ], [_update_from_main_button , _on_update_from_main_pressed ], [_update_from_release_button , _on_update_from_release_pressed ], [_check_updates_button , _on_check_updates_pressed ], [_reset_update_cache_button , _on_reset_update_cache_pressed ], [_view_template_repo_button , _on_view_template_repo_pressed ], [_link_to_commits_button , _on_link_to_commits_pressed ], [_link_to_release_notes_button , _on_link_to_release_notes_pressed ]]:
62+ for pair in [[_open_external_editor_button , _on_open_external_editor_pressed ], [ _cleanup_uids_button , _on_cleanup_uids_pressed ], [_nullable_button , _on_nullable_pressed ], [_remove_empty_folders_button , _on_remove_empty_folders_pressed ], [_close_all_scene_tabs_button , _on_close_all_scene_tabs_pressed ], [_restart_editor_button , _on_restart_editor_pressed ], [_expand_to_level_button , _on_expand_to_level_pressed ], [_fully_expand_button , _on_fully_expand_pressed ], [_fully_collapse_button , _on_fully_collapse_pressed ], [_update_from_main_button , _on_update_from_main_pressed ], [_update_from_release_button , _on_update_from_release_pressed ], [_check_updates_button , _on_check_updates_pressed ], [_reset_update_cache_button , _on_reset_update_cache_pressed ], [_view_template_repo_button , _on_view_template_repo_pressed ], [_link_to_commits_button , _on_link_to_commits_pressed ], [_link_to_release_notes_button , _on_link_to_release_notes_pressed ]]:
6263 pair [0 ].pressed .connect (pair [1 ])
6364 _check_updates_on_startup_checkbox .toggled .connect (_on_check_updates_on_startup_toggled )
6465 _clear_color_picker .color_changed .connect (_on_clear_color_changed )
@@ -72,7 +73,7 @@ func _unregister_events() -> void:
7273 if not _events_registered :
7374 return
7475 _events_registered = false
75- for pair in [[_cleanup_uids_button , "_on_cleanup_uids_pressed" ], [_nullable_button , "_on_nullable_pressed" ], [_remove_empty_folders_button , "_on_remove_empty_folders_pressed" ], [_close_all_scene_tabs_button , "_on_close_all_scene_tabs_pressed" ], [_restart_editor_button , "_on_restart_editor_pressed" ], [_expand_to_level_button , "_on_expand_to_level_pressed" ], [_fully_expand_button , "_on_fully_expand_pressed" ], [_fully_collapse_button , "_on_fully_collapse_pressed" ], [_update_from_main_button , "_on_update_from_main_pressed" ], [_update_from_release_button , "_on_update_from_release_pressed" ], [_check_updates_button , "_on_check_updates_pressed" ], [_reset_update_cache_button , "_on_reset_update_cache_pressed" ], [_view_template_repo_button , "_on_view_template_repo_pressed" ], [_link_to_commits_button , "_on_link_to_commits_pressed" ], [_link_to_release_notes_button , "_on_link_to_release_notes_pressed" ]]:
76+ for pair in [[_open_external_editor_button , "_on_open_external_editor_pressed" ], [ _cleanup_uids_button , "_on_cleanup_uids_pressed" ], [_nullable_button , "_on_nullable_pressed" ], [_remove_empty_folders_button , "_on_remove_empty_folders_pressed" ], [_close_all_scene_tabs_button , "_on_close_all_scene_tabs_pressed" ], [_restart_editor_button , "_on_restart_editor_pressed" ], [_expand_to_level_button , "_on_expand_to_level_pressed" ], [_fully_expand_button , "_on_fully_expand_pressed" ], [_fully_collapse_button , "_on_fully_collapse_pressed" ], [_update_from_main_button , "_on_update_from_main_pressed" ], [_update_from_release_button , "_on_update_from_release_pressed" ], [_check_updates_button , "_on_check_updates_pressed" ], [_reset_update_cache_button , "_on_reset_update_cache_pressed" ], [_view_template_repo_button , "_on_view_template_repo_pressed" ], [_link_to_commits_button , "_on_link_to_commits_pressed" ], [_link_to_release_notes_button , "_on_link_to_release_notes_pressed" ]]:
7677 _disconnect_signal (pair [0 ], "pressed" , pair [1 ])
7778 _disconnect_signal (_check_updates_on_startup_checkbox , "toggled" , "_on_check_updates_on_startup_toggled" )
7879 _disconnect_signal (_clear_color_picker , "color_changed" , "_on_clear_color_changed" )
@@ -94,17 +95,6 @@ func _set_status(text: String) -> void:
9495 _status_label .text = text
9596 _status_label .modulate = Color (0.6 , 0.95 , 0.6 )
9697
97- # Updates the status label shown at the bottom of the Visual tab.
98- func _set_visual_status (text : String ) -> void :
99- if _visual_status_label == null :
100- return
101- if text .is_empty ():
102- _visual_status_label .text = " "
103- _visual_status_label .modulate = Color (0.75 , 0.75 , 0.75 )
104- return
105- _visual_status_label .text = text
106- _visual_status_label .modulate = Color (0.6 , 0.95 , 0.6 )
107-
10898# Updates the status label in the Update tab only.
10999func _set_update_status (text : String ) -> void :
110100 _set_update_feedback (text )
@@ -119,7 +109,6 @@ func _refresh_editor_filesystem() -> void:
119109# Clears the status label once the feedback display duration elapses.
120110func _on_feedback_timer_timeout () -> void :
121111 _set_status ("" )
122- _set_visual_status ("" )
123112
124113# Updates the green update feedback label. An empty string hides its text.
125114func _set_update_feedback (text : String ) -> void :
@@ -171,35 +160,113 @@ func _on_restart_editor_pressed() -> void:
171160 _feedback_timer .start ()
172161 _editor_scene_actions .restart_editor (true )
173162
163+ # Opens the selected external editor, falling back to the system default.
164+ func _on_open_external_editor_pressed () -> void :
165+ var project_root : String = _project_root ()
166+ var solution_path : String = project_root .path_join (SOLUTION_FILE_NAME )
167+ var open_target : String = solution_path if FileAccess .file_exists (solution_path ) else project_root
168+ var selection : String = _selected_external_editor_key ()
169+ var opened : bool = false
170+
171+ match selection :
172+ EXTERNAL_EDITOR_VSCODE :
173+ opened = _open_in_vscode (project_root )
174+ EXTERNAL_EDITOR_VISUAL_STUDIO :
175+ opened = _open_in_visual_studio (open_target )
176+ EXTERNAL_EDITOR_RIDER :
177+ opened = _open_in_rider (open_target )
178+ _ :
179+ opened = _open_with_default (open_target )
180+
181+ _set_status ("Opened external editor." if opened else "Could not open external editor. Check your IDE install or PATH." )
182+ _feedback_timer .start ()
183+
184+ func _selected_external_editor_key () -> String :
185+ if _external_editor_options == null :
186+ return EXTERNAL_EDITOR_AUTO
187+ var index : int = _external_editor_options .selected
188+ var meta : Variant = _external_editor_options .get_item_metadata (index )
189+ if meta is String and not (meta as String ).is_empty ():
190+ return str (meta )
191+ return EXTERNAL_EDITOR_AUTO
192+
193+ func _open_in_vscode (project_root : String ) -> bool :
194+ var os_name : String = OS .get_name ()
195+ if os_name == "macOS" :
196+ if _try_launch ("open" , ["-a" , "Visual Studio Code" , project_root ]):
197+ return true
198+ if _try_launch ("code" , ["-r" , project_root ]):
199+ return true
200+ if _try_launch ("code-insiders" , ["-r" , project_root ]):
201+ return true
202+ var uri_path : String = project_root .replace (" " , "%20" )
203+ return OS .shell_open ("vscode://file/%s " % uri_path ) == OK
204+
205+ func _open_in_visual_studio (solution_path : String ) -> bool :
206+ var os_name : String = OS .get_name ()
207+ if os_name == "Windows" :
208+ if _try_launch ("devenv" , [solution_path ]):
209+ return true
210+ if _try_launch ("devenv.exe" , [solution_path ]):
211+ return true
212+ elif os_name == "macOS" :
213+ if _try_launch ("open" , ["-a" , "Visual Studio" , solution_path ]):
214+ return true
215+ return _open_with_default (solution_path )
216+
217+ func _open_in_rider (solution_path : String ) -> bool :
218+ var os_name : String = OS .get_name ()
219+ if os_name == "Windows" :
220+ for exe in ["rider64.exe" , "rider.exe" , "rider64" , "rider" ]:
221+ if _try_launch (exe , [solution_path ]):
222+ return true
223+ elif os_name == "macOS" :
224+ if _try_launch ("open" , ["-a" , "Rider" , solution_path ]):
225+ return true
226+ if _try_launch ("open" , ["-a" , "JetBrains Rider" , solution_path ]):
227+ return true
228+ else :
229+ for exe in ["rider" , "rider64" , "rider.sh" , "jetbrains-rider" ]:
230+ if _try_launch (exe , [solution_path ]):
231+ return true
232+ return _open_with_default (solution_path )
233+
234+ func _open_with_default (target_path : String ) -> bool :
235+ return OS .shell_open (target_path ) == OK
236+
237+ func _try_launch (executable : String , args : Array [String ]) -> bool :
238+ var pid : int = OS .create_process (executable , args , false )
239+ return pid != - 1
240+
174241# Expands the Scene dock hierarchy to the depth set in the SpinBox.
175242func _on_expand_to_level_pressed () -> void :
176243 var level : int = int (_hierarchy_level_spinbox .value )
177244 var changed_count : int = _scene_hierarchy_actions .expand_to_level (level )
178- _set_visual_status ("Expanded hierarchy to level %d " % level if changed_count > 0 else "No scene hierarchy available" )
245+ _set_status ("Expanded hierarchy to level %d " % level if changed_count > 0 else "No scene hierarchy available" )
179246 _feedback_timer .start ()
180247
181248# Fully expands every node in the Scene dock hierarchy.
182249func _on_fully_expand_pressed () -> void :
183- _set_visual_status ("Fully expanded hierarchy" if _scene_hierarchy_actions .fully_expand () > 0 else "No scene hierarchy available" )
250+ _set_status ("Fully expanded hierarchy" if _scene_hierarchy_actions .fully_expand () > 0 else "No scene hierarchy available" )
184251 _feedback_timer .start ()
185252
186253# Collapses the Scene dock hierarchy to just the root level.
187254func _on_fully_collapse_pressed () -> void :
188- _set_visual_status ("Fully collapsed hierarchy" if _scene_hierarchy_actions .fully_collapse () > 0 else "No scene hierarchy available" )
255+ _set_status ("Fully collapsed hierarchy" if _scene_hierarchy_actions .fully_collapse () > 0 else "No scene hierarchy available" )
189256 _feedback_timer .start ()
190257
191258# Persists the chosen viewport clear colour to project settings immediately.
192259func _on_clear_color_changed (color : Color ) -> void :
193260 ProjectSettings .set_setting (DEFAULT_CLEAR_COLOR_PATH , color )
194261 ProjectSettings .save ()
195- _set_visual_status ("Updated clear color." )
262+ _set_status ("Updated clear color." )
196263 _feedback_timer .start ()
197264
198265# Writes the chosen MSAA level to both 2D and 3D project settings.
199266func _on_anti_aliasing_item_selected (index : int ) -> void :
200267 ProjectSettings .set_setting (ANTI_ALIASING_PATH_2D , index )
201268 ProjectSettings .set_setting (ANTI_ALIASING_PATH_3D , index )
202- _set_visual_status ("Anti-aliasing updated." )
269+ _set_status ("Anti-aliasing updated." )
203270 _feedback_timer .start ()
204271
205272# Reads the current nullable state from Template.csproj and sets the button
0 commit comments