├── .github └── FUNDING.yml ├── .gitignore ├── DocEditorSettings.md ├── LICENSE ├── README.md ├── addons └── script_spliter │ ├── assets │ ├── File.svg │ ├── File.svg.import │ ├── dd.png │ ├── dd.png.import │ ├── github_CodeNameTwister.png │ ├── github_CodeNameTwister.png.import │ ├── placeholder.png │ └── placeholder.png.import │ ├── context │ ├── _POPGDScript_.gd │ ├── _POPGDScript_.gd.uid │ ├── btn_callback.gd │ ├── btn_callback.gd.uid │ ├── context_window.gd │ ├── context_window.gd.uid │ ├── custom_options.gd │ ├── custom_options.gd.uid │ ├── flying_script.gd │ ├── flying_script.gd.uid │ ├── flying_script.tscn │ ├── flying_script_font.tres │ ├── icons │ │ ├── atop.png │ │ ├── atop.png.import │ │ ├── expand.svg │ │ ├── expand.svg.import │ │ ├── sp_2H.png │ │ ├── sp_2H.png.import │ │ ├── sp_2V.png │ │ ├── sp_2V.png.import │ │ ├── sp_3H.png │ │ ├── sp_3H.png.import │ │ ├── sp_3V.png │ │ ├── sp_3V.png.import │ │ ├── sp_4S.png │ │ ├── sp_4S.png.import │ │ ├── sp_custom.png │ │ ├── sp_custom.png.import │ │ ├── sp_disable.png │ │ ├── sp_disable.png.import │ │ ├── split_cminus.svg │ │ ├── split_cminus.svg.import │ │ ├── split_cplus.svg │ │ ├── split_cplus.svg.import │ │ ├── split_rminus.svg │ │ ├── split_rminus.svg.import │ │ ├── split_rplus.svg │ │ └── split_rplus.svg.import │ ├── menu_tool.gd │ ├── menu_tool.gd.uid │ ├── menu_tool.tscn │ ├── panel_preview.tscn │ ├── split_type_button.gd │ ├── split_type_button.gd.uid │ └── tab_preview.tscn │ ├── core │ ├── DDContainer.gd │ ├── DDContainer.gd.uid │ ├── DDItem.gd │ ├── DDItem.gd.uid │ ├── DDTAB.gd │ ├── DDTAB.gd.uid │ ├── DaemonChaser.gd │ ├── DaemonChaser.gd.uid │ ├── EditorContainer.gd │ ├── EditorContainer.gd.uid │ ├── builder.gd │ ├── builder.gd.uid │ └── ui │ │ ├── dd.gd │ │ ├── dd.gd.uid │ │ ├── dd.tscn │ │ ├── icon │ │ ├── MultiSpliter.svg │ │ ├── MultiSpliter.svg.import │ │ ├── MultiSpliterButton.svg │ │ ├── MultiSpliterButton.svg.import │ │ ├── MultiSpliterItem.svg │ │ └── MultiSpliterItem.svg.import │ │ ├── multi_split_container.gd │ │ ├── multi_split_container.gd.uid │ │ ├── split_container_item.gd │ │ └── split_container_item.gd.uid │ ├── io │ ├── backward_key_button.tres │ ├── backward_mouse_button.tres │ ├── forward_key_button.tres │ └── forward_mouse_button.tres │ ├── plugin.cfg │ ├── plugin.gd │ └── plugin.gd.uid └── images ├── img0.png ├── img1.png ├── img2.png └── img3.png /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | ko_fi: cntwister 4 | buy_me_a_coffee: twister 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Godot 4+ specific ignores 2 | .godot/ 3 | 4 | # Godot-specific ignores 5 | .import/ 6 | export.cfg 7 | export_credentials.cfg 8 | 9 | # Imported translations (automatically generated from CSV files) 10 | *.translation 11 | 12 | # Mono-specific ignores 13 | .mono/ 14 | data_*/ 15 | mono_crash.*.json 16 | 17 | # User IO ignores 18 | addons/script_spliter/io/*_button.tres 19 | -------------------------------------------------------------------------------- /DocEditorSettings.md: -------------------------------------------------------------------------------- 1 | # Script Spliter in Editor Settings 2 | Each plugin configuration parameter is documented here. 3 | 4 | **Root of EditorSettings**: *plugin/script_spliter/** 5 | 6 | | Setting | Description | 7 | | ------------ | ------------ | 8 | | Row | (Work on start/Managed by Plugin) Initial rows, if it is zero it will be equal to 1 | 9 | | Column | (Work on start/Managed by Plugin) Initial columns, if it is zero it will be equal to 1 | 10 | | Save Rows Columns Count on exit | Save the current columns and rows you split before exiting to open them on next startup | 11 | 12 | ### Behaviour 13 | | Setting | Description | 14 | | ------------ | ------------ | 15 | | Refresh Warnings On Save | Check on save if all scripts has new errors/warnings| 16 | 17 | ### Window 18 | | Setting | Description | 19 | | ------------ | ------------ | 20 | | Use Highlight Selected | Show fade color when focus a window| 21 | | Highlight Selected Color | Color of the fader when focus | 22 | 23 | ### Editor 24 | | Setting | Description | 25 | | ------------ | ------------ | 26 | | Minimap for unfocus window | Hide minimap of the script when focus another window | 27 | | Out Focus Color Enabled | Enable set a modulate color when focus another window | 28 | | Out Focus Color Value | Modulate color when focus another window | 29 | 30 | ### Editor/Behaviour 31 | | Setting | Description | 32 | | ------------ | ------------ | 33 | | Expand on focus | Enable expand when focus a split window shrunk | 34 | | Can expand on same focus | Force Expand if the window current focused is shrunk | 35 | | Smooth expand | Enable Smooth when expand the window shrunk | 36 | | Smooth expand time| Total time for complete expand the window shrunk| 37 | | Swap by double click separator button | Enable swap between windows when double click in separator button | 38 | 39 | ### Editor/Behaviour/Back And Forward 40 | | Setting | Description | 41 | | ------------ | ------------ | 42 | | Handle Back And Forward | Enable handler event of back and forward by internal function addon | 43 | | History Size | Max buffer size history of scripts/documents recent opened by the window split (Are stored independently by window) 44 | | Using As Next And Back Tab| Change Behaviour and use back and forward as next or back aviable tab | 45 | | Backward Key Button Path| Path of resource setting of backward key button | 46 | | Forward Key Button Path| Path of resource setting of forward key button | 47 | | Backward Mouse Button Path| Path of resource setting of backward mouse button | 48 | | Forward Mouse Button Path| Path of resource setting of forward mouse button | 49 | | Use Native Handler When There Are No More Tabs| Enable leave to godot handle the back and forward when not exist more tabs in the focused window | 50 | 51 | ### Editor/Split 52 | This section work only when you add new split/s. 53 | in old versions < 0.3 was more useful. 54 | 55 | | Setting | Description | 56 | | ------------ | ------------ | 57 | | Reopen Last Closed Editor On Add Split | Enable open a script recent used and closed (Only for script / unless you make a request on github and change your mind)| 58 | | Remember Last Used Editor Buffer Size | Max last scripts for remember, maybe you want increase if you usually work with more than 4 windows | 59 | 60 | 61 | ### Line 62 | | Setting | Description | 63 | | ------------ | ------------ | 64 | | Size | Line width | 65 | | Color | Color of the Line, magenta is default that mean use editor color | 66 | | Draggable | Allow drag the Line pressing the primary mouse button | 67 | | Expand by Double Click | When you press with mouse (double click) the line back to initial position | 68 | 69 | ### Button 70 | | Setting | Description | 71 | | ------------ | ------------ | 72 | | Size | Button width | 73 | | Modulate | Modulate Button Color | 74 | | Icon Path | Texture path for the button | 75 | # 76 | Script Spliter tool plugin for Community Of Godot 4, created by Twister. 77 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 Twister 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Script-Spliter 2 | Tool addon for Godot 4, this addon allow split the script editor window. 3 | 4 | [![Godot Engine 4.3](https://img.shields.io/badge/Godot_Engine-4.x-blue)](https://godotengine.org/) ![ToolHack](https://img.shields.io/badge/Tool-Addon-green) ![Copyrights License](https://img.shields.io/badge/License-MIT-blue) 5 | 6 | 7 | ## Table of contents 8 | 9 | - [Preview](#preview-) 10 | - [News](#news-) 11 | - [Features](#features-) 12 | - [Roadmap](#roadmap) 13 | - [How-Work](#how-work) 14 | - [Know Issues](#know-issues-) 15 | - [Special Thanks](#special-thanks-) 16 | 17 | 18 | # Preview [↑](#table-of-contents) 19 | 20 | ### V0.2 Video Preview 21 | [![video preview](https://github.com/user-attachments/assets/636cddf4-815e-4bf3-acab-13c26ff21318)](https://youtu.be/ISSu45qzWWw) 22 | 23 | ### V0.1 Image Preview 24 | ![image](https://github.com/user-attachments/assets/a6e1dea8-74cf-4fd9-b0b4-ec7d65ea3995) 25 | 26 | # NEWS [↑](#table-of-contents) 27 | 28 | ### V0.3 29 |

30 | 31 |

