class_name PankuModuleInteractiveShell extends PankuModule var window:PankuLynxWindow var interactive_shell:Control var simple_launcher:Control enum InputMode { Window, Launcher } var gui_mode:InputMode = InputMode.Window var pause_if_input:bool = true var unified_window_visibility:bool = false var init_expr:String = "" var _is_gui_open:bool = false var _was_tree_paused: bool = false var _previous_mouse_mode := Input.MOUSE_MODE_VISIBLE var _show_side_menu:bool func get_intro() -> String: var intro:PackedStringArray = PackedStringArray() intro.append("[color=#ffffff44][b][i]> Panku Console[/i][/b][/color]") intro.append("[color=#ffffff44]Feature-Packed Runtime Debugging Toolkit for Godot[/color]") intro.append("[color=#ffffff44]Version: %s([url=%s][color=#10a00c]%s[/color][/url]) | Visit [color=#3feeb6][url=https://github.com/Ark2000/PankuConsole]github repo[/url][/color] for more info[/color]" % [PankuUtils.get_plugin_version(), PankuUtils.get_commit_url(), PankuUtils.get_commit_sha_short()]) return "\n".join(intro) func init_module(): interactive_shell = preload("./console_ui/panku_console_ui.tscn").instantiate() window = core.windows_manager.create_window(interactive_shell) add_auto_save_hook(window) interactive_shell._repl._module = self window.queue_free_on_close = false window.set_window_title_text("Interactive Shell V2") load_window_data(window) window.hide_window() interactive_shell.output(get_intro()) simple_launcher = preload("./mini_repl_2.tscn").instantiate() simple_launcher.console = core core.add_child(simple_launcher) simple_launcher.repl._module = self simple_launcher.hide() core.toggle_console_action_just_pressed.connect( func(): if gui_mode == InputMode.Window: if window.visible: window.hide_window() else: window.show_window() elif gui_mode == InputMode.Launcher: simple_launcher.visible = not simple_launcher.visible ) # Grab the mouse when the dev console is visible (e.g. FPS games) window.visibility_changed.connect( func(): # the mouse is grabbed when the window is visible if window.visible: _previous_mouse_mode = Input.mouse_mode Input.mouse_mode = Input.MOUSE_MODE_VISIBLE # restore the mouse mode when the window is hidden else: Input.mouse_mode = _previous_mouse_mode ) gui_mode = load_module_data("gui_mode", InputMode.Window) pause_if_input = load_module_data("pause_if_popup", true) unified_window_visibility = load_module_data("unified_visibility", false) init_expr = load_module_data("init_expression", "print('Panku Console Loaded!')") _show_side_menu = load_module_data("show_side_menu", true) set_side_menu_visible(_show_side_menu) window.visibility_changed.connect(update_gui_state) simple_launcher.visibility_changed.connect(update_gui_state) _is_gui_open = not (window.visible or simple_launcher.visible) update_gui_state() # TODO: this signal is emitted twice when the window is shown, investigate # window.visibility_changed.connect( # func(): # print("window visibility changed: ", window.visible) # ) # execute init_expr after a short delay if init_expr != "": core.create_tween().tween_callback( func(): var result = core.gd_exprenv.execute(init_expr) core.new_expression_entered.emit(init_expr, result) ).set_delay(0.1) _input_histories = load_module_data("histories", []) func quit_module(): super.quit_module() save_window_data(window) save_module_data("gui_mode", gui_mode) save_module_data("histories", _input_histories) save_module_data("show_side_menu", _show_side_menu) func update_gui_state(): var is_gui_open = window.visible or simple_launcher.visible if is_gui_open == _is_gui_open: return if _is_gui_open != is_gui_open: core._shell_visibility = is_gui_open core.interactive_shell_visibility_changed.emit(is_gui_open) _is_gui_open = is_gui_open if _is_gui_open and pause_if_input: _was_tree_paused = core.get_tree().paused core.get_tree().paused = true else: if core.get_tree().paused: core.get_tree().paused = _was_tree_paused if unified_window_visibility: core.windows_manager.visible = _is_gui_open func open_window(): if gui_mode == InputMode.Window: if not window.visible: window.show_window() else: core.notify("The window is alreay opened.") elif gui_mode == InputMode.Launcher: gui_mode = InputMode.Window simple_launcher.hide() window.show_window() func open_launcher(): if gui_mode == InputMode.Window: gui_mode = InputMode.Launcher window.hide_window() simple_launcher.show() elif gui_mode == InputMode.Launcher: if not simple_launcher.visible: simple_launcher.show() else: core.notify("The launcher is alreay opened.") func set_side_menu_visible(enabled:bool): _show_side_menu = enabled interactive_shell.enable_side_menu = enabled interactive_shell.resized.emit() func set_unified_window_visibility(enabled:bool): unified_window_visibility = enabled update_gui_state() func set_pause_if_popup(enabled:bool): pause_if_input = enabled update_gui_state() const MAX_HISTORY = 10 var _input_histories := [] func get_histories() -> Array: return _input_histories func add_history(s:String) -> void: _input_histories.append(s) if _input_histories.size() > MAX_HISTORY: _input_histories.remove_at(0)