32 | Introduction to using tabs 33 | 34 | * Tabs can be dragged to another window, now you can move one document from a window split to another window split. 35 | * Backward and Forward has an internal function with the plugin. (Thanks to [@adancau](https://github.com/adancau)) 36 | 37 | >*I had initially planned to create a Notepad++ like functionality as a reference for version 0.3, but it has been decided to maintain the functionality and backward compatibility to avoid confusion for those using the plugin since version 0.1.* 38 | 39 | ### Drag and Drop 40 | You can use tabs to drag and drop into another split window to switch between editors or you can drag directly from the script list and drop into the split window. 41 | 42 | ### Modify Backward and Forward buttons 43 | You can modify the buttons by input resources in "script_spliter/io" folder, 44 | seen in [Backward/Forward Request](https://github.com/CodeNameTwister/Script-Spliter/issues/9#issuecomment-2917555511) 45 | 46 | ### Using Backward/Forward 47 | It is per-window history, this means that if you've navigated through three different scripts within the window, moving back will only move between those three. The same happens when moving forward, and it's not affected by any other movements you've made in another window. 48 | >[!TIP] 49 | >In editor settings you have the checkbox: "using_as_next_and_back_tab" if you want use Backward/Forward move like Back/Next Tab. 50 | # 51 | 52 | ### V0.2 53 |

54 | 55 |

56 | The internal workflow has been modified, but the functionality of its predecessor version has been maintained. 57 | 58 | This has been done to maintain compatibility when using shorteners like Ctrl + [1, 2, 3, 4] to change the split style, this might be broken in version 0.3, see the roadmap for details. 59 | 60 | ### Differences with version 0.1 61 | * It more closely resembles the default editor window. 62 | * Reduces window switching time. 63 | * Allows you to zoom in on all windows. 64 | * You may have a separate script documentation help window. 65 | * Some visual aspects and configurable parameters in Editor Settings. 66 | * More Features and Split Options. 67 | 68 | >[!NOTE] 69 | >This plugin uses another built-in plugin created by me called [Multi Split Container](https://github.com/CodeNameTwister/Multi-Split-Container) 70 | 71 | 72 | # Features [↑](#table-of-contents) 73 | * Split Window of Document Files Like Script/Document Helper Window. 74 | * Split Two Window Horizontal/Vertical. 75 | * Split Three Window Horizontal/Vertical. 76 | * Split Four Window Squared. 77 | * Split Custom Window defined by you. *(using RMB context menu or Tool Menu)* 78 | * Plugins Setting in Editor Settings. *(In the section Plugin, you can see with advance option enabled!)* 79 | * Pop Script: Make Floating Script in Separate Window using RMB context menu. 80 | * Refresh Warnings changes in all opened windows when project is saved *(Errors/Warning Script)* 81 | * Reopen recently closed/changed scripts when adding a split. (Suggestion: [#5](https://github.com/CodeNameTwister/Script-Spliter/issues/5)) 82 | * Swap between windows by double-clicking the draggable button. (Suggestion: [#8](https://github.com/CodeNameTwister/Script-Spliter/issues/8])) 83 | * Back and Forward between script opened by the window splited. (Suggestion: [#9](https://github.com/CodeNameTwister/Script-Spliter/issues/9])) 84 | * Drag and Drop tabs between windows. 85 | 86 | >[!WARNING] 87 | >Experimental Refresh Warnings *(This option can be disabled on Editor Settings)* 88 | 89 | >[!NOTE] 90 | >In [DocEditorSettings.md](DocEditorSettings.md) you can see the description of the settings. 91 | 92 | 93 | 94 | # ROADMAP 95 | * Version >= 0.2.3: ~Flying scripts; Allow split in separate windows.~ 96 | * Version >= 0.3: 97 | * ~Change logo/colors: Currently the pet I use on github is placed and it is planned to change it to one more suitable for the plugin.~ 98 | * ~Using tabs for drag and drop between windows.~ *~(WARNING! : Some features offered in previous versions may change)~* 99 | * Version >= 0.4: Revisit Pop Scripts Issues. 100 | 101 | # How Work 102 | 103 | >[!TIP] 104 | > Now you can add or remove split with using context menu, the popup menu appear using the RMB (Right mouse button) in the editor. 105 | > 106 | > * Use Add/Remove split if you want increase or decrease the auto split window function. 107 | 108 | >[!NOTE] 109 | > Keep in mind, the style when appear new window (As Column or Row) depend of you configuration split style! 110 | > 111 | > *This may change in future releases.* 112 | 113 | ### Enable by shortcut [↑](#table-of-contents) 114 | * Press shortcut (**Ctrl + 1**) for set one window. 115 | * Press shortcut (**Ctrl + 2**) for set one split of two windows: Horizontal. 116 | * Press shortcut (**Ctrl + 3**) for set one split of two windows: Vertical. 117 | * Press shortcut (**Ctrl + 4**) for set two split of three windows: Horizontal. 118 | * Press shortcut (**Ctrl + 5**) for set two split of three windows: Vertical. 119 | * Press shortcut (**Ctrl + 6**) for set three split of four windows: Squared split. 120 | 121 | ### Enable by Tool Menu [↑](#table-of-contents) 122 | For enable the Script spliter menu go to **Project > Tools > Script Spliter**. 123 | 124 | ![image](images/img0.png) 125 | 126 | You can select split type and disabled, see the image. 127 | 128 | ![image](images/img1.png) 129 | 130 | Once activated, you'll see a draggable line like the one in the image, indicating that the plugin is active. 131 | 132 | >[!IMPORTANT] 133 | >This section will automatically expand when you open **two scripts**. 134 | 135 | The position of the line will vary depending on the selection of horizontal or vertical. 136 | 137 | ![image](images/img2.png) 138 | 139 | # Know Issues [↑](#table-of-contents) 140 | ### Version 0.2.3 141 | The **PopScripts** (Floating Scripts) 142 | It still has some issues related to the editor focus, which means that if you switch scenes, some features like the search engine within the PopScript may be affected and become unresponsive. 143 | 144 | # Special Thanks 📜 145 | This section lists users who have contributed to improving the quality of this project. 146 | 147 | [@adancau](https://github.com/adancau) 148 | 149 | # 150 | Copyrights (c) CodeNameTwister. See [LICENSE](LICENSE) for details. 151 | 152 | [godot engine]: https://godotengine.org/ 153 | -------------------------------------------------------------------------------- /addons/script_spliter/assets/File.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /addons/script_spliter/assets/File.svg.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://ljki8k8ckjtt" 6 | path="res://.godot/imported/File.svg-8fbfaa1520af51e8b790d847f68ee557.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://addons/script_spliter/assets/File.svg" 14 | dest_files=["res://.godot/imported/File.svg-8fbfaa1520af51e8b790d847f68ee557.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | svg/scale=1.0 36 | editor/scale_with_editor_scale=false 37 | editor/convert_colors_with_editor_theme=false 38 | -------------------------------------------------------------------------------- /addons/script_spliter/assets/dd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeNameTwister/Script-Spliter/8312d5b0eb2b24c85c669d5f9b4092ae518dc8da/addons/script_spliter/assets/dd.png -------------------------------------------------------------------------------- /addons/script_spliter/assets/dd.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://cxds5tr6aq5v3" 6 | path="res://.godot/imported/dd.png-3704eaaffe380d5ad414e6e7fce28e96.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://addons/script_spliter/assets/dd.png" 14 | dest_files=["res://.godot/imported/dd.png-3704eaaffe380d5ad414e6e7fce28e96.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | -------------------------------------------------------------------------------- /addons/script_spliter/assets/github_CodeNameTwister.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeNameTwister/Script-Spliter/8312d5b0eb2b24c85c669d5f9b4092ae518dc8da/addons/script_spliter/assets/github_CodeNameTwister.png -------------------------------------------------------------------------------- /addons/script_spliter/assets/github_CodeNameTwister.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://tgaoyybc2iji" 6 | path="res://.godot/imported/github_CodeNameTwister.png-88287e5d04f5b5c67334953a8a4ce6f2.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://addons/script_spliter/assets/github_CodeNameTwister.png" 14 | dest_files=["res://.godot/imported/github_CodeNameTwister.png-88287e5d04f5b5c67334953a8a4ce6f2.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | -------------------------------------------------------------------------------- /addons/script_spliter/assets/placeholder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeNameTwister/Script-Spliter/8312d5b0eb2b24c85c669d5f9b4092ae518dc8da/addons/script_spliter/assets/placeholder.png -------------------------------------------------------------------------------- /addons/script_spliter/assets/placeholder.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://b4vaut1t0ox3c" 6 | path="res://.godot/imported/placeholder.png-fc12f7043a3f8f5693de9ceb8fdb24a0.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://addons/script_spliter/assets/placeholder.png" 14 | dest_files=["res://.godot/imported/placeholder.png-fc12f7043a3f8f5693de9ceb8fdb24a0.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | -------------------------------------------------------------------------------- /addons/script_spliter/context/_POPGDScript_.gd: -------------------------------------------------------------------------------- 1 | @warning_ignore("empty_file") 2 | # This script is only placeholder for handle pop script input. 3 | 4 | # This should closed and removed after closing the pop-up. 5 | -------------------------------------------------------------------------------- /addons/script_spliter/context/_POPGDScript_.gd.uid: -------------------------------------------------------------------------------- 1 | uid://bkfdswehvs8sf 2 | -------------------------------------------------------------------------------- /addons/script_spliter/context/btn_callback.gd: -------------------------------------------------------------------------------- 1 | @tool 2 | extends Button 3 | # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # 4 | # Script Spliter 5 | # https://github.com/CodeNameTwister/Script-Spliter 6 | # 7 | # Script Spliter addon for godot 4 8 | # author: "Twister" 9 | # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # 10 | 11 | func _pressed() -> void: 12 | var parent : Node = owner 13 | if parent == null: 14 | parent = get_parent() 15 | if parent: 16 | if parent.has_method(name): 17 | parent.call(name) 18 | -------------------------------------------------------------------------------- /addons/script_spliter/context/btn_callback.gd.uid: -------------------------------------------------------------------------------- 1 | uid://bo38caobn2x7a 2 | -------------------------------------------------------------------------------- /addons/script_spliter/context/context_window.gd: -------------------------------------------------------------------------------- 1 | @tool 2 | extends EditorContextMenuPlugin 3 | # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # 4 | # Script Spliter 5 | # https://github.com/CodeNameTwister/Script-Spliter 6 | # 7 | # Script Spliter addon for godot 4 8 | # author: "Twister" 9 | # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # 10 | var CONTEXT : String = "CUSTOM" 11 | var ICON : Texture = null 12 | var SHORTCUT : Shortcut = null 13 | var CALLABLE : Callable 14 | var VALIDATOR : Callable 15 | 16 | func _init(context : String, handle : Callable, validator : Callable, icon : Texture, input_key : Array[InputEvent] = []): 17 | CONTEXT = context 18 | CALLABLE = handle 19 | ICON = icon 20 | VALIDATOR = validator 21 | if input_key.size() > 0: 22 | SHORTCUT = Shortcut.new() 23 | SHORTCUT.events = input_key 24 | add_menu_shortcut(SHORTCUT, handle) 25 | 26 | func _popup_menu(paths : PackedStringArray): 27 | if VALIDATOR.is_valid(): 28 | if !VALIDATOR.call(paths): 29 | return 30 | if SHORTCUT: 31 | add_context_menu_item_from_shortcut(CONTEXT, SHORTCUT, ICON) 32 | else: 33 | if CALLABLE.is_valid(): 34 | add_context_menu_item(CONTEXT, CALLABLE, ICON) 35 | else: 36 | push_error("Not valid callaback!") 37 | -------------------------------------------------------------------------------- /addons/script_spliter/context/context_window.gd.uid: -------------------------------------------------------------------------------- 1 | uid://dmf7coyb6hgbe 2 | -------------------------------------------------------------------------------- /addons/script_spliter/context/custom_options.gd: -------------------------------------------------------------------------------- 1 | @tool 2 | extends Control 3 | # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # 4 | # Script Spliter 5 | # https://github.com/CodeNameTwister/Script-Spliter 6 | # 7 | # Script Spliter addon for godot 4 8 | # author: "Twister" 9 | # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # 10 | 11 | @export var columns : SpinBox 12 | @export var rows : SpinBox 13 | 14 | func set_values(_columns : int, _rows : int) -> void: 15 | columns.value = _columns 16 | rows.value = _rows 17 | 18 | func get_columns_value() -> int: 19 | return max(columns.value, 1) 20 | 21 | func get_rows_value() -> int: 22 | return max(rows.value, 1) 23 | -------------------------------------------------------------------------------- /addons/script_spliter/context/custom_options.gd.uid: -------------------------------------------------------------------------------- 1 | uid://y3jbguu2nw5c 2 | -------------------------------------------------------------------------------- /addons/script_spliter/context/flying_script.gd: -------------------------------------------------------------------------------- 1 | @tool 2 | extends Window 3 | # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # 4 | # Script Spliter 5 | # https://github.com/CodeNameTwister/Script-Spliter 6 | # 7 | # Script Spliter addon for godot 4f 8 | # author: "Twister" 9 | # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # 10 | signal on_close(window : Window) 11 | 12 | @export var _container : Control = null 13 | @export var _base_control : TabContainer = null 14 | @export var _always_top : Button = null 15 | @export var _close : Button = null 16 | @export var _root : Control = null 17 | 18 | var proxy : Control = null 19 | var replacer : Node = null 20 | var controller : Object = null 21 | 22 | func set_base_control(node : Node) -> void: 23 | if _base_control: 24 | _base_control.queue_sort() 25 | _base_control = node 26 | if _container: 27 | _container.add_child(node) 28 | return 29 | add_child(node) 30 | 31 | if node is Control: 32 | node.size = node.get_parent().size 33 | 34 | func get_base_control() -> TabContainer: 35 | return _base_control 36 | 37 | func _init() -> void: 38 | visible = false 39 | close_requested.connect(_on_close) 40 | visibility_changed.connect(_on_visibility) 41 | focus_entered.connect(_on_focus) 42 | focus_exited.connect(_on_focus_exited) 43 | 44 | func _get_edit(n : Node) -> CodeEdit: 45 | if n is CodeEdit: 46 | return n 47 | for x : Node in n.get_children(): 48 | return _get_edit(x) 49 | return null 50 | 51 | func _on_focus() -> void: 52 | if replacer == null: 53 | var script_editor: ScriptEditor = EditorInterface.get_script_editor() 54 | var root : Node = script_editor.get_child(0).get_child(1).get_child(1) 55 | if root.get_child_count() > 2: 56 | replacer = root.get_child(2) 57 | if "FindReplaceBar" in replacer.name: 58 | replacer.get_parent().remove_child(replacer) 59 | 60 | if is_instance_valid(_root): 61 | _root.add_child(replacer) 62 | else: 63 | add_child(replacer) 64 | 65 | if is_instance_valid(controller): 66 | controller.emit_signal.call_deferred(&"focus", controller) 67 | 68 | func _update_name() -> void: 69 | if is_queued_for_deletion(): 70 | return 71 | if is_instance_valid(_base_control): 72 | if _base_control.current_tab > -1: 73 | title = "Script-Spliter: {0}".format([_base_control.get_tab_title(_base_control.current_tab)]) 74 | return 75 | title = "Script-Spliter: Pop Script" 76 | 77 | func _on_tabity(__ : int) -> void: 78 | _update_name.call_deferred() 79 | 80 | func _on_always_top() -> void: 81 | if transient: 82 | return 83 | always_on_top = !always_on_top 84 | 85 | func _shortcut_input(event: InputEvent) -> void: 86 | if is_instance_valid(proxy): 87 | var vp : Viewport = proxy.get_viewport() 88 | if vp and vp != get_viewport(): 89 | vp.push_input(event) 90 | 91 | func _ready() -> void: 92 | set_process_shortcut_input(true) 93 | if _always_top: 94 | if !_always_top.pressed.is_connected(_on_always_top): 95 | _always_top.pressed.connect(_on_always_top) 96 | if _close: 97 | if !_close.pressed.is_connected(_on_close): 98 | _close.pressed.connect(_on_close) 99 | if _base_control: 100 | if !_base_control.tab_changed.is_connected(_on_tabity): 101 | _base_control.tab_changed.connect(_on_tabity) 102 | if !_base_control.child_entered_tree.is_connected(_on_child): 103 | _base_control.child_entered_tree.connect(_on_child) 104 | if !_base_control.child_exiting_tree.is_connected(_out_child): 105 | _base_control.child_exiting_tree.connect(_out_child) 106 | 107 | var root : Control = EditorInterface.get_base_control() 108 | if root: 109 | add_theme_stylebox_override(&"Panel",root.get_theme_stylebox("panel", "PanelContainer")) 110 | 111 | func _connect(n : Node, e : bool) -> void: 112 | if n is CodeEdit: 113 | if e: 114 | if !n.focus_entered.is_connected(_on_focus): 115 | n.focus_entered.connect(_on_focus) 116 | else: 117 | if n.focus_entered.is_connected(_on_focus): 118 | n.focus_entered.disconnect(_on_focus) 119 | return 120 | for x : Node in n.get_children(): 121 | _connect(x, e) 122 | 123 | func _on_child(n : Node) -> void: 124 | if n is Control: 125 | _connect(n, true) 126 | 127 | func _out_child(n : Node) -> void: 128 | if n is Control: 129 | _connect(n, false) 130 | 131 | func _on_visibility() -> void: 132 | if !visible: 133 | _on_focus_exited() 134 | _on_close() 135 | return 136 | set_deferred(&"always_top", false) 137 | set_process(true) 138 | _update_name.call_deferred() 139 | 140 | func _on_close() -> void: 141 | on_close.emit(self) 142 | 143 | if _base_control and _base_control.get_child_count() < 1: 144 | queue_free() 145 | 146 | func _on_focus_exited() -> void: 147 | if replacer != null: 148 | var script_editor: ScriptEditor = EditorInterface.get_script_editor() 149 | var root : Node = script_editor.get_child(0).get_child(1).get_child(1) 150 | 151 | var parent : Node = replacer.get_parent() 152 | if parent != root: 153 | if is_instance_valid(parent): 154 | parent.remove_child(replacer) 155 | root.add_child(replacer) 156 | replacer = null 157 | 158 | func _notification(what: int) -> void: 159 | if what == NOTIFICATION_PREDELETE: 160 | if is_instance_valid(replacer): 161 | var script_editor: ScriptEditor = EditorInterface.get_script_editor() 162 | var root : Node = script_editor.get_child(0).get_child(1).get_child(1) 163 | 164 | var parent : Node = replacer.get_parent() 165 | if parent != root: 166 | if is_instance_valid(parent): 167 | parent.remove_child(replacer) 168 | root.add_child(replacer) 169 | replacer = null 170 | if is_instance_valid(controller): 171 | controller.call(&"reset") 172 | 173 | func _move_to_center() -> void: 174 | move_to_center() 175 | 176 | func _alpha_value(v : float) -> void: 177 | get_child(0).modulate.a = v 178 | -------------------------------------------------------------------------------- /addons/script_spliter/context/flying_script.gd.uid: -------------------------------------------------------------------------------- 1 | uid://dbkyfe5ri2p73 2 | -------------------------------------------------------------------------------- /addons/script_spliter/context/flying_script.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=5 format=3 uid="uid://cr2xovtt6uo7s"] 2 | 3 | [ext_resource type="Script" uid="uid://dbkyfe5ri2p73" path="res://addons/script_spliter/context/flying_script.gd" id="1_wfm3d"] 4 | [ext_resource type="Texture2D" uid="uid://r6u1jtnbr4eg" path="res://addons/script_spliter/context/icons/atop.png" id="2_q3d74"] 5 | [ext_resource type="Script" uid="uid://bo38caobn2x7a" path="res://addons/script_spliter/context/btn_callback.gd" id="3_1p1sv"] 6 | 7 | [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_q3d74"] 8 | content_margin_left = 3.0 9 | content_margin_top = 3.0 10 | content_margin_right = 3.0 11 | content_margin_bottom = 3.0 12 | bg_color = Color(0.1155, 0.132, 0.1595, 1) 13 | corner_detail = 1 14 | anti_aliasing = false 15 | 16 | [node name="FlyingScript" type="Window" node_paths=PackedStringArray("_container", "_always_top", "_close", "_root")] 17 | title = "Script-Spliter: Pop Script" 18 | initial_position = 4 19 | size = Vector2i(805, 512) 20 | visible = false 21 | wrap_controls = true 22 | script = ExtResource("1_wfm3d") 23 | _container = NodePath("PanelContainer/VC") 24 | _always_top = NodePath("PanelContainer/VC/HB/AlwaysTop") 25 | _close = NodePath("PanelContainer/VC/HB/Close") 26 | _root = NodePath("PanelContainer/VC") 27 | 28 | [node name="PanelContainer" type="PanelContainer" parent="."] 29 | anchors_preset = 15 30 | anchor_right = 1.0 31 | anchor_bottom = 1.0 32 | grow_horizontal = 2 33 | grow_vertical = 2 34 | theme_override_styles/panel = SubResource("StyleBoxFlat_q3d74") 35 | 36 | [node name="VC" type="VBoxContainer" parent="PanelContainer"] 37 | layout_mode = 2 38 | size_flags_horizontal = 3 39 | size_flags_vertical = 3 40 | 41 | [node name="HB" type="HBoxContainer" parent="PanelContainer/VC"] 42 | layout_mode = 2 43 | theme_override_constants/separation = 8 44 | 45 | [node name="AlwaysTop" type="Button" parent="PanelContainer/VC/HB"] 46 | layout_mode = 2 47 | tooltip_text = "Set always front visible the current window" 48 | theme_override_font_sizes/font_size = 12 49 | toggle_mode = true 50 | text = "Always Top" 51 | icon = ExtResource("2_q3d74") 52 | flat = true 53 | 54 | [node name="_move_to_center" type="Button" parent="PanelContainer/VC/HB"] 55 | layout_mode = 2 56 | tooltip_text = "Move the window to center" 57 | theme_override_font_sizes/font_size = 12 58 | toggle_mode = true 59 | text = "Move To Center" 60 | flat = true 61 | script = ExtResource("3_1p1sv") 62 | 63 | [node name="Close" type="Button" parent="PanelContainer/VC/HB"] 64 | visible = false 65 | custom_minimum_size = Vector2(32, 0) 66 | layout_mode = 2 67 | size_flags_horizontal = 10 68 | tooltip_text = "Close the window" 69 | text = "X" 70 | -------------------------------------------------------------------------------- /addons/script_spliter/context/flying_script_font.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="LabelSettings" format=3 uid="uid://cdrt4b0qrb77v"] 2 | 3 | [resource] 4 | font_size = 12 5 | -------------------------------------------------------------------------------- /addons/script_spliter/context/icons/atop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeNameTwister/Script-Spliter/8312d5b0eb2b24c85c669d5f9b4092ae518dc8da/addons/script_spliter/context/icons/atop.png -------------------------------------------------------------------------------- /addons/script_spliter/context/icons/atop.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://r6u1jtnbr4eg" 6 | path="res://.godot/imported/atop.png-1d61cb69aae60a076cd60a0a3f1cc72c.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://addons/script_spliter/context/icons/atop.png" 14 | dest_files=["res://.godot/imported/atop.png-1d61cb69aae60a076cd60a0a3f1cc72c.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | -------------------------------------------------------------------------------- /addons/script_spliter/context/icons/expand.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /addons/script_spliter/context/icons/expand.svg.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://cractge21enk" 6 | path="res://.godot/imported/expand.svg-963ea7d55c7ac4362bba429ef9c40e46.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://addons/script_spliter/context/icons/expand.svg" 14 | dest_files=["res://.godot/imported/expand.svg-963ea7d55c7ac4362bba429ef9c40e46.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | svg/scale=1.0 36 | editor/scale_with_editor_scale=false 37 | editor/convert_colors_with_editor_theme=false 38 | -------------------------------------------------------------------------------- /addons/script_spliter/context/icons/sp_2H.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeNameTwister/Script-Spliter/8312d5b0eb2b24c85c669d5f9b4092ae518dc8da/addons/script_spliter/context/icons/sp_2H.png -------------------------------------------------------------------------------- /addons/script_spliter/context/icons/sp_2H.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://c1kjfqirfexvp" 6 | path="res://.godot/imported/sp_2H.png-c589a7f8579a9ee26d2875c35e52e183.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://addons/script_spliter/context/icons/sp_2H.png" 14 | dest_files=["res://.godot/imported/sp_2H.png-c589a7f8579a9ee26d2875c35e52e183.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | -------------------------------------------------------------------------------- /addons/script_spliter/context/icons/sp_2V.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeNameTwister/Script-Spliter/8312d5b0eb2b24c85c669d5f9b4092ae518dc8da/addons/script_spliter/context/icons/sp_2V.png -------------------------------------------------------------------------------- /addons/script_spliter/context/icons/sp_2V.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://d1r72ixdgbwl6" 6 | path="res://.godot/imported/sp_2V.png-39915ece37e791e8d9a130c4c3240f49.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://addons/script_spliter/context/icons/sp_2V.png" 14 | dest_files=["res://.godot/imported/sp_2V.png-39915ece37e791e8d9a130c4c3240f49.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | -------------------------------------------------------------------------------- /addons/script_spliter/context/icons/sp_3H.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeNameTwister/Script-Spliter/8312d5b0eb2b24c85c669d5f9b4092ae518dc8da/addons/script_spliter/context/icons/sp_3H.png -------------------------------------------------------------------------------- /addons/script_spliter/context/icons/sp_3H.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://32xnl4cu46pj" 6 | path="res://.godot/imported/sp_3H.png-09e8b9f9a346f328495f443e565ad878.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://addons/script_spliter/context/icons/sp_3H.png" 14 | dest_files=["res://.godot/imported/sp_3H.png-09e8b9f9a346f328495f443e565ad878.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | -------------------------------------------------------------------------------- /addons/script_spliter/context/icons/sp_3V.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeNameTwister/Script-Spliter/8312d5b0eb2b24c85c669d5f9b4092ae518dc8da/addons/script_spliter/context/icons/sp_3V.png -------------------------------------------------------------------------------- /addons/script_spliter/context/icons/sp_3V.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://b4cmfno0ixqnm" 6 | path="res://.godot/imported/sp_3V.png-6984dd1b3c8e11f26b5964981b46a4b8.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://addons/script_spliter/context/icons/sp_3V.png" 14 | dest_files=["res://.godot/imported/sp_3V.png-6984dd1b3c8e11f26b5964981b46a4b8.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | -------------------------------------------------------------------------------- /addons/script_spliter/context/icons/sp_4S.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeNameTwister/Script-Spliter/8312d5b0eb2b24c85c669d5f9b4092ae518dc8da/addons/script_spliter/context/icons/sp_4S.png -------------------------------------------------------------------------------- /addons/script_spliter/context/icons/sp_4S.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://bf2bjkoock7re" 6 | path="res://.godot/imported/sp_4S.png-38dbb9b7da5a9846aab652bf564a4249.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://addons/script_spliter/context/icons/sp_4S.png" 14 | dest_files=["res://.godot/imported/sp_4S.png-38dbb9b7da5a9846aab652bf564a4249.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | -------------------------------------------------------------------------------- /addons/script_spliter/context/icons/sp_custom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeNameTwister/Script-Spliter/8312d5b0eb2b24c85c669d5f9b4092ae518dc8da/addons/script_spliter/context/icons/sp_custom.png -------------------------------------------------------------------------------- /addons/script_spliter/context/icons/sp_custom.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://bdxvp5dyj8y0r" 6 | path="res://.godot/imported/sp_custom.png-91b7ef0ad7d63ebf7700a2047739db70.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://addons/script_spliter/context/icons/sp_custom.png" 14 | dest_files=["res://.godot/imported/sp_custom.png-91b7ef0ad7d63ebf7700a2047739db70.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | -------------------------------------------------------------------------------- /addons/script_spliter/context/icons/sp_disable.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeNameTwister/Script-Spliter/8312d5b0eb2b24c85c669d5f9b4092ae518dc8da/addons/script_spliter/context/icons/sp_disable.png -------------------------------------------------------------------------------- /addons/script_spliter/context/icons/sp_disable.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://dmvcijsjhb5pc" 6 | path="res://.godot/imported/sp_disable.png-d75c06feba36dd2af819e235b22c2ea6.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://addons/script_spliter/context/icons/sp_disable.png" 14 | dest_files=["res://.godot/imported/sp_disable.png-d75c06feba36dd2af819e235b22c2ea6.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | -------------------------------------------------------------------------------- /addons/script_spliter/context/icons/split_cminus.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 23 | 41 | 49 | 50 | 52 | 54 | 55 | split-screen 57 | 61 | 65 | 74 | 76 | 77 | 79 | split-screen 80 | 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /addons/script_spliter/context/icons/split_cminus.svg.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://c1b7aoplxr0x7" 6 | path="res://.godot/imported/split_cminus.svg-3d236e355acd272b8108cca3f8e1c7f3.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://addons/script_spliter/context/icons/split_cminus.svg" 14 | dest_files=["res://.godot/imported/split_cminus.svg-3d236e355acd272b8108cca3f8e1c7f3.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | svg/scale=8.0 36 | editor/scale_with_editor_scale=false 37 | editor/convert_colors_with_editor_theme=false 38 | -------------------------------------------------------------------------------- /addons/script_spliter/context/icons/split_cplus.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 23 | 41 | 49 | 50 | 52 | 54 | 55 | split-screen 57 | 61 | 65 | 74 | 83 | 85 | 86 | 88 | split-screen 89 | 90 | 91 | 92 | 93 | -------------------------------------------------------------------------------- /addons/script_spliter/context/icons/split_cplus.svg.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://bvyjqo1dus1xu" 6 | path="res://.godot/imported/split_cplus.svg-5f233626ec643447e303aa2d98ed8d14.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://addons/script_spliter/context/icons/split_cplus.svg" 14 | dest_files=["res://.godot/imported/split_cplus.svg-5f233626ec643447e303aa2d98ed8d14.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | svg/scale=8.0 36 | editor/scale_with_editor_scale=false 37 | editor/convert_colors_with_editor_theme=false 38 | -------------------------------------------------------------------------------- /addons/script_spliter/context/icons/split_rminus.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 23 | 41 | 49 | 50 | 52 | 54 | 55 | split-screen 57 | 61 | 65 | 74 | 76 | 77 | 79 | split-screen 80 | 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /addons/script_spliter/context/icons/split_rminus.svg.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://bvjk4po8w2m2j" 6 | path="res://.godot/imported/split_rminus.svg-6f9fc75a64032d6fe5bdcc9bc3bf399d.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://addons/script_spliter/context/icons/split_rminus.svg" 14 | dest_files=["res://.godot/imported/split_rminus.svg-6f9fc75a64032d6fe5bdcc9bc3bf399d.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | svg/scale=8.0 36 | editor/scale_with_editor_scale=false 37 | editor/convert_colors_with_editor_theme=false 38 | -------------------------------------------------------------------------------- /addons/script_spliter/context/icons/split_rplus.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 23 | 41 | 49 | 50 | 52 | 54 | 55 | split-screen 57 | 61 | 65 | 74 | 83 | 85 | 86 | 88 | split-screen 89 | 90 | 91 | 92 | 93 | -------------------------------------------------------------------------------- /addons/script_spliter/context/icons/split_rplus.svg.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://1sqajw0mikdj" 6 | path="res://.godot/imported/split_rplus.svg-a26b8d20ca41f0ec060d5e021092eced.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://addons/script_spliter/context/icons/split_rplus.svg" 14 | dest_files=["res://.godot/imported/split_rplus.svg-a26b8d20ca41f0ec060d5e021092eced.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | svg/scale=8.0 36 | editor/scale_with_editor_scale=false 37 | editor/convert_colors_with_editor_theme=false 38 | -------------------------------------------------------------------------------- /addons/script_spliter/context/menu_tool.gd: -------------------------------------------------------------------------------- 1 | @tool 2 | extends Window 3 | # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # 4 | # Script Spliter 5 | # https://github.com/CodeNameTwister/Script-Spliter 6 | # 7 | # Script Spliter addon for godot 4 8 | # author: "Twister" 9 | # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # 10 | @export var _container : Node 11 | @export var _custom_options : Control 12 | 13 | var _plugin : Object = null 14 | 15 | func _init_1() -> void: 16 | if _container and _plugin: 17 | var columns : int = _plugin.call(&"get_split_columns") 18 | var rows : int = _plugin.call(&"get_split_rows") 19 | set_split_value(columns, rows) 20 | 21 | func _ready() -> void: 22 | if _custom_options: 23 | _custom_options.visible = false 24 | 25 | if !visibility_changed.is_connected(_on_visibility_change): 26 | visibility_changed.connect(_on_visibility_change) 27 | 28 | _init_1() 29 | 30 | func set_plugin(current_plugin : Object) -> void: 31 | _plugin = current_plugin 32 | 33 | func _on_visibility_change() -> void: 34 | if !visible: return 35 | if !_plugin: 36 | return 37 | 38 | _init_1() 39 | 40 | func enable_options() -> void: 41 | var custom : CheckBox = _container.get_child(_container.get_child_count() - 1) 42 | for c : Node in _container.get_children(): 43 | if c is CheckBox: 44 | c.button_pressed = false 45 | 46 | _custom_options.visible = true 47 | custom.button_pressed = true 48 | 49 | func set_split_value(columns : int, rows : int) -> void: 50 | var current : Node = null 51 | var custom : CheckBox = _container.get_child(_container.get_child_count() - 1) 52 | for c : Node in _container.get_children(): 53 | if c is CheckBox: 54 | if c.columns == columns and c.rows == rows: 55 | current = c 56 | c.button_pressed = true 57 | continue 58 | c.button_pressed = false 59 | 60 | if columns < 2 and rows < 2: 61 | current = _container.get_child(0) 62 | if current is CheckBox: 63 | current.button_pressed = true 64 | else: 65 | current = null 66 | 67 | _custom_options.visible = current == null 68 | custom.button_pressed = _custom_options.visible 69 | _custom_options.set_values(columns, rows) 70 | 71 | func _on_ok_pressed() -> void: 72 | var columns : int = _custom_options.get_columns_value() 73 | var rows : int = _custom_options.get_rows_value() 74 | if !_plugin: 75 | push_error("[ERROR] Can not set split type!") 76 | else: 77 | _plugin.call(&"set_type_split", columns, rows) 78 | hide() 79 | 80 | func _on_cancel_pressed() -> void: 81 | hide() 82 | -------------------------------------------------------------------------------- /addons/script_spliter/context/menu_tool.gd.uid: -------------------------------------------------------------------------------- 1 | uid://4wllvh127dwh 2 | -------------------------------------------------------------------------------- /addons/script_spliter/context/menu_tool.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=15 format=3 uid="uid://csu7djr8m1mgb"] 2 | 3 | [ext_resource type="Script" uid="uid://4wllvh127dwh" path="res://addons/script_spliter/context/menu_tool.gd" id="1_00j1l"] 4 | [ext_resource type="Texture2D" uid="uid://tgaoyybc2iji" path="res://addons/script_spliter/assets/github_CodeNameTwister.png" id="2_bi1if"] 5 | [ext_resource type="Texture2D" uid="uid://dmvcijsjhb5pc" path="res://addons/script_spliter/context/icons/sp_disable.png" id="2_le2a0"] 6 | [ext_resource type="Script" uid="uid://bobw4q6hrbbox" path="res://addons/script_spliter/context/split_type_button.gd" id="3_h7rbp"] 7 | [ext_resource type="Texture2D" uid="uid://c1kjfqirfexvp" path="res://addons/script_spliter/context/icons/sp_2H.png" id="3_o7fne"] 8 | [ext_resource type="Texture2D" uid="uid://d1r72ixdgbwl6" path="res://addons/script_spliter/context/icons/sp_2V.png" id="4_js2dr"] 9 | [ext_resource type="Texture2D" uid="uid://32xnl4cu46pj" path="res://addons/script_spliter/context/icons/sp_3H.png" id="5_h32ac"] 10 | [ext_resource type="Texture2D" uid="uid://b4cmfno0ixqnm" path="res://addons/script_spliter/context/icons/sp_3V.png" id="6_h7rbp"] 11 | [ext_resource type="Texture2D" uid="uid://bf2bjkoock7re" path="res://addons/script_spliter/context/icons/sp_4S.png" id="7_bi1if"] 12 | [ext_resource type="Texture2D" uid="uid://bdxvp5dyj8y0r" path="res://addons/script_spliter/context/icons/sp_custom.png" id="10_0n25h"] 13 | [ext_resource type="Script" uid="uid://y3jbguu2nw5c" path="res://addons/script_spliter/context/custom_options.gd" id="11_2o3ku"] 14 | 15 | [sub_resource type="LabelSettings" id="LabelSettings_00j1l"] 16 | font_size = 28 17 | outline_size = 4 18 | outline_color = Color(0, 0, 0, 1) 19 | 20 | [sub_resource type="LabelSettings" id="LabelSettings_2o3ku"] 21 | font_size = 12 22 | font_color = Color(1, 1, 1, 0.4) 23 | 24 | [sub_resource type="LabelSettings" id="LabelSettings_0n25h"] 25 | font_size = 12 26 | 27 | [node name="MenuTool" type="PopupPanel" node_paths=PackedStringArray("_container", "_custom_options")] 28 | title = "Script Splitter Menu" 29 | position = Vector2i(0, 36) 30 | size = Vector2i(602, 382) 31 | visible = true 32 | script = ExtResource("1_00j1l") 33 | _container = NodePath("MarginContainer/MenContainer/Body") 34 | _custom_options = NodePath("MarginContainer/MenContainer/COptions") 35 | 36 | [node name="BG" type="ColorRect" parent="."] 37 | anchors_preset = 15 38 | anchor_right = 1.0 39 | anchor_bottom = 1.0 40 | offset_left = 4.0 41 | offset_top = 4.0 42 | offset_right = -4.0 43 | offset_bottom = -4.0 44 | grow_horizontal = 2 45 | grow_vertical = 2 46 | color = Color(0.249011, 0.114569, 0.435571, 1) 47 | 48 | [node name="BGTX" type="TextureRect" parent="."] 49 | modulate = Color(1, 1, 1, 0.34902) 50 | anchors_preset = 15 51 | anchor_right = 1.0 52 | anchor_bottom = 1.0 53 | offset_left = 4.0 54 | offset_top = 4.0 55 | offset_right = -4.0 56 | offset_bottom = -4.0 57 | grow_horizontal = 2 58 | grow_vertical = 2 59 | texture = ExtResource("2_bi1if") 60 | stretch_mode = 3 61 | 62 | [node name="MarginContainer" type="MarginContainer" parent="."] 63 | anchors_preset = 15 64 | anchor_right = 1.0 65 | anchor_bottom = 1.0 66 | offset_left = 4.0 67 | offset_top = 4.0 68 | offset_right = -4.0 69 | offset_bottom = -4.0 70 | grow_horizontal = 2 71 | grow_vertical = 2 72 | theme_override_constants/margin_left = 4 73 | theme_override_constants/margin_top = 4 74 | theme_override_constants/margin_right = 4 75 | theme_override_constants/margin_bottom = 4 76 | 77 | [node name="MenContainer" type="VBoxContainer" parent="MarginContainer"] 78 | layout_mode = 2 79 | 80 | [node name="PanelContainer2" type="PanelContainer" parent="MarginContainer/MenContainer"] 81 | layout_mode = 2 82 | 83 | [node name="Tittle" type="Label" parent="MarginContainer/MenContainer/PanelContainer2"] 84 | layout_mode = 2 85 | text = "Menu Split Selection" 86 | label_settings = SubResource("LabelSettings_00j1l") 87 | horizontal_alignment = 1 88 | uppercase = true 89 | 90 | [node name="Label" type="Label" parent="MarginContainer/MenContainer"] 91 | visible = false 92 | layout_mode = 2 93 | text = "Version 0.2 94 | Rows are created based on the maximum number of columns reached. 95 | Example: If you want two vertical scripts, you must define a maximum of one column." 96 | label_settings = SubResource("LabelSettings_2o3ku") 97 | horizontal_alignment = 1 98 | vertical_alignment = 1 99 | 100 | [node name="Body" type="GridContainer" parent="MarginContainer/MenContainer"] 101 | layout_mode = 2 102 | size_flags_horizontal = 4 103 | size_flags_vertical = 6 104 | theme_override_constants/h_separation = 8 105 | theme_override_constants/v_separation = 8 106 | columns = 2 107 | 108 | [node name="splited_off" type="CheckBox" parent="MarginContainer/MenContainer/Body"] 109 | layout_mode = 2 110 | tooltip_text = "Disabled Splited" 111 | button_pressed = true 112 | text = "Disabled" 113 | icon = ExtResource("2_le2a0") 114 | script = ExtResource("3_h7rbp") 115 | 116 | [node name="splited_two_horizontal" type="CheckBox" parent="MarginContainer/MenContainer/Body"] 117 | layout_mode = 2 118 | tooltip_text = "Two Horizontal Splited" 119 | text = "Two Horizontal" 120 | icon = ExtResource("3_o7fne") 121 | script = ExtResource("3_h7rbp") 122 | columns = 2 123 | rows = 1 124 | 125 | [node name="splited_two_vertical" type="CheckBox" parent="MarginContainer/MenContainer/Body"] 126 | layout_mode = 2 127 | tooltip_text = "Two Vertical Splited" 128 | text = "Two Vertical" 129 | icon = ExtResource("4_js2dr") 130 | script = ExtResource("3_h7rbp") 131 | columns = 1 132 | rows = 2 133 | 134 | [node name="splited_three_horizontal" type="CheckBox" parent="MarginContainer/MenContainer/Body"] 135 | layout_mode = 2 136 | tooltip_text = "Three Horizontal Splited" 137 | text = "Three Horizontal" 138 | icon = ExtResource("5_h32ac") 139 | script = ExtResource("3_h7rbp") 140 | columns = 3 141 | rows = 1 142 | 143 | [node name="splited_three_vertical" type="CheckBox" parent="MarginContainer/MenContainer/Body"] 144 | layout_mode = 2 145 | tooltip_text = "Three Vertical Splited" 146 | text = "Three Vertical" 147 | icon = ExtResource("6_h7rbp") 148 | script = ExtResource("3_h7rbp") 149 | columns = 1 150 | rows = 3 151 | 152 | [node name="splited_four_square" type="CheckBox" parent="MarginContainer/MenContainer/Body"] 153 | layout_mode = 2 154 | tooltip_text = "Square Splited" 155 | text = "Four Squared" 156 | icon = ExtResource("7_bi1if") 157 | script = ExtResource("3_h7rbp") 158 | columns = 2 159 | rows = 2 160 | 161 | [node name="CheckBox" type="CheckBox" parent="MarginContainer/MenContainer/Body"] 162 | layout_mode = 2 163 | text = "Custom Split" 164 | icon = ExtResource("10_0n25h") 165 | script = ExtResource("3_h7rbp") 166 | is_custom = true 167 | 168 | [node name="COptions" type="VBoxContainer" parent="MarginContainer/MenContainer" node_paths=PackedStringArray("columns", "rows")] 169 | visible = false 170 | layout_mode = 2 171 | script = ExtResource("11_2o3ku") 172 | columns = NodePath("ValueOptions/ColumnsValue") 173 | rows = NodePath("ValueOptions/RowsValue") 174 | 175 | [node name="Label" type="Label" parent="MarginContainer/MenContainer/COptions"] 176 | layout_mode = 2 177 | text = "Custom Split Options" 178 | label_settings = SubResource("LabelSettings_0n25h") 179 | horizontal_alignment = 1 180 | 181 | [node name="TextureRect" type="TextureRect" parent="MarginContainer/MenContainer/COptions"] 182 | layout_mode = 2 183 | texture = ExtResource("10_0n25h") 184 | expand_mode = 1 185 | stretch_mode = 5 186 | 187 | [node name="ValueOptions" type="HBoxContainer" parent="MarginContainer/MenContainer/COptions"] 188 | layout_mode = 2 189 | 190 | [node name="ColumnsValue" type="SpinBox" parent="MarginContainer/MenContainer/COptions/ValueOptions"] 191 | layout_mode = 2 192 | size_flags_horizontal = 3 193 | min_value = 1.0 194 | max_value = 30.0 195 | value = 1.0 196 | alignment = 1 197 | prefix = "Columns" 198 | 199 | [node name="RowsValue" type="SpinBox" parent="MarginContainer/MenContainer/COptions/ValueOptions"] 200 | layout_mode = 2 201 | size_flags_horizontal = 3 202 | min_value = 1.0 203 | max_value = 30.0 204 | value = 1.0 205 | alignment = 1 206 | prefix = "Rows" 207 | 208 | [node name="Separator" type="HSeparator" parent="MarginContainer/MenContainer"] 209 | layout_mode = 2 210 | size_flags_vertical = 8 211 | 212 | [node name="Footer" type="HBoxContainer" parent="MarginContainer/MenContainer"] 213 | layout_mode = 2 214 | 215 | [node name="OK" type="Button" parent="MarginContainer/MenContainer/Footer"] 216 | layout_mode = 2 217 | size_flags_horizontal = 3 218 | text = "Accept" 219 | 220 | [node name="Cancel" type="Button" parent="MarginContainer/MenContainer/Footer"] 221 | layout_mode = 2 222 | size_flags_horizontal = 3 223 | text = "Exit" 224 | 225 | [connection signal="pressed" from="MarginContainer/MenContainer/Footer/OK" to="." method="_on_ok_pressed"] 226 | [connection signal="pressed" from="MarginContainer/MenContainer/Footer/Cancel" to="." method="_on_cancel_pressed"] 227 | -------------------------------------------------------------------------------- /addons/script_spliter/context/panel_preview.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene format=3 uid="uid://di83u5ac2jww6"] 2 | 3 | [node name="PanelPreview" type="ColorRect"] 4 | anchors_preset = 15 5 | anchor_right = 1.0 6 | anchor_bottom = 1.0 7 | grow_horizontal = 2 8 | grow_vertical = 2 9 | color = Color(1.27546e-06, 0.644043, 0.17534, 0.4) 10 | 11 | [node name="Label" type="Label" parent="."] 12 | layout_mode = 1 13 | anchors_preset = 8 14 | anchor_left = 0.5 15 | anchor_top = 0.5 16 | anchor_right = 0.5 17 | anchor_bottom = 0.5 18 | offset_left = -44.5 19 | offset_top = -11.5 20 | offset_right = 44.5 21 | offset_bottom = 11.5 22 | grow_horizontal = 2 23 | grow_vertical = 2 24 | text = "DROP HERE" 25 | horizontal_alignment = 1 26 | vertical_alignment = 1 27 | -------------------------------------------------------------------------------- /addons/script_spliter/context/split_type_button.gd: -------------------------------------------------------------------------------- 1 | @tool 2 | extends CheckBox 3 | # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # 4 | # Script Spliter 5 | # https://github.com/CodeNameTwister/Script-Spliter 6 | # 7 | # Script Spliter addon for godot 4 8 | # author: "Twister" 9 | # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # 10 | 11 | ## V0.2 Used now as max columns by row!, 0 as infinite horizontal. 12 | @export var columns : int = 0 13 | ## V0.2: Used now only as extra container if row > 1 14 | @export var rows : int = 0 15 | 16 | @export var is_custom : bool = false 17 | 18 | func _pressed() -> void: 19 | if is_custom: 20 | if owner.has_method(&"enable_options"): 21 | owner.call(&"enable_options") 22 | else: 23 | if owner.has_method(&"set_split_value"): 24 | owner.call(&"set_split_value", columns, rows) 25 | -------------------------------------------------------------------------------- /addons/script_spliter/context/split_type_button.gd.uid: -------------------------------------------------------------------------------- 1 | uid://bobw4q6hrbbox 2 | -------------------------------------------------------------------------------- /addons/script_spliter/context/tab_preview.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=2 format=3 uid="uid://od0wse8oyuwn"] 2 | 3 | [ext_resource type="Texture2D" uid="uid://ljki8k8ckjtt" path="res://addons/script_spliter/assets/File.svg" id="1_obfxw"] 4 | 5 | [node name="preview_tab" type="Control"] 6 | layout_mode = 3 7 | anchors_preset = 0 8 | 9 | [node name="TabPreview" type="TextureRect" parent="."] 10 | layout_mode = 1 11 | anchors_preset = 15 12 | anchor_right = 1.0 13 | anchor_bottom = 1.0 14 | offset_left = -8.0 15 | offset_top = -8.0 16 | offset_right = -8.0 17 | offset_bottom = -8.0 18 | grow_horizontal = 2 19 | grow_vertical = 2 20 | texture = ExtResource("1_obfxw") 21 | expand_mode = 1 22 | stretch_mode = 2 23 | 24 | [node name="Label" type="Label" parent="."] 25 | layout_mode = 1 26 | anchors_preset = 5 27 | anchor_left = 0.5 28 | anchor_right = 0.5 29 | offset_left = -20.0 30 | offset_top = 4.0 31 | offset_right = 20.0 32 | offset_bottom = 27.0 33 | grow_horizontal = 2 34 | text = "FILE" 35 | horizontal_alignment = 1 36 | vertical_alignment = 1 37 | -------------------------------------------------------------------------------- /addons/script_spliter/core/DDContainer.gd: -------------------------------------------------------------------------------- 1 | @tool 2 | extends TabContainer 3 | # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # 4 | # Script Spliter 5 | # https://github.com/CodeNameTwister/Script-Spliter 6 | # 7 | # Script Spliter addon for godot 4 8 | # author: "Twister" 9 | # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # 10 | 11 | @warning_ignore("unused_signal") 12 | signal on_dragging(e : Control) 13 | signal out_dragging(e : Control) 14 | 15 | const DDTAB : Script = preload("res://addons/script_spliter/core/DDTAB.gd") 16 | 17 | var _buffer_editors : Array[Object] = [] 18 | 19 | #static var _tab_focus : StyleBox = null 20 | #static var _tab_disabled : StyleBox = null 21 | #static var _tab_selected : StyleBox = null 22 | #static var _tab_hovered : StyleBox = null 23 | #static var _tab_unselected : StyleBox = null 24 | 25 | func _config_tab(_tab : StyleBox) -> void: 26 | if _tab is StyleBoxFlat: 27 | _tab.skew.x = 0.5 28 | _tab.border_color = Color.AQUA 29 | #_tab.border_width_left = 0.0 30 | #_tab.border_width_right = 0.0 31 | #_tab.border_width_top = 0.0 32 | #_tab.border_width_bottom = 0.1 33 | 34 | func _ready() -> void: 35 | pass 36 | #var root : Control = EditorInterface.get_base_control() 37 | #if root: 38 | #if _tab_focus == null: 39 | #_tab_focus = root.get_theme_stylebox(&"panel", &"tab_focus") 40 | #if _tab_focus is StyleBoxFlat: 41 | #_tab_focus = _tab_focus.duplicate() 42 | #_config_tab(_tab_focus) 43 | #if _tab_disabled == null: 44 | #_tab_disabled = root.get_theme_stylebox(&"panel", &"tab_disabled") 45 | #if _tab_disabled is StyleBoxFlat: 46 | #_tab_disabled = _tab_disabled.duplicate() 47 | #_config_tab(_tab_disabled) 48 | #if _tab_selected == null: 49 | #_tab_selected = root.get_theme_stylebox(&"panel", &"tab_selected") 50 | #if _tab_selected is StyleBoxFlat: 51 | #_tab_selected = _tab_selected.duplicate() 52 | #_config_tab(_tab_selected) 53 | #if _tab_hovered == null: 54 | #_tab_hovered = root.get_theme_stylebox(&"panel", &"tab_hovered") 55 | #if _tab_hovered is StyleBoxFlat: 56 | #_tab_hovered = _tab_hovered.duplicate() 57 | #_config_tab(_tab_hovered) 58 | #if _tab_unselected == null: 59 | #_tab_unselected = root.get_theme_stylebox(&"panel", &"tab_unselected") 60 | #if _tab_unselected is StyleBoxFlat: 61 | #_tab_unselected = _tab_unselected.duplicate() 62 | #_config_tab(_tab_unselected) 63 | #set(&"theme_override_styles/tab_focus", _tab_focus) 64 | #set(&"theme_override_styles/tab_disabled", _tab_disabled) 65 | #set(&"theme_override_styles/tab_selected", _tab_selected) 66 | #set(&"theme_override_styles/tab_hovered", _tab_hovered) 67 | #set(&"theme_override_styles/tab_unselected", _tab_unselected) 68 | 69 | func reset() -> void: 70 | for x : Node in get_children(true): 71 | if x is TabBar: 72 | if x.get_script() == DDTAB: 73 | x.reset() 74 | 75 | func clear_editors() -> void: 76 | _buffer_editors.clear() 77 | 78 | func add_editor(o : Object, limit : int) -> Object: 79 | if is_instance_valid(o): 80 | if limit > 0: 81 | var i : int = _buffer_editors.find(o) 82 | if i > -1: 83 | _buffer_editors.remove_at(i) 84 | _buffer_editors.append(o) 85 | if limit > -1: 86 | while _buffer_editors.size() > limit: 87 | _buffer_editors.remove_at(0) 88 | return o 89 | 90 | func remove_editor(o : Object) -> void: 91 | _buffer_editors.erase(o) 92 | 93 | func backward_editor() -> Object: 94 | if _buffer_editors.size() > 1: 95 | var o : Variant = _buffer_editors.pop_back() 96 | while !is_instance_valid(o) and _buffer_editors.size() > 0: 97 | o = _buffer_editors.pop_back() 98 | if is_instance_valid(o): 99 | _buffer_editors.push_front(o) 100 | return o 101 | return null 102 | 103 | func forward_editor() -> Object: 104 | if _buffer_editors.size() > 1: 105 | var o : Object = _buffer_editors.pop_front() 106 | while !is_instance_valid(o) and _buffer_editors.size() > 0: 107 | o = _buffer_editors.pop_front() 108 | if is_instance_valid(o): 109 | _buffer_editors.push_back(o) 110 | return o 111 | return null 112 | 113 | 114 | func _on_child(n : Node) -> void: 115 | if n is TabBar: 116 | if n.get_script() != DDTAB: 117 | n.set_script(DDTAB) 118 | 119 | if !n.on_start_drag.is_connected(_on_start_drag): 120 | n.on_start_drag.connect(_on_start_drag) 121 | if !n.on_stop_drag.is_connected(_on_stop_drag): 122 | n.on_stop_drag.connect(_on_stop_drag) 123 | 124 | func _out_child(n : Node) -> void: 125 | if n is TabBar: 126 | 127 | if n.on_start_drag.is_connected(_on_start_drag): 128 | n.on_start_drag.disconnect(_on_start_drag) 129 | if n.on_stop_drag.is_connected(_on_stop_drag): 130 | n.on_stop_drag.disconnect(_on_stop_drag) 131 | if n.get_script() == DDTAB: 132 | n.set_script(null) 133 | 134 | func _on_stop_drag(tab : TabBar) -> void: 135 | out_dragging.emit(tab) 136 | 137 | func _on_start_drag(tab : TabBar) -> void: 138 | on_dragging.emit(tab) 139 | # 140 | func _init() -> void: 141 | child_entered_tree.connect(_on_child) 142 | child_exiting_tree.connect(_out_child) 143 | -------------------------------------------------------------------------------- /addons/script_spliter/core/DDContainer.gd.uid: -------------------------------------------------------------------------------- 1 | uid://chk1nts3d41v8 2 | -------------------------------------------------------------------------------- /addons/script_spliter/core/DDItem.gd: -------------------------------------------------------------------------------- 1 | @tool 2 | extends ItemList 3 | # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # 4 | # Script Spliter 5 | # https://github.com/CodeNameTwister/Script-Spliter 6 | # 7 | # Script Spliter addon for godot 4 8 | # author: "Twister" 9 | # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # 10 | 11 | 12 | signal on_start_drag(t : ItemList) 13 | signal on_stop_drag(t : ItemList) 14 | 15 | const PREVIEW : PackedScene = preload("res://addons/script_spliter/context/tab_preview.tscn") 16 | 17 | var is_drag : bool = false: 18 | set(e): 19 | is_drag = e 20 | if is_drag: 21 | Input.set_mouse_mode(Input.MOUSE_MODE_HIDDEN) 22 | else: 23 | Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE) 24 | 25 | var _fms : float = 0.0 26 | 27 | func _init() -> void: 28 | if is_node_ready(): 29 | _ready() 30 | 31 | func _ready() -> void: 32 | set_process(false) 33 | setup() 34 | 35 | func _process(delta: float) -> void: 36 | _fms += delta 37 | if _fms > 0.24: 38 | if is_drag: 39 | if !Input.is_mouse_button_pressed(MOUSE_BUTTON_LEFT): 40 | set_process(false) 41 | is_drag = false 42 | on_stop_drag.emit(self) 43 | else: 44 | on_start_drag.emit(self) 45 | is_drag = true 46 | 47 | func setup() -> void: 48 | if !gui_input.is_connected(_on_input): 49 | gui_input.connect(_on_input) 50 | 51 | func _on_input(e : InputEvent) -> void: 52 | if e is InputEventMouseButton: 53 | if e.button_index == 1: 54 | if e.pressed: 55 | _fms = 0.0 56 | is_drag = false 57 | set_process(true) 58 | else: 59 | set_process(false) 60 | if _fms >= 0.24: 61 | on_stop_drag.emit(self) 62 | -------------------------------------------------------------------------------- /addons/script_spliter/core/DDItem.gd.uid: -------------------------------------------------------------------------------- 1 | uid://ci8kq81lonwua 2 | -------------------------------------------------------------------------------- /addons/script_spliter/core/DDTAB.gd: -------------------------------------------------------------------------------- 1 | @tool 2 | extends TabBar 3 | # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # 4 | # Script Spliter 5 | # https://github.com/CodeNameTwister/Script-Spliter 6 | # 7 | # Script Spliter addon for godot 4 8 | # author: "Twister" 9 | # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # 10 | 11 | 12 | signal on_start_drag(t : TabBar) 13 | signal on_stop_drag(t : TabBar) 14 | 15 | const PREVIEW : PackedScene = preload("res://addons/script_spliter/context/tab_preview.tscn") 16 | 17 | var is_drag : bool = false: 18 | set(e): 19 | is_drag = e 20 | if is_drag: 21 | Input.set_mouse_mode(Input.MOUSE_MODE_HIDDEN) 22 | else: 23 | Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE) 24 | 25 | var _fms : float = 0.0 26 | 27 | func reset() -> void: 28 | if is_drag: 29 | set_process(false) 30 | is_drag = false 31 | if is_inside_tree(): 32 | on_stop_drag.emit(null) 33 | 34 | func _init() -> void: 35 | if is_node_ready(): 36 | _ready() 37 | 38 | func _ready() -> void: 39 | set_process(false) 40 | setup() 41 | 42 | func _process(delta: float) -> void: 43 | _fms += delta 44 | if _fms > 0.24: 45 | if is_drag: 46 | if !Input.is_mouse_button_pressed(MOUSE_BUTTON_LEFT): 47 | set_process(false) 48 | is_drag = false 49 | on_stop_drag.emit(self) 50 | else: 51 | on_start_drag.emit(self) 52 | is_drag = true 53 | 54 | func setup() -> void: 55 | if !gui_input.is_connected(_on_input): 56 | gui_input.connect(_on_input) 57 | 58 | func _on_input(e : InputEvent) -> void: 59 | if e is InputEventMouseButton: 60 | if e.button_index == 1: 61 | is_drag = false 62 | if e.pressed: 63 | _fms = 0.0 64 | set_process(true) 65 | else: 66 | set_process(false) 67 | if _fms >= 0.24: 68 | on_stop_drag.emit(self) 69 | -------------------------------------------------------------------------------- /addons/script_spliter/core/DDTAB.gd.uid: -------------------------------------------------------------------------------- 1 | uid://cma5va5lbj5it 2 | -------------------------------------------------------------------------------- /addons/script_spliter/core/DaemonChaser.gd: -------------------------------------------------------------------------------- 1 | @tool 2 | extends Node 3 | # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # 4 | # Script Spliter 5 | # https://github.com/CodeNameTwister/Script-Spliter 6 | # 7 | # Script Spliter addon for godot 4 8 | # author: "Twister" 9 | # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # 10 | var callback : Callable 11 | var end_callback : Callable 12 | var index : int = 0 13 | var back_to : int = 0 14 | var buffer : Dictionary 15 | 16 | func set_current_index(current : int) -> void: 17 | back_to = current 18 | 19 | func run(new_callback : Callable, new_end_callback : Callable) -> void: 20 | callback = new_callback 21 | end_callback = new_end_callback 22 | index = 0 23 | set_process(true) 24 | 25 | func _ready() -> void: 26 | set_process(false) 27 | 28 | func _back() -> void: 29 | if callback.is_valid(): 30 | callback.call(back_to) 31 | 32 | func _process(__: float) -> void: 33 | if !callback.is_valid() or !callback.call(index): 34 | set_process(false) 35 | _back() 36 | if end_callback.is_valid(): 37 | end_callback.call(buffer) 38 | buffer = {} 39 | return 40 | index += 1 41 | -------------------------------------------------------------------------------- /addons/script_spliter/core/DaemonChaser.gd.uid: -------------------------------------------------------------------------------- 1 | uid://dbiugbnirptj8 2 | -------------------------------------------------------------------------------- /addons/script_spliter/core/EditorContainer.gd: -------------------------------------------------------------------------------- 1 | @tool 2 | # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # 3 | # Script Spliter 4 | # https://github.com/CodeNameTwister/Script-Spliter 5 | # 6 | # Script Spliter addon for godot 4 7 | # author: "Twister" 8 | # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # 9 | 10 | extends "res://addons/script_spliter/core/ui/multi_split_container.gd" 11 | 12 | const PREVIEW : PackedScene = preload("res://addons/script_spliter/context/panel_preview.tscn") 13 | 14 | var preview : Control = null 15 | 16 | func get_total_containers() -> int: 17 | var total : int = 0 18 | for x : Node in get_children(): 19 | if x is SplitContainerItem: 20 | if x.get_child_count() > 0: 21 | total += 1 22 | return total 23 | 24 | func _notification(what: int) -> void: 25 | if what == NOTIFICATION_PREDELETE: 26 | if is_instance_valid(preview) and !preview.is_queued_for_deletion(): 27 | preview.queue_free() 28 | 29 | func make_split_container_item() -> Control: 30 | var x : SplitContainerItem = SplitContainerItem.new() 31 | x.size_flags_horizontal = Control.SIZE_FILL 32 | x.size_flags_vertical = Control.SIZE_FILL 33 | x.custom_minimum_size = Vector2.ZERO 34 | x.clip_contents = true 35 | x.visible = false 36 | return x 37 | 38 | func has_items() -> bool: 39 | return get_child_count() > 0 40 | 41 | func is_split_container_item(x : Object) -> bool: 42 | return x is SplitContainerItem 43 | 44 | -------------------------------------------------------------------------------- /addons/script_spliter/core/EditorContainer.gd.uid: -------------------------------------------------------------------------------- 1 | uid://ds3bvm7nwsq2s 2 | -------------------------------------------------------------------------------- /addons/script_spliter/core/builder.gd.uid: -------------------------------------------------------------------------------- 1 | uid://dpje5up34xbux 2 | -------------------------------------------------------------------------------- /addons/script_spliter/core/ui/dd.gd: -------------------------------------------------------------------------------- 1 | @tool 2 | extends Control 3 | # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # 4 | # Script Spliter 5 | # https://github.com/CodeNameTwister/Script-Spliter 6 | # 7 | # Script Spliter addon for godot 4 8 | # author: "Twister" 9 | # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # 10 | @export var lbl : Control 11 | 12 | var _0x0001 : float = 0.0 13 | var _0x0002 : float= 0.5 14 | 15 | func _ready() -> void: 16 | if !is_inside_tree(): 17 | set_process(false) 18 | 19 | func _process(delta: float) -> void: 20 | if !visible: 21 | return 22 | var p : Control = get_parent() 23 | if !p: 24 | return 25 | _0x0001 += delta * 2.0 26 | if _0x0001 >= 1.0: 27 | _0x0001 = 0.0 28 | if _0x0002 == 1.0: 29 | _0x0002 = 0.5 30 | else: 31 | _0x0002 = 1.0 32 | modulate.a = lerp(modulate.a, _0x0002, _0x0001) 33 | lbl.pivot_offset = (lbl.size + Vector2.ONE) / 2.0 34 | lbl.scale = lerp(lbl.scale, Vector2.ONE * _0x0002 , _0x0001 * 0.24) 35 | 36 | func _enter_tree() -> void: 37 | set_process(true) 38 | 39 | func _exit_tree() -> void: 40 | set_process(false) 41 | -------------------------------------------------------------------------------- /addons/script_spliter/core/ui/dd.gd.uid: -------------------------------------------------------------------------------- 1 | uid://prv0v0r500g6 2 | -------------------------------------------------------------------------------- /addons/script_spliter/core/ui/dd.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=3 format=3 uid="uid://bd4fb42jjkgr0"] 2 | 3 | [ext_resource type="Script" uid="uid://prv0v0r500g6" path="res://addons/script_spliter/core/ui/dd.gd" id="1_1ryr1"] 4 | [ext_resource type="Texture2D" uid="uid://cxds5tr6aq5v3" path="res://addons/script_spliter/assets/dd.png" id="2_pid5b"] 5 | 6 | [node name="Dd" type="ColorRect" node_paths=PackedStringArray("lbl")] 7 | modulate = Color(0.8, 0.8, 0.8, 0.501533) 8 | self_modulate = Color(1, 1, 1, 0.4) 9 | size_flags_horizontal = 4 10 | size_flags_vertical = 4 11 | tooltip_text = "Drop the current dragged tab for change window!" 12 | color = Color(1.3236e-07, 0.348188, 0.0242278, 1) 13 | script = ExtResource("1_1ryr1") 14 | lbl = NodePath("Label") 15 | 16 | [node name="Label" type="TextureRect" parent="."] 17 | show_behind_parent = true 18 | layout_mode = 1 19 | anchors_preset = 15 20 | anchor_right = 1.0 21 | anchor_bottom = 1.0 22 | grow_horizontal = 2 23 | grow_vertical = 2 24 | size_flags_horizontal = 4 25 | size_flags_vertical = 4 26 | texture = ExtResource("2_pid5b") 27 | stretch_mode = 3 28 | -------------------------------------------------------------------------------- /addons/script_spliter/core/ui/icon/MultiSpliter.svg: -------------------------------------------------------------------------------- 1 | 2 | 15 | 17 | 26 | 34 | 35 | 43 | 44 | -------------------------------------------------------------------------------- /addons/script_spliter/core/ui/icon/MultiSpliter.svg.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://bslfeut6hh5yo" 6 | path="res://.godot/imported/MultiSpliter.svg-ba196a92a18cd9aeefd856cd4e65a016.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://addons/script_spliter/core/ui/icon/MultiSpliter.svg" 14 | dest_files=["res://.godot/imported/MultiSpliter.svg-ba196a92a18cd9aeefd856cd4e65a016.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | svg/scale=8.0 36 | editor/scale_with_editor_scale=false 37 | editor/convert_colors_with_editor_theme=false 38 | -------------------------------------------------------------------------------- /addons/script_spliter/core/ui/icon/MultiSpliterButton.svg: -------------------------------------------------------------------------------- 1 | 2 | 16 | 18 | 36 | 44 | 45 | 53 | 59 | 65 | 71 | 77 | 83 | 89 | 90 | -------------------------------------------------------------------------------- /addons/script_spliter/core/ui/icon/MultiSpliterButton.svg.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://151hs5hrois7" 6 | path="res://.godot/imported/MultiSpliterButton.svg-f2ca8d7d3b41369a9fe8ce79d9fcb1df.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://addons/script_spliter/core/ui/icon/MultiSpliterButton.svg" 14 | dest_files=["res://.godot/imported/MultiSpliterButton.svg-f2ca8d7d3b41369a9fe8ce79d9fcb1df.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | svg/scale=8.0 36 | editor/scale_with_editor_scale=false 37 | editor/convert_colors_with_editor_theme=false 38 | -------------------------------------------------------------------------------- /addons/script_spliter/core/ui/icon/MultiSpliterItem.svg: -------------------------------------------------------------------------------- 1 | 2 | 15 | 17 | 26 | 34 | 35 | 43 | 49 | 54 | 59 | 64 | 69 | 70 | -------------------------------------------------------------------------------- /addons/script_spliter/core/ui/icon/MultiSpliterItem.svg.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://bd3tnqhyiny6o" 6 | path="res://.godot/imported/MultiSpliterItem.svg-73b989ef018da2301c61b6f59ef99931.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://addons/script_spliter/core/ui/icon/MultiSpliterItem.svg" 14 | dest_files=["res://.godot/imported/MultiSpliterItem.svg-73b989ef018da2301c61b6f59ef99931.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | svg/scale=8.0 36 | editor/scale_with_editor_scale=false 37 | editor/convert_colors_with_editor_theme=false 38 | -------------------------------------------------------------------------------- /addons/script_spliter/core/ui/multi_split_container.gd: -------------------------------------------------------------------------------- 1 | @tool 2 | @icon("icon/MultiSpliter.svg") 3 | extends Container 4 | # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # 5 | # https://github.com/CodeNameTwister/Multi-Split-Container 6 | # 7 | # Multi-Split-Container addon for godot 4 8 | # author: "Twister" 9 | # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # 10 | 11 | const SplitContainerItem : Script = preload("res://addons/script_spliter/core/ui/split_container_item.gd") 12 | const SplitButton : Texture = preload("res://addons/script_spliter/core/ui/icon/MultiSpliterButton.svg") 13 | 14 | @export_category("Multi-Split Settings") 15 | ## Max columns by rows, after added childs this is eparated by row group by columns size! 16 | ## [br][br] 17 | ## if this value is 0, will not create rows spliters. 18 | @export_range(0.0, 1000.0, 1.0) var max_columns : int = 0: 19 | set(e): 20 | max_columns = maxi(0, e) 21 | 22 | if Engine.is_editor_hint(): 23 | for x : int in range(separators_line_offsets.size()): 24 | separators_line_offsets[x] = 0.0 25 | for x : LineSep in _separators: 26 | x.queue_free() 27 | 28 | _separators.clear() 29 | _first = true 30 | update() 31 | 32 | @export_group("Line Separator", "separator_line") 33 | ## Line separator size. 34 | @export var separator_line_size : float = 4.0: 35 | set(e): 36 | separator_line_size = max(e, 0.0) 37 | update() 38 | 39 | ## Separator line color. 40 | @export var separator_line_color : Color = Color.MAGENTA: 41 | set(e): 42 | separator_line_color = e 43 | if separator_line_color == Color.MAGENTA: # That color reminds me of texture not found errors. 44 | var root = EditorInterface.get_base_control() 45 | separator_line_color = root.get_theme_color("base_color", "Editor") 46 | update() 47 | 48 | ## Separator line visibility. 49 | @export var separator_line_visible : bool = true: 50 | set(e): 51 | separator_line_visible = e 52 | for l : LineSep in _separators: 53 | l.visible = separator_line_visible 54 | 55 | @export_subgroup("Behaviour", "behaviour_") 56 | ## Enable function for auto expand lines container on inside focus. 57 | @export var behaviour_expand_on_focus : bool = true 58 | 59 | ## Enable function for auto expand lines container on double click in the line. 60 | @export var behaviour_expand_on_double_click : bool = true: 61 | set(e): 62 | behaviour_expand_on_double_click = e 63 | for l : LineSep in _separators: 64 | l.double_click_handler = behaviour_expand_on_double_click 65 | 66 | ## Enable movement by touching line. 67 | @export var behaviour_can_move_by_line : bool = true: 68 | set(e): 69 | behaviour_can_move_by_line = e 70 | for l : LineSep in _separators: 71 | l.draggable = behaviour_can_move_by_line 72 | 73 | ## This allow expand you current focused container if you shrunk it. 74 | @export var behaviour_can_expand_focus_same_container : bool = false 75 | 76 | ## Enable smooth when expand container. 77 | @export var behaviour_expand_smoothed : bool = true: 78 | set(e): 79 | behaviour_expand_smoothed = e 80 | if !e: 81 | if _tween and _tween.is_running(): 82 | _tween.kill() 83 | _tween = null 84 | 85 | ## Time speed duration for reset expand container. 86 | @export_range(0.01, 1000.0, 0.01) var behaviour_expand_smoothed_time : float = 0.24: 87 | set(e): 88 | behaviour_expand_smoothed_time = maxf(0.01, e) 89 | if _tween and _tween.is_running(): 90 | _tween.kill() 91 | _tween = null 92 | 93 | ## Custom initial offset for separator lines. (TODO: Still Working here!) 94 | @export var separators_line_offsets : Array[float] : 95 | set(e): 96 | separators_line_offsets = e 97 | 98 | if Engine.is_editor_hint(): 99 | if separators_line_offsets.size() != _separators.size(): 100 | separators_line_offsets.resize(_separators.size()) 101 | update() 102 | 103 | @export_subgroup("Drag Button", "drag_button") 104 | 105 | ## Set if drag button always be visible (Useful for test button size) 106 | @export var drag_button_always_visible : bool = false: 107 | set(e): 108 | drag_button_always_visible = e 109 | 110 | var min_visible_drag_button : float = 0.0 111 | if drag_button_always_visible: 112 | min_visible_drag_button = 0.4 113 | 114 | for l : LineSep in _separators: 115 | if l.button: 116 | l.button.modulate.a = 0.0 117 | l.button.min_no_focus_transparense = min_visible_drag_button 118 | 119 | ## Min size for drag button visible on split lines. 120 | @export_range(1.0, 200.0, 0.1) var drag_button_size : float = 24.0: 121 | set(e): 122 | drag_button_size = e 123 | update() 124 | 125 | ## Modulate color for the drag button. 126 | @export var drag_button_modulate : Color = Color.MAGENTA: 127 | set(e): 128 | drag_button_modulate = e 129 | if drag_button_modulate == Color.MAGENTA: 130 | if Engine.is_editor_hint(): 131 | var root : Control = EditorInterface.get_base_control() 132 | drag_button_modulate = root.get_theme_color("base_color", "Editor").lightened(0.5) 133 | update() 134 | 135 | ## Change default drag button icon. 136 | @export var drag_button_icon : Texture = null: 137 | set(e): 138 | drag_button_icon = e 139 | update() 140 | 141 | var _separators : Array[LineSep] = [] 142 | var _last_container_focus : Node = null 143 | var _frame : int = 1 144 | var _first : bool = true 145 | var _tween : Tween = null 146 | 147 | func get_separators() -> Array[LineSep]: 148 | return _separators 149 | 150 | ## Get line begin offset limit. 151 | func get_line_seperator_left_offset_limit(index : int) -> float: 152 | if index < _separators.size(): 153 | var line_sep : LineSep = _separators[index] 154 | if !line_sep.is_vertical: 155 | if index < 1: 156 | return -_separators[index].initial_position.x 157 | var next : LineSep = _separators[index - 1] 158 | return (next.initial_position.x + (next.size.x/2.0)) - _separators[index].initial_position.x 159 | else: 160 | if index < 1: 161 | return -_separators[index].initial_position.y 162 | var next : LineSep = _separators[index - 1] 163 | return (next.initial_position.y + (next.size.y/2.0)) - _separators[index].initial_position.y 164 | push_warning("[PLUGIN] Not valid index for line separator!") 165 | return 0.0 166 | 167 | ## Get line end offset limit. 168 | func get_line_seperator_right_offset_limit(index : int) -> float: 169 | if index < _separators.size(): 170 | var line_sep : LineSep = _separators[index] 171 | if !line_sep.is_vertical: 172 | if index + 1 == _separators.size(): 173 | return (size.x/2.0) -_separators[index].initial_position.x 174 | var current : LineSep = _separators[index] 175 | return (_separators[index + 1].initial_position.x - current.initial_position.x + (current.size.x/2.0)) 176 | else: 177 | if index + 1 == _separators.size(): 178 | return size.x -_separators[index].initial_position.y 179 | var current : LineSep = _separators[index] 180 | return (_separators[index + 1].initial_position.y - current.initial_position.y + (current.size.y/2.0)) 181 | push_warning("[PLUGIN] Not valid index for line separator!") 182 | return 0.0 183 | 184 | # This is function is util when you want expand or constraint manualy offset. 185 | ## Update offset of the line 186 | func update_line_separator_offset(index : int, offset : float) -> void: 187 | var line_sep : LineSep = _separators[index] 188 | line_sep.offset = offset 189 | line_sep.force_update() 190 | 191 | ## Get total line count. 192 | func get_line_separator_count() -> int: 193 | return _separators.size() 194 | 195 | ## Get Line reference by index, see get_line_separator_count() 196 | func get_line_separator(index : int) -> LineSep: 197 | return _separators[index] 198 | 199 | ## Get if line separator is vertical. 200 | func is_vertical_line_separator(index : int) -> bool: 201 | if index < _separators.size(): 202 | return _separators[index].is_vertical 203 | push_warning("[PLUGIN] Not valid index for line separator!") 204 | return false 205 | 206 | ## Expand splited container by index container. 207 | func expand_splited_container(node : Node) -> void: 208 | var same : bool = _last_container_focus == node 209 | 210 | if same and !behaviour_can_expand_focus_same_container: 211 | return 212 | 213 | _last_container_focus = node 214 | 215 | if !behaviour_expand_on_focus: 216 | return 217 | 218 | if _tween and _tween.is_running(): 219 | if same: 220 | return 221 | _tween.kill() 222 | _tween = null 223 | 224 | var top_lines : Array[LineSep] = [] 225 | var bottom_lines : Array[LineSep] = [] 226 | 227 | var update_required : bool = false 228 | 229 | for line : LineSep in _separators: 230 | if node in line.top_items: 231 | update_required = update_required or line.offset < 0.0 232 | top_lines.append(line) 233 | elif node in line.bottom_items: 234 | update_required = update_required or line.offset > 0.0 235 | bottom_lines.append(line) 236 | 237 | if update_required: 238 | if behaviour_expand_smoothed: 239 | _tween = get_tree().create_tween() 240 | _tween.tween_method(_reset_expanded_lines.bind(top_lines, bottom_lines), 0.0, 1.0, behaviour_expand_smoothed_time) 241 | else: 242 | _reset_expanded_lines(1.0, top_lines, bottom_lines) 243 | 244 | func _reset_expanded_lines(_lerp : float, top_lines : Array[LineSep], bottom_lines : Array[LineSep]) -> void: 245 | for iline : int in range(top_lines.size() - 1, -1, -1): 246 | var line : LineSep = top_lines[iline] 247 | if is_instance_valid(line): 248 | if line.offset < 0.0: 249 | line.offset = lerp(line.offset, 0.0, _lerp) 250 | else: 251 | top_lines.remove_at(iline) 252 | 253 | for iline : int in range(bottom_lines.size() - 1, -1, -1): 254 | var line : LineSep = bottom_lines[iline] 255 | if is_instance_valid(line): 256 | if line.offset > 0.0: 257 | line.offset = lerp(line.offset, 0.0, _lerp) 258 | else: 259 | bottom_lines.remove_at(iline) 260 | 261 | for line : LineSep in top_lines: 262 | line.force_update() 263 | for line : LineSep in bottom_lines: 264 | line.force_update() 265 | 266 | ## Get initial position of a separator line. 267 | func get_line_separator_initial_position(index : int) -> Vector2: 268 | if index < _separators.size(): 269 | return _separators[index].initial_position 270 | push_warning("[PLUGIN] Not valid index for line separator!") 271 | return Vector2.ZERO 272 | 273 | class DragButton extends Button: 274 | var _frm : float = 0.0 275 | var _line_sep : LineSep = null 276 | var _is_pressed : bool = false 277 | 278 | var is_hover : bool = false 279 | 280 | var _hover : Array[bool] = [false, false] 281 | 282 | var min_no_focus_transparense : float = 0.0: 283 | set(e): 284 | min_no_focus_transparense = e 285 | modulate.a = maxf(modulate.a, min_no_focus_transparense) 286 | 287 | static var DEFAULT_STYLE : StyleBox = null 288 | 289 | func set_drag_icon(new_icon : Texture) -> void: 290 | if icon != new_icon: 291 | if new_icon == null: 292 | icon = SplitButton 293 | return 294 | icon = new_icon 295 | 296 | func update_gui() -> void: 297 | if !_line_sep: 298 | return 299 | 300 | if _line_sep.is_vertical: 301 | _line_sep.mouse_default_cursor_shape = Control.CURSOR_VSPLIT 302 | mouse_default_cursor_shape = Control.CURSOR_VSPLIT 303 | else: 304 | _line_sep.mouse_default_cursor_shape = Control.CURSOR_HSPLIT 305 | mouse_default_cursor_shape = Control.CURSOR_HSPLIT 306 | 307 | func set_line(line_sep : LineSep) -> void: 308 | if _line_sep: 309 | if _line_sep.mouse_entered.is_connected(_on_enter): 310 | _line_sep.mouse_entered.disconnect(_on_enter) 311 | if _line_sep.mouse_exited.is_connected(_on_exit): 312 | _line_sep.mouse_exited.disconnect(_on_exit) 313 | if _line_sep.gui_input.is_connected(_on_input): 314 | _line_sep.gui_input.disconnect(_on_input) 315 | 316 | _line_sep = line_sep 317 | 318 | if _line_sep: 319 | if !_line_sep.mouse_entered.is_connected(_on_enter): 320 | _line_sep.mouse_entered.connect(_on_enter.bind(1)) 321 | if !_line_sep.mouse_exited.is_connected(_on_exit): 322 | _line_sep.mouse_exited.connect(_on_exit.bind(1)) 323 | if !_line_sep.gui_input.is_connected(_on_input): 324 | _line_sep.gui_input.connect(_on_input) 325 | 326 | 327 | func _init(line_sep : LineSep = null) -> void: 328 | modulate.a = 0.0 329 | 330 | set_line(line_sep) 331 | 332 | button_down.connect(_on_press) 333 | button_up.connect(_out_press) 334 | mouse_entered.connect(_on_enter.bind(0)) 335 | mouse_exited.connect(_on_exit.bind(0)) 336 | 337 | gui_input.connect(_custom_input) 338 | 339 | icon = SplitButton 340 | icon_alignment = HORIZONTAL_ALIGNMENT_CENTER 341 | vertical_icon_alignment = VERTICAL_ALIGNMENT_CENTER 342 | expand_icon = true 343 | 344 | if null != icon: 345 | flat = true 346 | 347 | if DEFAULT_STYLE == null: 348 | DEFAULT_STYLE = StyleBoxEmpty.new() 349 | 350 | focus_mode = Control.FOCUS_CLICK 351 | 352 | set(&"theme_override_styles/focus", DEFAULT_STYLE) 353 | set(&"theme_override_styles/disabled_mirrored", DEFAULT_STYLE) 354 | set(&"theme_override_styles/disabled", DEFAULT_STYLE) 355 | set(&"theme_override_styles/hover_pressed_mirrored", DEFAULT_STYLE) 356 | set(&"theme_override_styles/hover_pressed", DEFAULT_STYLE) 357 | set(&"theme_override_styles/hover_mirrored", DEFAULT_STYLE) 358 | set(&"theme_override_styles/hover", DEFAULT_STYLE) 359 | set(&"theme_override_styles/pressed_mirrored", DEFAULT_STYLE) 360 | set(&"theme_override_styles/pressed", DEFAULT_STYLE) 361 | set(&"theme_override_styles/normal_mirrored", DEFAULT_STYLE) 362 | set(&"theme_override_styles/normal", DEFAULT_STYLE) 363 | 364 | z_as_relative = true 365 | z_index = 2000 366 | 367 | update_gui() 368 | 369 | func _custom_input(e : InputEvent) -> void: 370 | if e is InputEventMouseButton: 371 | if e.pressed and e.double_click: 372 | get_tree().call_group(&"ScriptSpliter", &"swap", get_parent()) 373 | 374 | func _on_input(e : InputEvent) -> void: 375 | if e is InputEventMouseButton: 376 | if e.pressed and e.double_click: 377 | if _line_sep and _line_sep.double_click_handler: 378 | _line_sep.offset = 0.0 379 | _line_sep.offset_updated.emit() 380 | elif e.pressed and _line_sep.draggable and e.button_index == 1: 381 | button_down.emit() 382 | elif !e.pressed and _line_sep.draggable and e.button_index == 1: 383 | button_up.emit() 384 | 385 | func set_line_sep_reference(ref : LineSep) -> void: 386 | _line_sep = ref 387 | 388 | func _ready() -> void: 389 | set_process(false) 390 | 391 | func _on_enter(x : int = 0) -> void: 392 | _hover[x] = true 393 | 394 | _frm = 0.0 395 | modulate.a = 1.0 396 | is_hover = true 397 | set_process(true) 398 | 399 | func _on_exit(x : int = 0) -> void: 400 | _hover[x] = false 401 | 402 | for h : bool in _hover: 403 | if h != false: 404 | return 405 | 406 | _frm = 0.0 407 | modulate.a = 1.0 408 | is_hover = false 409 | set_process(true) 410 | 411 | func _on_press() -> void: 412 | _is_pressed = true 413 | _frm = 0.0 414 | modulate.a = 1.0 415 | set_process(true) 416 | 417 | func _out_press() -> void: 418 | _is_pressed = false 419 | set_process(true) 420 | 421 | func _process(delta : float) -> void: 422 | if !has_focus() and !is_hover: 423 | _frm += delta * 0.4 424 | if _frm >= 1.0: 425 | _frm = 1.0 426 | set_process(false) 427 | modulate.a = lerp(modulate.a, min_no_focus_transparense, _frm) 428 | if _is_pressed: 429 | var mpos : Vector2 = _line_sep.get_parent().get_local_mouse_position() 430 | if mpos != get_rect().get_center(): 431 | _line_sep.update_offset_by_position(mpos) 432 | 433 | class UndoredoSplit extends RefCounted: 434 | var object : SplitContainerItem = null 435 | var c_objects : Array[Node] = [] 436 | 437 | class LineSep extends ColorRect: 438 | signal offset_updated() 439 | 440 | var top_lines : Array[LineSep] = [] 441 | var bottom_lines : Array[LineSep] = [] 442 | 443 | var top_items : Array[Control] = [] 444 | var bottom_items : Array[Control] = [] 445 | 446 | var is_vertical : bool = false: 447 | set(e): 448 | is_vertical = e 449 | 450 | if button: 451 | button.update_gui() 452 | 453 | var row : int = 0 454 | 455 | var initial_position : Vector2 = Vector2.ZERO 456 | var offset : float = 0.0 457 | 458 | var min_size_offset : float = 0.0 459 | 460 | var prev_line : LineSep = null 461 | var next_line : LineSep = null 462 | 463 | var button : DragButton = null 464 | 465 | var double_click_handler : bool = true 466 | var draggable : bool = true 467 | 468 | func set_next_line(next : LineSep = null) -> void: 469 | next_line = next 470 | next.prev_line = self 471 | 472 | func clear() -> void: 473 | top_items.clear() 474 | bottom_items.clear() 475 | top_lines.clear() 476 | bottom_lines.clear() 477 | 478 | func reset() -> void: 479 | position = initial_position 480 | update_items() 481 | 482 | func update_items() -> void: 483 | if is_vertical: 484 | for item : Control in top_items: 485 | item.size.y = position.y - item.position.y 486 | if !prev_line: 487 | item.position.y = 0.0 488 | 489 | for item : Control in bottom_items: 490 | item.position.y = position.y + size.y 491 | 492 | if next_line: 493 | item.size.y = next_line.position.y - item.position.y 494 | else: 495 | item.size.y = get_parent().size.y - item.position.y 496 | else: 497 | for item : Control in top_items: 498 | item.size.x = position.x - item.position.x + (size.x / 2.0) - 2.0 499 | if !prev_line: 500 | item.position.x = 0.0 501 | 502 | for item : Control in bottom_items: 503 | var diff : float = position.x + (size.x / 2.0) + 2.0 504 | item.position.x = diff 505 | 506 | if next_line: 507 | item.size.x = next_line.position.x - item.position.x 508 | else: 509 | item.size.x = get_parent().size.x - item.position.x 510 | 511 | func force_update() -> void: 512 | update_offset_by_position(initial_position + Vector2(offset * int(!is_vertical), offset * int(is_vertical))) 513 | 514 | func get_current_position() -> Vector2: 515 | return initial_position + Vector2(offset * int(!is_vertical), offset * int(is_vertical)) 516 | 517 | func update_offset_by_position(vpos : Vector2) -> void: 518 | if is_vertical: 519 | min_size_offset = 0.0 520 | for x : Control in top_items: 521 | min_size_offset = maxf(min_size_offset, x.get_minimum_size().y) 522 | if prev_line: 523 | prev_line.min_size_offset = 0.0 524 | for x : Control in prev_line.bottom_items: 525 | prev_line.min_size_offset = maxf(prev_line.min_size_offset, x.get_minimum_size().y) 526 | 527 | offset = vpos.y - initial_position.y 528 | offset = minf(offset, get_parent().size.y - (initial_position.y + size.y + min_size_offset)) 529 | offset = maxf(offset, -(initial_position.y - min_size_offset)) 530 | 531 | if next_line: 532 | var val : float = next_line.position.y - (initial_position.y + size.y + min_size_offset) 533 | if offset > val: 534 | offset = val 535 | else: 536 | var val : float = get_parent().size.y - (initial_position.y + (size.y / 2.0) + min_size_offset) 537 | if offset > val: 538 | offset = val 539 | if prev_line: 540 | var val : float = -(initial_position.y - (prev_line.position.y + prev_line.size.y + prev_line.min_size_offset)) 541 | 542 | if offset < val: 543 | offset = val 544 | else: 545 | var top_size_offset : float = 0.0 546 | for x : Control in top_items: 547 | top_size_offset = maxf(top_size_offset, x.get_minimum_size().y) 548 | offset = maxf(offset, top_size_offset-initial_position.y) 549 | 550 | position.y = initial_position.y + offset 551 | 552 | for line : LineSep in top_lines: 553 | line.size.y = position.y - line.position.y 554 | 555 | for line : LineSep in bottom_lines: 556 | line.position.y = position.y + size.y 557 | 558 | if next_line: 559 | line.size.y = next_line.position.y - line.position.y 560 | else: 561 | line.size.y = get_parent().size.y - line.position.y 562 | else: 563 | min_size_offset = 0.0 564 | for x : Control in bottom_items: 565 | min_size_offset = maxf(min_size_offset, x.get_minimum_size().x) 566 | 567 | if prev_line: 568 | prev_line.min_size_offset = 0.0 569 | for x : Control in prev_line.bottom_items: 570 | prev_line.min_size_offset = maxf(prev_line.min_size_offset, x.get_minimum_size().x) 571 | 572 | offset = vpos.x - initial_position.x 573 | offset = minf(offset, get_parent().size.x - (initial_position.x + size.x + min_size_offset)) 574 | offset = maxf(offset, -initial_position.x) 575 | 576 | if next_line: 577 | var val : float = next_line.position.x - (initial_position.x + size.x + min_size_offset) 578 | if offset > val: 579 | offset = val 580 | else: 581 | var val : float = get_parent().size.x - (initial_position.x + (size.x/2.0) + min_size_offset) 582 | if offset > val: 583 | offset = val 584 | if prev_line: 585 | var val : float = -(initial_position.x - (prev_line.position.x + prev_line.size.x + prev_line.min_size_offset)) 586 | 587 | if offset < val: 588 | offset = val 589 | else: 590 | var top_size_offset : float = 0.0 591 | for x : Control in top_items: 592 | top_size_offset = maxf(top_size_offset, x.get_minimum_size().x) 593 | offset = maxf(offset, top_size_offset-initial_position.x) 594 | 595 | position.x = initial_position.x + offset 596 | update_items() 597 | 598 | func _draw() -> void: 599 | update() 600 | 601 | func update() -> void: 602 | button.rotation_degrees = 90.0 * int(is_vertical) 603 | button.pivot_offset = button.size / 2.0 604 | button.position = size / 2.0 - button.pivot_offset 605 | 606 | 607 | 608 | func _init() -> void: 609 | color = Color.RED 610 | 611 | func _ready() -> void: 612 | name = "SplitLine" 613 | if button == null: 614 | button = DragButton.new(self) 615 | add_child(button, false, Node.INTERNAL_MODE_BACK) 616 | 617 | func _test() -> void: 618 | queue_redraw() 619 | 620 | func _init() -> void: 621 | child_entered_tree.connect(_on_enter) 622 | child_exiting_tree.connect(_on_exiting) 623 | 624 | func update() -> void: 625 | set_process(true) 626 | 627 | func _create_separator() -> Control: 628 | var line_sep : LineSep = LineSep.new() 629 | line_sep.offset_updated.connect(update) 630 | return line_sep 631 | 632 | func _undoredo_undo(ur : UndoredoSplit) -> void: 633 | if !is_instance_valid(ur): 634 | return 635 | 636 | var split : SplitContainerItem = ur.object 637 | if is_instance_valid(split): 638 | if split.get_parent() == self: 639 | ur.c_objects = split.get_children() 640 | for x : Node in ur.c_objects: 641 | split.remove_child(x) 642 | if x is Control: 643 | x.visible = false 644 | add_child(x) 645 | if is_instance_valid(split) and split.get_parent() == self: 646 | remove_child(split) 647 | 648 | func _update() -> void: 649 | var items : Array[Control] = [] 650 | for x : Node in get_children(): 651 | if is_instance_valid(x) and x is Control: 652 | if x.visible and !x.is_queued_for_deletion(): 653 | if x is SplitContainerItem: 654 | if x.get_child_count() > 0: 655 | var _is_visible : bool = false 656 | for y : Node in x.get_children(): 657 | if y is Control and y.visible: 658 | _is_visible = true 659 | break 660 | if !_is_visible: 661 | continue 662 | else: 663 | x.queue_free() 664 | continue 665 | elif x is DragButton or x is LineSep: 666 | x.queue_free() 667 | continue 668 | else: 669 | var container : SplitContainerItem = SplitContainerItem.new() 670 | 671 | add_child(container, true) 672 | 673 | x.reparent(container) 674 | x = container 675 | 676 | 677 | x.size_flags_horizontal = Control.SIZE_FILL 678 | x.size_flags_vertical = Control.SIZE_FILL 679 | x.clip_contents = true 680 | x.custom_minimum_size = Vector2.ZERO 681 | items.append(x) 682 | 683 | var totals : int = items.size() 684 | var rows : int = 0 685 | 686 | if max_columns > 0: 687 | var _totals : int = totals 688 | rows = 0 689 | while _totals > max_columns: 690 | _totals -= max_columns 691 | rows += 1 692 | totals -= rows 693 | 694 | if totals < 1: 695 | for x : int in range(0, _separators.size(), 1): 696 | _separators[x].queue_free() 697 | _separators[x] = null 698 | _separators.clear() 699 | 700 | for x : Control in items: 701 | x.position = Vector2.ZERO 702 | x.size = get_rect().size 703 | return 704 | else: 705 | if separator_line_size <= 0.0: 706 | for x : int in range(0, _separators.size(), 1): 707 | _separators[x].queue_free() 708 | _separators[x] = null 709 | _separators.clear() 710 | else: 711 | var sep : int = totals - 1 + rows 712 | for x : int in range(sep, _separators.size(), 1): 713 | _separators[x].queue_free() 714 | _separators[x] = null 715 | _separators.resize(sep) 716 | for x : int in range(0, _separators.size(), 1): 717 | if _separators[x] == null: 718 | _separators[x] = _create_separator() 719 | 720 | rows += 1 721 | if max_columns > 1: 722 | if totals > max_columns: 723 | totals = max_columns 724 | 725 | var rect_size : Vector2 = get_rect().size 726 | var start_position : Vector2 = Vector2.ZERO 727 | 728 | var size_split : Vector2 = (rect_size / Vector2(totals, rows)) 729 | 730 | var size_sep : Vector2 = Vector2.ONE * separator_line_size 731 | 732 | if totals > 1: 733 | size_sep = (size_sep / (totals - 1)) 734 | 735 | var item_size : Vector2 = Vector2(size_split.x, size_split.y) 736 | var line_size : Vector2 = Vector2(separator_line_size, item_size.y) 737 | 738 | var total_items : int = items.size() 739 | 740 | var vpos : Vector2 = Vector2.ZERO 741 | var current_row : int = 0 742 | 743 | var item_index : int = 0 744 | 745 | var last_vline : LineSep = null 746 | var last_hline : LineSep = null 747 | 748 | for x : Control in items: 749 | x.position = Vector2.ZERO 750 | x.size = x.get_minimum_size() 751 | 752 | for z : int in range(_separators.size()): 753 | var x : LineSep = _separators[z] 754 | 755 | x.clear() 756 | 757 | start_position.x += 1 758 | 759 | if 0 < max_columns and start_position.x + 1 > max_columns: 760 | total_items -= max_columns 761 | start_position.x = 0.0 762 | start_position.y += 1.0 763 | current_row += 1 764 | if total_items <= max_columns and total_items > 0: 765 | size_split = (rect_size / Vector2(total_items, rows)) 766 | if total_items == 1: 767 | size_sep = Vector2.ONE * separator_line_size 768 | else: 769 | size_sep = ((Vector2.ONE * separator_line_size) / (total_items - 1)) 770 | item_size = Vector2(size_split.x, size_split.y) 771 | line_size = Vector2(separator_line_size, rect_size.y - x.position.y) 772 | 773 | vpos = Vector2(0.0, start_position.y) * item_size 774 | x.is_vertical = true 775 | 776 | if x.get_parent() == null: 777 | add_child(x, false, Node.INTERNAL_MODE_BACK) 778 | 779 | 780 | x.row = current_row 781 | 782 | if items.size() > 0: 783 | var it : int = mini(item_index, items.size() - 1) 784 | var min_size : float = 0.0 785 | 786 | var _has : bool = false 787 | 788 | for y : int in range(z - 1, -1, -1): 789 | if it > -1: 790 | var item : Control = items[it] 791 | x.top_items.append(item) 792 | min_size = maxf(item.get_minimum_size().y, min_size) 793 | it -= 1 794 | 795 | var ln : LineSep = _separators[y] 796 | if ln.is_vertical: 797 | _has = true 798 | break 799 | x.top_lines.append(ln) 800 | if !_has: 801 | for _it : int in range(it, -1, -1): 802 | var item : Control = items[it] 803 | x.top_items.append(item) 804 | 805 | if item_index + 1 < items.size(): 806 | it = item_index + 1 807 | _has = false 808 | for y : int in range(z + 1, _separators.size(), 1): 809 | if it < items.size(): 810 | var item : Control = items[it] 811 | x.bottom_items.append(item) 812 | it += 1 813 | 814 | var ln : LineSep = _separators[y] 815 | if ln.is_vertical: 816 | _has = true 817 | break 818 | x.bottom_lines.append(ln) 819 | if !_has: 820 | for _it : int in range(it, items.size(), 1): 821 | var item : Control = items[_it] 822 | x.bottom_items.append(item) 823 | 824 | var vline_size : Vector2 = Vector2(rect_size.x, separator_line_size) 825 | 826 | x.initial_position = vpos 827 | x.initial_position.y -= (vline_size.y) / 2.0 828 | x.position = x.initial_position 829 | 830 | x.button.size = Vector2(drag_button_size, drag_button_size) 831 | 832 | x.set(&"size", vline_size) 833 | x.update() 834 | 835 | if last_vline: 836 | last_vline.set_next_line(x) 837 | 838 | last_vline = x 839 | last_hline = null 840 | item_index += 1 841 | continue 842 | 843 | vpos = start_position * item_size 844 | 845 | if x.get_parent() == null: 846 | add_child(x, false, Node.INTERNAL_MODE_BACK) 847 | 848 | 849 | if item_index < items.size(): 850 | var item : Control = items[item_index] 851 | x.top_items.append(item) 852 | item_index += 1 853 | if item_index < items.size(): 854 | if z + 1 < _separators.size(): 855 | if !_separators[z].is_vertical: 856 | x.bottom_items.append(items[item_index]) 857 | else: 858 | x.bottom_items.append(items[item_index]) 859 | 860 | x.initial_position = vpos 861 | x.initial_position.x -= (line_size.x) / 2.0 862 | 863 | x.button.size = Vector2(drag_button_size, drag_button_size) 864 | 865 | x.row = current_row 866 | x.position = x.initial_position 867 | 868 | x.set(&"size", line_size) 869 | x.update() 870 | 871 | if last_hline: 872 | last_hline.set_next_line(x) 873 | last_hline = x 874 | 875 | for x : Control in items: 876 | x.size = size 877 | 878 | var min_visible_drag_button : float = 0.0 879 | if drag_button_always_visible: 880 | min_visible_drag_button = 0.4 881 | 882 | if _first: 883 | for l : LineSep in _separators: 884 | l.visible = separator_line_visible 885 | l.color = separator_line_color 886 | l.double_click_handler = behaviour_expand_on_double_click 887 | l.button.self_modulate = drag_button_modulate 888 | l.button.min_no_focus_transparense = min_visible_drag_button 889 | l.button.set_drag_icon(drag_button_icon) 890 | l.draggable = behaviour_can_move_by_line 891 | 892 | l.reset() 893 | 894 | else: 895 | if separators_line_offsets.size() > 0: 896 | for l : int in range(0, _separators.size(), 1): 897 | if l < separators_line_offsets.size(): 898 | _separators[l].offset = separators_line_offsets[l] 899 | continue 900 | break 901 | 902 | for l : LineSep in _separators: 903 | l.visible = separator_line_visible 904 | l.color = separator_line_color 905 | l.double_click_handler = behaviour_expand_on_double_click 906 | l.button.self_modulate = drag_button_modulate 907 | l.button.min_no_focus_transparense = min_visible_drag_button 908 | l.button.set_drag_icon(drag_button_icon) 909 | l.draggable = behaviour_can_move_by_line 910 | 911 | l.force_update() 912 | 913 | if !Engine.is_editor_hint(): 914 | separators_line_offsets.clear() 915 | else: 916 | for l : int in range(0, _separators.size(), 1): 917 | if l < separators_line_offsets.size(): 918 | separators_line_offsets[l] = _separators[l].offset 919 | continue 920 | break 921 | 922 | func _on_enter(n : Node) -> void: 923 | n.is_inside_tree() 924 | if n is SplitContainerItem or (n is Control and !Engine.is_editor_hint()): 925 | if !n.visibility_changed.is_connected(_on_visible): 926 | n.visibility_changed.connect(_on_visible) 927 | if is_node_ready(): 928 | for x : int in range(separators_line_offsets.size()): 929 | separators_line_offsets[x] = 0.0 930 | update() 931 | 932 | func _on_visible() -> void: 933 | update() 934 | 935 | func _on_exiting(n : Node) -> void: 936 | if n is SplitContainerItem or (n is Control and !Engine.is_editor_hint()): 937 | if is_node_ready(): 938 | for x : int in range(separators_line_offsets.size()): 939 | separators_line_offsets[x] = 0.0 940 | for x : LineSep in _separators: 941 | x.offset = 0.0 942 | if n.visibility_changed.is_connected(_on_visible): 943 | n.visibility_changed.disconnect(_on_visible) 944 | update() 945 | 946 | func _process(__ : float) -> void: 947 | if is_node_ready(): 948 | if _frame > 0: 949 | _frame -= 1 950 | return 951 | _update() 952 | if _first: 953 | _first = false 954 | else: 955 | set_process(false) 956 | 957 | func _on_exiting_tree() -> void: 958 | var vp : Viewport = get_viewport() 959 | if vp and vp.size_changed.is_connected(update): 960 | vp.size_changed.disconnect(update) 961 | 962 | var parent : Node = get_parent() 963 | if parent is Control: 964 | if parent.item_rect_changed.is_connected(update): 965 | parent.item_rect_changed.disconnect(update) 966 | 967 | func _enter_tree() -> void: 968 | var vp : Viewport = get_viewport() 969 | if vp and !vp.size_changed.is_connected(update): 970 | vp.size_changed.connect(update) 971 | 972 | var parent : Node = get_parent() 973 | if parent is Control: 974 | if !parent.item_rect_changed.is_connected(update): 975 | parent.item_rect_changed.connect(update) 976 | 977 | if !tree_exiting.is_connected(_on_exiting_tree): 978 | tree_exiting.connect(_on_exiting_tree) 979 | 980 | func _on_draw() -> void: 981 | update() 982 | 983 | func _ready() -> void: 984 | separator_line_color = separator_line_color 985 | drag_button_modulate = drag_button_modulate 986 | 987 | size_flags_horizontal = Control.SIZE_EXPAND_FILL 988 | size_flags_vertical =Control.SIZE_EXPAND_FILL 989 | 990 | set_deferred(&"anchor_left", 0.0) 991 | set_deferred(&"anchor_top", 0.0) 992 | set_deferred(&"anchor_bottom", 1.0) 993 | set_deferred(&"anchor_right", 1.0) 994 | 995 | if Engine.is_editor_hint(): 996 | draw.connect(_on_draw) 997 | 998 | if _first: 999 | update() 1000 | -------------------------------------------------------------------------------- /addons/script_spliter/core/ui/multi_split_container.gd.uid: -------------------------------------------------------------------------------- 1 | uid://cbd7egxjurkl4 2 | -------------------------------------------------------------------------------- /addons/script_spliter/core/ui/split_container_item.gd: -------------------------------------------------------------------------------- 1 | @tool 2 | @icon("icon/MultiSpliterItem.svg") 3 | extends Control 4 | # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # 5 | # https://github.com/CodeNameTwister/Multi-Split-Container 6 | # 7 | # Multi-Split-Container addon for godot 4 8 | # author: "Twister" 9 | # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # 10 | 11 | var focus_handler : bool = false 12 | 13 | ## Expand if tight by spliter 14 | func show_splited_container() -> void: 15 | var parent : Node = get_parent() 16 | if parent.has_method(&"expand_splited_container"): 17 | parent.call(&"expand_splited_container", self) 18 | 19 | 20 | func _ready() -> void: 21 | set_process(false) 22 | 23 | size_flags_horizontal = Control.SIZE_FILL 24 | size_flags_vertical = Control.SIZE_FILL 25 | 26 | set_deferred(&"anchor_left", 0.0) 27 | set_deferred(&"anchor_top", 0.0) 28 | set_deferred(&"anchor_bottom", 1.0) 29 | set_deferred(&"anchor_right", 1.0) 30 | 31 | func _init() -> void: 32 | name = "SplitContainerItem" 33 | 34 | child_exiting_tree.connect(_on_child_exiting_tree) 35 | child_entered_tree.connect(_on_child_entered_tree) 36 | 37 | func _on_visible() -> void: 38 | var _visible : bool = false 39 | for x : Node in get_children(): 40 | if x is Control: 41 | if x.visible: 42 | _visible = true 43 | break 44 | visible = _visible 45 | 46 | func _on_child_entered_tree(n : Node) -> void: 47 | if n is Control: 48 | n.size = size 49 | n.set_anchor(SIDE_LEFT, 0.0) 50 | n.set_anchor(SIDE_RIGHT, 1.0) 51 | n.set_anchor(SIDE_TOP, 0.0) 52 | n.set_anchor(SIDE_BOTTOM, 1.0) 53 | if !n.visibility_changed.is_connected(_on_visible): 54 | n.visibility_changed.connect(_on_visible) 55 | 56 | func _disconnect(n : Node) -> void: 57 | if n is Control: 58 | if n.visibility_changed.is_connected(_on_visible): 59 | n.visibility_changed.disconnect(_on_visible) 60 | for x : Node in n.get_children(): 61 | _disconnect(x) 62 | 63 | func _on_child_exiting_tree(n : Node) -> void: 64 | _disconnect(n) 65 | 66 | func _enter_tree() -> void: 67 | var c : Node = get_parent() 68 | if c is Control: 69 | size = c.size 70 | -------------------------------------------------------------------------------- /addons/script_spliter/core/ui/split_container_item.gd.uid: -------------------------------------------------------------------------------- 1 | uid://buerhchaby30c 2 | -------------------------------------------------------------------------------- /addons/script_spliter/io/backward_key_button.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="InputEventKey" format=3 uid="uid://p4o5dw6yauu"] 2 | 3 | [resource] 4 | alt_pressed = true 5 | key_label = 4194319 6 | -------------------------------------------------------------------------------- /addons/script_spliter/io/backward_mouse_button.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="InputEventMouseButton" format=3 uid="uid://bwpahdvr80ivr"] 2 | 3 | [resource] 4 | device = -1 5 | button_index = 8 6 | -------------------------------------------------------------------------------- /addons/script_spliter/io/forward_key_button.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="InputEventKey" format=3 uid="uid://b43ac78k4ox2a"] 2 | 3 | [resource] 4 | alt_pressed = true 5 | physical_keycode = 4194321 6 | -------------------------------------------------------------------------------- /addons/script_spliter/io/forward_mouse_button.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="InputEventMouseButton" format=3 uid="uid://bs1lk5ids0s01"] 2 | 3 | [resource] 4 | button_index = 9 5 | -------------------------------------------------------------------------------- /addons/script_spliter/plugin.cfg: -------------------------------------------------------------------------------- 1 | [plugin] 2 | 3 | name="Script Spliter" 4 | description="Tool Addon for godot 4 5 | Allow split script window." 6 | author="Twister" 7 | version="0.3.5.4" 8 | github="https://github.com/CodeNameTwister/Script-Spliter" 9 | script="plugin.gd" 10 | -------------------------------------------------------------------------------- /addons/script_spliter/plugin.gd: -------------------------------------------------------------------------------- 1 | @tool 2 | extends EditorPlugin 3 | # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # 4 | # Script Spliter 5 | # https://github.com/CodeNameTwister/Script-Spliter 6 | # 7 | # Script Spliter addon for godot 4 8 | # author: "Twister" 9 | # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # 10 | 11 | const BUILDER : Script = preload("res://addons/script_spliter/core/builder.gd") 12 | const CONTEXT : Script = preload("res://addons/script_spliter/context/context_window.gd") 13 | 14 | const CMD_MENU_TOOL : String = "Script Spliter" 15 | 16 | #CONTEXT 17 | const ICON_ADD_COLUMN : Texture = preload("res://addons/script_spliter/context/icons/split_cplus.svg") 18 | const ICON_REMOVE_COLUMN : Texture = preload("res://addons/script_spliter/context/icons/split_cminus.svg") 19 | const ICON_ADD_ROW : Texture = preload("res://addons/script_spliter/context/icons/split_rplus.svg") 20 | const ICON_REMOVE_ROW : Texture = preload("res://addons/script_spliter/context/icons/split_rminus.svg") 21 | const ICON_FLOATING : Texture = preload("res://addons/script_spliter/context/icons/atop.png") 22 | 23 | var _rmb_editor_add_split : EditorContextMenuPlugin = null 24 | var _rmb_editor_remove_split: EditorContextMenuPlugin = null 25 | var _rmb_editor_code_add_split : EditorContextMenuPlugin = null 26 | var _rmb_editor_code_remove_split : EditorContextMenuPlugin = null 27 | var _rmb_editor_pop_script : EditorContextMenuPlugin = null 28 | var _rmb_editor_code_pop_script : EditorContextMenuPlugin = null 29 | 30 | var _menu_split_selector : Window = null 31 | var _builder : Object = null 32 | 33 | var _daemon_chaser : Node = null 34 | 35 | #region _REF_ 36 | var _tab_container : Node = null: 37 | get: 38 | if !is_instance_valid(_tab_container): 39 | var script_editor: ScriptEditor = EditorInterface.get_script_editor() 40 | _tab_container = find(script_editor, "*", "TabContainer") 41 | return _tab_container 42 | 43 | var _item_list : Node = null: 44 | get: 45 | if !is_instance_valid(_item_list): 46 | var script_editor: ScriptEditor = EditorInterface.get_script_editor() 47 | _item_list = find(script_editor, "*", "ItemList") 48 | return _item_list 49 | #endregion 50 | 51 | #region _USER_BUFFER_ 52 | var _rows : int = 0: 53 | set(e): 54 | _rows = maxi(e, 0) 55 | var _columns : int = 0: 56 | set(e): 57 | _columns = maxi(e, 0) 58 | var _refresh_warnings_on_save : bool = true 59 | #endregion 60 | 61 | var _frm : int = 0 62 | var _d_chase : bool = false 63 | 64 | func get_builder() -> Object: 65 | return _builder 66 | 67 | func find(root : Node, pattern : String, type : String) -> Node: 68 | var e : Array[Node] = root.find_children(pattern, type, true, false) 69 | if e.size() > 0: 70 | return e[0] 71 | return null 72 | 73 | func get_split_rows() -> int: 74 | return _rows 75 | 76 | func get_split_columns() -> int: 77 | return _columns 78 | 79 | func _on_save(res : Resource) -> void: 80 | if res is Script: 81 | _save_external_data() 82 | 83 | func _save_external_data() -> void: 84 | if _d_chase == true: 85 | return 86 | _d_chase = true 87 | if _refresh_warnings_on_save and is_instance_valid(_builder): 88 | if _daemon_chaser == null: 89 | _daemon_chaser = ResourceLoader.load("res://addons/script_spliter/core/DaemonChaser.gd").new() 90 | add_child(_daemon_chaser) 91 | _daemon_chaser.set_current_index(_builder.get_current_focus_index()) 92 | _daemon_chaser.buffer = _builder.get_focus_config() 93 | _builder.enable_focus_highlight(false) 94 | _daemon_chaser.run(_builder.focus_by_index, _builder.set_focus_config) 95 | set_deferred(&"_d_chase", false) 96 | 97 | func _process(__: float) -> void: 98 | if _frm < 2: 99 | _frm += 1 100 | return 101 | _frm = 0 102 | set_process(false) 103 | if is_instance_valid(_builder): 104 | _builder.update() 105 | 106 | func _on_change_settings() -> void: 107 | if is_instance_valid(_builder): 108 | _builder.update_config() 109 | var settings : EditorSettings = EditorInterface.get_editor_settings() 110 | var changes : PackedStringArray = settings.get_changed_settings() 111 | 112 | if &"plugin/script_spliter/behaviour/refresh_warnings_on_save" in changes: 113 | _refresh_warnings_on_save = settings.get_setting(&"plugin/script_spliter/behaviour/refresh_warnings_on_save") 114 | 115 | func _init() -> void: 116 | var o : Object = _tab_container 117 | if o == null: 118 | #push_warning("[Script-Spliter] 0x000A") 119 | return 120 | o = _item_list 121 | if o == null: 122 | #push_warning("[Script-Spliter] 0x000B") 123 | return 124 | 125 | func _run() -> void: 126 | if is_instance_valid(_builder): 127 | var settings : EditorSettings = EditorInterface.get_editor_settings() 128 | var scripts_tab_container : Node = _tab_container 129 | 130 | if !scripts_tab_container: 131 | push_warning("[Script-Spliter] 0x000A Error can not find editor reference!") 132 | return 133 | 134 | var il : Node = _item_list 135 | if null != il: 136 | _builder.set_item_list(il) 137 | else: 138 | push_warning("[Script-Spliter] 0x000B Error can not find editor reference!") 139 | return 140 | 141 | if !scripts_tab_container.is_node_ready(): 142 | await scripts_tab_container.ready 143 | if !is_instance_valid(scripts_tab_container): 144 | push_error("Unspected error reference be replace or free it, can not run plugin!") 145 | return 146 | 147 | settings.settings_changed.connect(_on_change_settings) 148 | 149 | _builder.init_1() 150 | _builder.build(scripts_tab_container, _columns, _rows) 151 | set_process_input(true) 152 | 153 | func set_type_split(columns : int, rows : int) -> void: 154 | _columns = columns 155 | _rows = rows 156 | 157 | var str_columns : String = str(maxi(_columns, 1)) 158 | var str_rows : String = str(maxi(rows, 1)) 159 | 160 | print("[{0}] {1} {2}: > {3} {5} - {4} {6}".format( 161 | [ 162 | _get_translated_text("INFO"), 163 | _get_translated_text("Setting"), 164 | _get_translated_text("To"), 165 | _get_translated_text("Columns"), 166 | _get_translated_text("Rows"), 167 | str_columns, 168 | str_rows 169 | ]) ) 170 | 171 | if is_instance_valid(_builder): 172 | _builder.update_build(columns, rows) 173 | 174 | func _exit_tree() -> void: 175 | remove_tool_menu_item(CMD_MENU_TOOL) 176 | _setup(0) 177 | 178 | if is_instance_valid(_builder): 179 | _builder.init_0() 180 | _builder.free.call_deferred() 181 | 182 | var settings : EditorSettings = EditorInterface.get_editor_settings() 183 | if settings.settings_changed.is_connected(_on_change_settings): 184 | settings.settings_changed.disconnect(_on_change_settings) 185 | 186 | if is_instance_valid(_daemon_chaser) and !_daemon_chaser.is_queued_for_deletion(): 187 | _daemon_chaser.queue_free() 188 | 189 | func _get_translated_text(text : String) -> String: 190 | # TODO: Translation 191 | return text 192 | 193 | func swap(caller : Object) -> void: 194 | if is_instance_valid(_builder): 195 | _builder.swap(caller) 196 | 197 | func _setup(input : int) -> void: 198 | var settings : EditorSettings = EditorInterface.get_editor_settings() 199 | 200 | if input != 0: 201 | add_to_group(&"ScriptSpliter") 202 | 203 | main_screen_changed.connect(_on_change) 204 | resource_saved.connect(_on_save) 205 | 206 | var ctx_add_column : String = _get_translated_text("ADD_SPLIT").capitalize() 207 | var ctx_remove_split : String = _get_translated_text("REMOVE_SPLIT").capitalize() 208 | var ctx_pop_script : String = _get_translated_text("MAKE_FLOATING_SCRIPT").capitalize() 209 | 210 | #SETUP 211 | _rmb_editor_add_split = CONTEXT.new(ctx_add_column, _add_window_split, _can_add_split, ICON_ADD_COLUMN) 212 | _rmb_editor_remove_split = CONTEXT.new(ctx_remove_split, _remove_window_split, _can_remove_split, ICON_REMOVE_COLUMN) 213 | 214 | _rmb_editor_code_add_split = CONTEXT.new(ctx_add_column, _add_window_split, _can_add_split, ICON_ADD_COLUMN) 215 | _rmb_editor_code_remove_split = CONTEXT.new(ctx_remove_split, _remove_window_split, _can_remove_split, ICON_REMOVE_COLUMN) 216 | 217 | _rmb_editor_pop_script = CONTEXT.new(ctx_pop_script, _make_pop_script, _can_make_pop_script, ICON_FLOATING) 218 | _rmb_editor_code_pop_script = CONTEXT.new(ctx_pop_script, _make_pop_script, _can_make_pop_script, ICON_FLOATING) 219 | 220 | add_context_menu_plugin(EditorContextMenuPlugin.CONTEXT_SLOT_SCRIPT_EDITOR, _rmb_editor_add_split) 221 | add_context_menu_plugin(EditorContextMenuPlugin.CONTEXT_SLOT_SCRIPT_EDITOR, _rmb_editor_remove_split) 222 | 223 | add_context_menu_plugin(EditorContextMenuPlugin.CONTEXT_SLOT_SCRIPT_EDITOR_CODE, _rmb_editor_code_add_split) 224 | add_context_menu_plugin(EditorContextMenuPlugin.CONTEXT_SLOT_SCRIPT_EDITOR_CODE, _rmb_editor_code_remove_split) 225 | 226 | add_context_menu_plugin(EditorContextMenuPlugin.CONTEXT_SLOT_SCRIPT_EDITOR, _rmb_editor_pop_script) 227 | add_context_menu_plugin(EditorContextMenuPlugin.CONTEXT_SLOT_SCRIPT_EDITOR_CODE, _rmb_editor_code_pop_script) 228 | 229 | if !settings.has_setting(&"plugin/script_spliter/rows"): 230 | settings.set_setting(&"plugin/script_spliter/rows", _rows) 231 | else: 232 | _rows = settings.get_setting(&"plugin/script_spliter/rows") 233 | if !settings.has_setting(&"plugin/script_spliter/columns"): 234 | settings.set_setting(&"plugin/script_spliter/columns", _columns) 235 | else: 236 | _columns = settings.get_setting(&"plugin/script_spliter/columns") 237 | if !settings.has_setting(&"plugin/script_spliter/save_rows_columns_count_on_exit"): 238 | settings.set_setting(&"plugin/script_spliter/save_rows_columns_count_on_exit", false) 239 | if !settings.has_setting(&"plugin/script_spliter/behaviour/refresh_warnings_on_save"): 240 | settings.set_setting(&"plugin/script_spliter/behaviour/refresh_warnings_on_save", _refresh_warnings_on_save) 241 | else: 242 | _refresh_warnings_on_save = settings.get_setting(&"plugin/script_spliter/behaviour/refresh_warnings_on_save") 243 | else: 244 | if is_in_group(&"ScriptSpliter"): 245 | remove_from_group(&"ScriptSpliter") 246 | 247 | main_screen_changed.disconnect(_on_change) 248 | resource_saved.disconnect(_on_save) 249 | 250 | if is_instance_valid(_rmb_editor_add_split): 251 | remove_context_menu_plugin(_rmb_editor_add_split) 252 | if is_instance_valid(_rmb_editor_remove_split): 253 | remove_context_menu_plugin(_rmb_editor_remove_split) 254 | if is_instance_valid(_rmb_editor_code_add_split): 255 | remove_context_menu_plugin(_rmb_editor_code_add_split) 256 | if is_instance_valid(_rmb_editor_code_remove_split): 257 | remove_context_menu_plugin(_rmb_editor_code_remove_split) 258 | if is_instance_valid(_rmb_editor_pop_script): 259 | remove_context_menu_plugin(_rmb_editor_pop_script) 260 | if is_instance_valid(_rmb_editor_code_pop_script): 261 | remove_context_menu_plugin(_rmb_editor_code_pop_script) 262 | 263 | 264 | if settings.has_setting(&"plugin/script_spliter/save_rows_columns_count_on_exit"): 265 | if settings.get_setting(&"plugin/script_spliter/save_rows_columns_count_on_exit") == true: 266 | settings.set_setting(&"plugin/script_spliter/rows", _rows) 267 | settings.set_setting(&"plugin/script_spliter/columns", _columns) 268 | 269 | func _can_add_split(path : PackedStringArray) -> bool: 270 | if !is_instance_valid(_builder): 271 | return false 272 | if path.size() == 0: 273 | return _builder.can_add_split(null) 274 | else: 275 | for x : String in path: 276 | if x.begins_with("res://"): 277 | var sc : ScriptEditor = EditorInterface.get_script_editor() 278 | return _builder.can_add_split(sc.get_current_editor().get_base_editor()) 279 | else: 280 | var node : Node = get_node_or_null(x) 281 | if node: 282 | return _builder.can_add_split(node) 283 | else: 284 | var sc : ScriptEditor = EditorInterface.get_script_editor() 285 | return _builder.can_add_split(sc.get_current_editor().get_base_editor()) 286 | return false 287 | 288 | func _can_remove_split(path : PackedStringArray) -> bool: 289 | if !is_instance_valid(_builder): 290 | return false 291 | if path.size() == 0: 292 | return _builder.can_remove_split(null) 293 | else: 294 | for x : String in path: 295 | if x.begins_with("res://"): 296 | var sc : ScriptEditor = EditorInterface.get_script_editor() 297 | return _builder.can_remove_split(sc.get_current_editor().get_base_editor()) 298 | else: 299 | var node : Node = get_node_or_null(x) 300 | if node: 301 | return _builder.can_remove_split(node) 302 | else: 303 | var sc : ScriptEditor = EditorInterface.get_script_editor() 304 | return _builder.can_remove_split(sc.get_current_editor().get_base_editor()) 305 | return false 306 | 307 | func _add_window_split(variant : Variant) -> void: 308 | var control : Control = null 309 | if variant is Script: 310 | var sc : ScriptEditor = EditorInterface.get_script_editor() 311 | if variant == sc.get_current_script(): 312 | control = sc.get_current_editor().get_base_editor() 313 | else: 314 | var c : ScriptEditorBase = sc.get_current_editor() 315 | if c: 316 | control = c.get_base_editor() 317 | elif variant is CodeEdit: 318 | control = variant 319 | if is_instance_valid(control): 320 | _builder.add_split(control) 321 | 322 | func _remove_window_split(variant : Variant) -> void: 323 | var control : Control = null 324 | if variant is Script: 325 | var sc : ScriptEditor = EditorInterface.get_script_editor() 326 | if variant == sc.get_current_script(): 327 | control = sc.get_current_editor().get_base_editor() 328 | else: 329 | var c : ScriptEditorBase = sc.get_current_editor() 330 | if c: 331 | control = c.get_base_editor() 332 | elif variant is CodeEdit: 333 | control = variant 334 | if is_instance_valid(control): 335 | _builder.remove_split(control) 336 | 337 | func _make_pop_script(variant : Variant) -> void: 338 | var control : Control = null 339 | if variant is Script: 340 | var sc : ScriptEditor = EditorInterface.get_script_editor() 341 | var arr : Array[ScriptEditorBase] = sc.get_open_script_editors() 342 | var scs : Array[Script] = sc.get_open_scripts() 343 | if arr.size() == scs.size(): 344 | for y : int in range(0, scs.size(), 1): 345 | if scs[y] == variant: 346 | control = arr[y].get_base_editor() 347 | break 348 | if variant is CodeEdit: 349 | control = variant 350 | if is_instance_valid(control): 351 | _builder.make_pop_script(control) 352 | 353 | func _can_make_pop_script(path : PackedStringArray) -> bool: 354 | if !is_instance_valid(_builder): 355 | return false 356 | for x : String in path: 357 | var node : Node = get_node_or_null(x) 358 | if node: 359 | return !_builder.is_pop_script(node) 360 | return false 361 | 362 | func _on_change(screen_name : String) -> void: 363 | if screen_name == "Script": 364 | if is_instance_valid(_builder): 365 | _builder.update_rect.call_deferred() 366 | 367 | 368 | func _enter_tree() -> void: 369 | _setup(1) 370 | if !is_instance_valid(_builder): 371 | _builder = BUILDER.new(self) 372 | add_tool_menu_item(CMD_MENU_TOOL, _on_tool_command) 373 | 374 | func _on_tool_command() -> void: 375 | if is_instance_valid(_builder): 376 | var data : Array[int] = _builder.get_current_columns_and_rows() 377 | _columns = data[0] 378 | _rows = data[1] 379 | 380 | if !is_instance_valid(_menu_split_selector): 381 | _menu_split_selector = (ResourceLoader.load("res://addons/script_spliter/context/menu_tool.tscn") as PackedScene).instantiate() 382 | _menu_split_selector.set_plugin(self) 383 | _menu_split_selector.visible = false 384 | add_child(_menu_split_selector) 385 | _menu_split_selector.popup_centered.call_deferred() 386 | 387 | func _ready() -> void: 388 | set_process(false) 389 | set_process_input(false) 390 | if !get_tree().root.is_node_ready(): 391 | await get_tree().root.ready 392 | for __ : int in range(2): 393 | await get_tree().process_frame 394 | _run() 395 | 396 | func _notification(what: int) -> void: 397 | if what == NOTIFICATION_PREDELETE: 398 | if is_instance_valid(_builder) and !_builder.is_queued_for_deletion(): 399 | _builder.init_0() 400 | _builder.free() 401 | 402 | func _input(event: InputEvent) -> void: 403 | if event is InputEventKey: 404 | if event.pressed and event.ctrl_pressed: 405 | if event.keycode == 49: 406 | set_type_split(0, 0) 407 | elif event.keycode == 50: 408 | set_type_split(2, 1) 409 | elif event.keycode == 51: 410 | set_type_split(1, 2) 411 | elif event.keycode == 52: 412 | set_type_split(3, 1) 413 | elif event.keycode == 53: 414 | set_type_split(1, 3) 415 | elif event.keycode == 54: 416 | set_type_split(2, 2) 417 | -------------------------------------------------------------------------------- /addons/script_spliter/plugin.gd.uid: -------------------------------------------------------------------------------- 1 | uid://dwmaoslxt1uop 2 | -------------------------------------------------------------------------------- /images/img0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeNameTwister/Script-Spliter/8312d5b0eb2b24c85c669d5f9b4092ae518dc8da/images/img0.png -------------------------------------------------------------------------------- /images/img1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeNameTwister/Script-Spliter/8312d5b0eb2b24c85c669d5f9b4092ae518dc8da/images/img1.png -------------------------------------------------------------------------------- /images/img2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeNameTwister/Script-Spliter/8312d5b0eb2b24c85c669d5f9b4092ae518dc8da/images/img2.png -------------------------------------------------------------------------------- /images/img3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeNameTwister/Script-Spliter/8312d5b0eb2b24c85c669d5f9b4092ae518dc8da/images/img3.png --------------------------------------------------------------------------------